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

C#循环调用SendInput导致鼠标移动异常的问题排查与解决

问题分析与解决方案

异常原因

  1. 游标位置读取延迟:在循环内调用Cursor.Position时,Windows可能尚未处理完上一次SendInput发送的输入指令,导致读取到的是过时的游标位置。基于这个旧位置计算新坐标,会导致重复发送相同的移动指令,或产生累积误差,最终表现为移动距离不足、方向偏移。
  2. 绝对坐标计算精度问题:当前代码使用65536作为归一化系数,但根据微软官方文档,SendInput的绝对坐标范围应为0-65535,使用65536可能在边缘场景下导致坐标溢出或映射错误。

解决方法

方法1:手动追踪游标位置

放弃在循环内读取系统游标位置,而是自行维护当前坐标值,确保每次发送的绝对坐标是连续且准确的,与正常案例的逻辑一致。

// 初始化当前位置
int currentX = Cursor.Position.X;
int currentY = Cursor.Position.Y;
const int MOVESPACE = 1;

for (int i = 0; i < 100; i++)
{
    currentX += MOVESPACE;
    Simulator.MouseSimulator.MoveMouse((ushort)currentX, (ushort)currentY, SCREENWIDTH, SCREENHEIGHT);
    Thread.Sleep(2);
}

方法2:使用相对移动模式

避免绝对坐标的计算,直接发送相对移动指令,无需依赖游标位置读取。

首先在MouseSimulator类中添加相对移动方法:

public static uint MoveMouseRelative(int deltaX, int deltaY)
{
    MOUSEINPUT mouseInput = new MOUSEINPUT();
    mouseInput.dx = deltaX;
    mouseInput.dy = deltaY;
    mouseInput.dwFlags = (uint)MouseEventFlags.MOVE; // 移除ABSOLUTE标志
    mouseInput.time = 0;
    mouseInput.dwExtraInfo = IntPtr.Zero;

    InputUnion union = new InputUnion();
    union.mi = mouseInput;

    INPUT[] input = new INPUT[1];
    input[0].type = (uint)InputTypes.MOUSE;
    input[0].U = union;

    return SendInput(1, input, Marshal.SizeOf(typeof(INPUT)));
}

然后在循环中调用:

const int MOVESPACE = 1;
for (int i = 0; i < 100; i++)
{
    Simulator.MouseSimulator.MoveMouseRelative(MOVESPACE, 0);
    Thread.Sleep(2);
}

方法3:修正绝对坐标归一化系数

将MouseSimulator类中的归一化常量从65536改为65535,符合官方文档要求:

private const double LEN = 65535; // 原数值为65536

额外调试建议

每次调用SendInput后检查返回值,若返回0表示指令发送失败,可通过Marshal.GetLastWin32Error()获取具体错误码排查问题:

uint result = Simulator.MouseSimulator.MoveMouse(...);
if (result == 0)
{
    int errorCode = Marshal.GetLastWin32Error();
    // 处理错误逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 04:57:02