You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于C#实现类TeamViewer远程鼠标控制技术咨询(已完成屏幕共享)

实现C#远程鼠标控制的分步方案

我之前做过类似的远程控制工具,正好可以给你分享下实现远程鼠标控制的核心步骤,结合你已经有屏幕共享基础的情况,重点放在鼠标事件捕获、数据传输、被控端模拟操作这三块:

一、控制端捕获鼠标事件并转换坐标

首先你需要在控制端的屏幕显示窗口上监听鼠标动作,这里要注意的是:控制端显示的被控端屏幕大概率是缩放后的,所以得把控制端的鼠标相对坐标转换成被控端的绝对屏幕坐标。

举个WinForms的例子:

// 假设controlScreen是显示被控端屏幕的PictureBox
private void controlScreen_MouseMove(object sender, MouseEventArgs e)
{
    // 先获取被控端的实际屏幕分辨率(你已经掌握被控端信息,这里直接用已知值)
    int remoteScreenWidth = 1920;
    int remoteScreenHeight = 1080;

    // 计算控制端窗口中显示的屏幕缩放比例
    float scaleX = (float)remoteScreenWidth / controlScreen.Width;
    float scaleY = (float)remoteScreenHeight / controlScreen.Height;

    // 转换为被控端的绝对坐标
    int remoteX = (int)(e.X * scaleX);
    int remoteY = (int)(e.Y * scaleY);

    // 打包鼠标移动命令,准备发送
    SendMouseCommand(new MouseCommand { CommandType = MouseCommandType.Move, X = remoteX, Y = remoteY });
}

// 监听鼠标点击事件
private void controlScreen_MouseDown(object sender, MouseEventArgs e)
{
    // 同样先转换坐标,然后发送点击命令
    // ...(坐标转换逻辑同上)
    MouseButton button = e.Button == MouseButtons.Left ? MouseButton.Left : MouseButton.Right;
    SendMouseCommand(new MouseCommand { CommandType = MouseCommandType.Down, Button = button, X = remoteX, Y = remoteY });
}

private void controlScreen_MouseUp(object sender, MouseEventArgs e)
{
    // 发送松开命令
    // ...(坐标转换逻辑同上)
    MouseButton button = e.Button == MouseButtons.Left ? MouseButton.Left : MouseButton.Right;
    SendMouseCommand(new MouseCommand { CommandType = MouseCommandType.Up, Button = button, X = remoteX, Y = remoteY });
}

这里我定义了一个简单的命令结构体来统一传输格式:

public enum MouseCommandType
{
    Move,
    Down,
    Up
}

public enum MouseButton
{
    Left,
    Right
}

public class MouseCommand
{
    public MouseCommandType CommandType { get; set; }
    public MouseButton Button { get; set; }
    public int X { get; set; }
    public int Y { get; set; }
}

二、复用现有通信通道传输命令

既然你已经实现了屏幕共享,肯定已经有了控制端和被控端之间的通信连接(比如TCP Socket),直接把序列化后的MouseCommand通过这个通道发送就行。可以用JSON序列化(比如Newtonsoft.Json)或者二进制序列化,前者更易调试:

private void SendMouseCommand(MouseCommand command)
{
    // 假设socket是已建立的TCP连接
    string json = JsonConvert.SerializeObject(command);
    byte[] data = Encoding.UTF8.GetBytes(json);
    socket.Send(data);
}

三、被控端接收命令并模拟鼠标操作

这一步核心是调用Windows API来模拟鼠标动作,推荐用SendInput函数(mouse_event已经被标记为过时)。首先需要导入user32.dll的相关函数:

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public struct INPUT
{
    public uint Type;
    public MOUSEINPUT MouseInput;
}

[StructLayout(LayoutKind.Sequential)]
public struct MOUSEINPUT
{
    public int dx;
    public int dy;
    public uint MouseData;
    public uint dwFlags;
    public uint Time;
    public IntPtr ExtraInfo;
}

[DllImport("user32.dll", SetLastError = true)]
private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

// 鼠标操作的Flag常量
private const uint MOUSEEVENTF_MOVE = 0x0001;
private const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
private const uint MOUSEEVENTF_LEFTUP = 0x0004;
private const uint MOUSEEVENTF_RIGHTDOWN = 0x0008;
private const uint MOUSEEVENTF_RIGHTUP = 0x0010;
private const uint MOUSEEVENTF_ABSOLUTE = 0x8000;

然后编写处理命令的逻辑:

private void HandleMouseCommand(MouseCommand command)
{
    switch (command.CommandType)
    {
        case MouseCommandType.Move:
            // SendInput的坐标是0-65535的绝对范围,需要转换
            int absoluteX = (command.X * 65535) / Screen.PrimaryScreen.Bounds.Width;
            int absoluteY = (command.Y * 65535) / Screen.PrimaryScreen.Bounds.Height;

            INPUT[] moveInput = new INPUT[1];
            moveInput[0].Type = 0; // 0表示鼠标输入
            moveInput[0].MouseInput.dx = absoluteX;
            moveInput[0].MouseInput.dy = absoluteY;
            moveInput[0].MouseInput.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;

            SendInput(1, moveInput, Marshal.SizeOf(typeof(INPUT)));
            break;

        case MouseCommandType.Down:
            INPUT[] downInput = new INPUT[1];
            downInput[0].Type = 0;
            downInput[0].MouseInput.dwFlags = command.Button == MouseButton.Left ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN;
            SendInput(1, downInput, Marshal.SizeOf(typeof(INPUT)));
            break;

        case MouseCommandType.Up:
            INPUT[] upInput = new INPUT[1];
            upInput[0].Type = 0;
            upInput[0].MouseInput.dwFlags = command.Button == MouseButton.Left ? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP;
            SendInput(1, upInput, Marshal.SizeOf(typeof(INPUT)));
            break;
    }
}

几个关键注意点

  • 坐标转换准确性:一定要确保被控端的实际屏幕分辨率是正确的,不然鼠标位置会偏移;如果被控端有多个屏幕,还要处理目标屏幕的选择。
  • 权限问题:有些Windows系统(比如Win10/11的管理员账户)可能需要程序以管理员权限运行才能正常模拟鼠标操作,记得在项目属性里设置requireAdministrator。
  • 延迟优化:连续的鼠标移动事件可以合并成一个或者按频率发送(比如每10ms发送一次),避免过多的网络传输导致卡顿。

内容的提问来源于stack exchange,提问作者Alisa456

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:20:15