使用SendInput设置鼠标绝对位置出现漂移问题该如何解决
问题原因
- 缺少
MOUSEEVENTF_VIRTUALDESKTOP标志:默认情况下SendInput的绝对鼠标坐标仅映射到主显示器,多屏环境下要加这个标志才能适配整个虚拟桌面坐标系 - 硬编码的分辨率基准错误:你当前用2560/1440作为归一化基准,但双屏左右排列的虚拟桌面总宽度是5120,x坐标范围从0到5119,换算基准不匹配就会出现坐标偏移
- 整数除法精度丢失:反复循环下,整数除法的截断误差会不断累积,最终表现为鼠标持续漂移
- 结构体未完全初始化:
INPUT结构体的mi.mouseData等字段未赋值,残留的随机值可能引发未知异常
修正后的代码
// 先获取虚拟桌面全局参数,不要硬编码分辨率 int virtualScreenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN); int virtualScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN); int virtualScreenLeft = GetSystemMetrics(SM_XVIRTUALSCREEN); int virtualScreenTop = GetSystemMetrics(SM_YVIRTUALSCREEN); for(;;) { // 获取鼠标坐标 POINT Point; GetCursorPos(&Point); // 初始化INPUT结构体全为0,避免未初始化字段异常 INPUT Input = {0}; Input.type = INPUT_MOUSE; // 坐标转换:先把屏幕坐标转为相对虚拟桌面左上角的偏移,再做归一化,用浮点数避免精度损失 Input.mi.dx = (LONG)(((Point.x - virtualScreenLeft) * 65535.0) / (virtualScreenWidth - 1)); Input.mi.dy = (LONG)(((Point.y - virtualScreenTop) * 65535.0) / (virtualScreenHeight - 1)); // 新增MOUSEEVENTF_VIRTUALDESKTOP标志支持多屏 Input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_VIRTUALDESKTOP; Input.mi.time = 0; Input.mi.dwExtraInfo = 0; SendInput(1, &Input, sizeof(INPUT)); usleep(15000); }
关键修改说明
- 用
GetSystemMetrics获取虚拟桌面参数,自动适配任意多屏布局、任意分辨率,不需要手动修改硬编码值 - 归一化运算使用
65535.0浮点数计算,最后再转整数,避免了整数除法的截断误差,循环运行不会出现累积漂移 - 增加
MOUSEEVENTF_VIRTUALDESKTOP后,坐标会正确映射到整个多屏桌面,不会出现跨屏坐标错乱的问题
内容的提问来源于stack exchange,提问作者rphii
相关产品推荐
相关产品推荐

