C#循环调用SendInput导致鼠标移动异常的问题排查与解决
问题分析与解决方案
异常原因
- 游标位置读取延迟:在循环内调用
Cursor.Position时,Windows可能尚未处理完上一次SendInput发送的输入指令,导致读取到的是过时的游标位置。基于这个旧位置计算新坐标,会导致重复发送相同的移动指令,或产生累积误差,最终表现为移动距离不足、方向偏移。 - 绝对坐标计算精度问题:当前代码使用
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
相关产品推荐
相关产品推荐

