使用JNA调用Windows SendInput实现鼠标移动失效问题排查
你的代码返回result=1说明SendInput调用成功了,但鼠标不动的核心原因是没有正确使用绝对坐标模式,以及坐标值未按Windows要求做归一化处理。
问题拆解
- 坐标模式错误:
MOUSEEVENTF_MOVE默认是相对移动模式,直接传入屏幕像素值(比如1000)不会触发绝对位置移动,必须加上MOUSEEVENTF_ABSOLUTE标志声明绝对坐标。 - 坐标值未归一化:Windows要求
SendInput的绝对坐标dx/dy必须是0-65535之间的数值(对应屏幕左上角到右下角的范围),直接传像素值无效。 - 不必要的装箱类型:参数用
Long装箱类型会额外创建对象,改用基本类型long更高效。
修正后的代码
import com.sun.jna.platform.win32.User32; import com.sun.jna.platform.win32.WinDef.DWORD; import com.sun.jna.platform.win32.WinDef.LONG; import com.sun.jna.platform.win32.WinUser.INPUT; import static com.sun.jna.platform.win32.WinUser.INPUT.INPUT_MOUSE; import static com.sun.jna.platform.win32.WinUser.MOUSEEVENTF_MOVE; import static com.sun.jna.platform.win32.WinUser.MOUSEEVENTF_ABSOLUTE; public class Test { public static void main(String[] a) { // 示例:移动到屏幕(1000, 1000)的像素位置 moveMouse(1000, 1000); } /** * @param x 目标屏幕X像素坐标 * @param y 目标屏幕Y像素坐标 */ public static void moveMouse(long x, long y) { // 获取当前屏幕分辨率 int screenWidth = User32.INSTANCE.GetSystemMetrics(0); // SM_CXSCREEN int screenHeight = User32.INSTANCE.GetSystemMetrics(1); // SM_CYSCREEN // 将像素坐标转换为SendInput要求的0-65535范围的绝对坐标 long normalizedX = (x * 65535L) / screenWidth; long normalizedY = (y * 65535L) / screenHeight; INPUT input = new INPUT(); input.type = new DWORD(INPUT_MOUSE); input.input.mi.dx = new LONG(normalizedX); input.input.mi.dy = new LONG(normalizedY); input.input.mi.time = new DWORD(0); // 同时设置移动标志和绝对坐标标志 input.input.mi.dwFlags = new DWORD(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE); INPUT[] inputArray = {input}; // input.size()对应C++里的sizeof(INPUT),是单个结构体的字节大小,此用法正确 DWORD result = User32.INSTANCE.SendInput(new DWORD(1), inputArray, input.size()); System.out.println("result = " + result.longValue()); System.out.println("size = " + input.size()); } }
额外说明
- 如果需要相对移动(比如相对于当前位置偏移N像素),去掉
MOUSEEVENTF_ABSOLUTE标志,直接传入正负偏移值即可,但注意系统鼠标加速可能影响实际移动距离。 SendInput的第三个参数确实是单个INPUT结构体的大小,和数组无关,你之前的input.size()用法是正确的,无需纠结数组字节数。
内容的提问来源于stack exchange,提问作者Vaishnav Kanhirathingal
相关产品推荐
相关产品推荐

