我正在尝试学习如何使用Java和JNA(Java Native Access)与Windows API进行交互,但我正处于障碍之中。我试图通过在鼠标输入流上排队鼠标事件来使鼠标做某事,并且代码有效,因为SendInput(...)
方法返回1表明它已成功排队事件,但鼠标本身什么也没做。
我的SSCCE:
编辑编辑以填写dwFlags字段。我已经尝试了几种常量组合,无论是自己还是比特或组合都没有成功。同样,SendInput方法返回1,因为它应该建议一个正常运行的方法,但鼠标不会让步:
import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinDef.*;
import com.sun.jna.platform.win32.WinUser.*;
import com.sun.jna.win32.StdCallLibrary;
public class MouseUtils {
public interface User32 extends StdCallLibrary {
public static final long MOUSEEVENTF_MOVE = 0x0001L;
public static final long MOUSEEVENTF_VIRTUALDESK = 0x4000L;
public static final long MOUSEEVENTF_ABSOLUTE = 0x8000L;
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
DWORD SendInput(DWORD dWord, INPUT[] input, int cbSize);
}
public static void main(String[] args) {
INPUT input = new INPUT();
input.type = new DWORD(INPUT.INPUT_MOUSE);
input.input.mi.dx = new LONG(500);
input.input.mi.dy = new LONG(500);
input.input.mi.mouseData = new DWORD(0);
input.input.mi.dwFlags = new DWORD(User32.MOUSEEVENTF_MOVE
| User32.MOUSEEVENTF_VIRTUALDESK | User32.MOUSEEVENTF_ABSOLUTE);
// input.input.mi.dwFlags = new DWORD(0x8000L);
input.input.mi.time = new DWORD(0);
INPUT[] inArray = {input};
int cbSize = input.size(); // mouse input struct size
DWORD nInputs = new DWORD(1); // number of inputs
DWORD result = User32.INSTANCE.SendInput(nInputs , inArray, cbSize);
System.out.println("result: " + result); // return 1 if the 1 event successfully inserted
}
}
编辑2:
做更多的阅读,似乎我对使用JNA的数组的理解是有缺陷的,我必须考虑C数组,其中数组只是指向连续内存区域的指针。更多内容(我希望!)。
答案 0 :(得分:10)
JNA文件Using Structures And Unions上写着:
联合通常可以与Structures互换,但要求您在使用
setType
方法指示哪个联合字段处于活动状态,然后才能正确传递给函数调用。
我猜你错过了setType
部分。此外,使用MOUSEEVENTF_ABSOLUTE
时,dx
和dy
被指定为鼠标的坐标,而不是像素。
以下作品:
public interface User32 extends StdCallLibrary {
...
public static final int SM_CXSCREEN = 0x0;
public static final int SM_CYSCREEN = 0x1;
int GetSystemMetrics(int index);
}
public static void main(String[] args) {
...
input.input.setType("mi");
input.input.mi.dx = new LONG(500 * 65536 / User32.INSTANCE.GetSystemMetrics(User32.SM_CXSCREEN));
input.input.mi.dy = new LONG(500 * 65536 / User32.INSTANCE.GetSystemMetrics(User32.SM_CYSCREEN));
...
}
答案 1 :(得分:3)
调用结构上的toArray()方法以获取连续的内存块。
INPUT input = new INPUT();
INPUT[] arg = (INPUT[])input.toArray(1);
或者,您可以简单地为SendInput声明替代方法映射:
DWORD SendInput(int nInputs, INPUT pInputs, int cbSize);
然而,可能还有其他事情(权限,也许?请参阅关于UIPI的MS说明),因为您的示例应该工作(至少使用单个数组元素)。
编辑:Union.setType()答案确实是正确答案。
答案 2 :(得分:2)
input.input.mi.dwFlags = new DWORD(0);
您没有指定任何鼠标输入标志,因此没有鼠标输入。