Enigo 多屏幕下鼠标移动问题
enigo = "0.3.0"
该版本下,windows在多屏幕,分辨率不同,含有缩放的情况时,在鼠标移动到其他屏幕再通过程序进行鼠标位移,会导致鼠标移动到角落,无法实现正常的平移功能。
在move_mouse实现中使用的是
// 通过 main_display 获取 w 和 h
let w = unsafe { GetSystemMetrics(SM_CXSCREEN) };
let h = unsafe { GetSystemMetrics(SM_CYSCREEN) };
let w = w as i64 - 1;
let h = h as i64 - 1;
let x = x as i64;
let y = y as i64;
let x = (x * 65535 + w / 2 * x.signum()) / w;
let y = (y * 65535 + h / 2 * y.signum()) / h;
// TODO: Check if we should use MOUSEEVENTF_VIRTUALDESK too
(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, x as i32, y as i32)
// 这里可以看到作者有考虑使用MOUSEEVENTF_VIRTUALDESK这个类型进行鼠标移动
重写move_mouse实现
// 同参考网站中可以看到使用这个类型,可以修复这个问题
fn virtual_screen() -> InputResult<(i32, i32, i32, i32)> {
let x = unsafe { GetSystemMetrics(SM_XVIRTUALSCREEN) }; // 最左边的屏幕X坐标
let y = unsafe { GetSystemMetrics(SM_YVIRTUALSCREEN) }; // 最上边的屏幕Y坐标
let w = unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) }; // 虚拟桌面总宽度
let h = unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) }; // 虚拟桌面总高度
Ok((x, y, w, h))
}
let (virtual_x, virtual_y, virtual_w, virtual_h) = virtual_screen()?;
let x = x as i64;
let y = y as i64;
let w = virtual_w as i64 - 1;
let h = virtual_h as i64 - 1;
// 修正归一化计算,基于整个虚拟桌面
let x = ((x - virtual_x as i64) * 65535 + w / 2 * x.signum()) / w;
let y = ((y - virtual_y as i64) * 65535 + h / 2 * y.signum()) / h;
// 使用 MOUSEEVENTF_VIRTUALDESK,确保鼠标在整个虚拟屏幕内移动
(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK, x as i32, y as i32)
对move_mouse添加一个新的实现或者通过上面的方式进行重写,测试后windows可以正常在多屏幕,缩放和分辨率不同的情况下,正常移动鼠标位置。
参考
How to move the mouse cursor through WinAPI in a multi-monitor setup
文章作者:栗何生
文章链接:https://ronan.ink/archives/enigo-duo-ping-mu-xia-shu-biao-yi-dong-wen-ti
版权声明:本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0 许可协议,转载请注明出处!
评论