【发布时间】:2021-03-26 16:53:45
【问题描述】:
编辑:抱歉,我不确定我的问题是否正确关闭。有人建议我thread,但它没有回答我的问题。我能够模拟鼠标点击,但它无法正常工作,正如我在问题中描述的那样。
我仍在学习 JNA 并在我的 Java 应用程序(JNA 5.6.0 和 jna-platform 5.6.0)中使用它,但我希望熟悉的人 Java em>C 语言也可以理解我,因为 JNA 使用的是 WinAPI 函数。我的操作系统是 Windows 10。
我有什么:
- 启动魔兽争霸III游戏的Swing应用程序,运行游戏的exe文件。
- 拦截击键
LowLevelKeyboardProc()并调用click()方法的低级键盘挂钩,如下所述。 - 按下某些坐标的逻辑>keys(如下图所示)。
问题是我无法在游戏窗口的坐标上实现鼠标点击的正确执行。
我想提前声明,我并没有违反游戏许可协议的规则,我只想将它用于旧版本游戏1.26的个人目的。另外,我在其他编程语言中也看到过类似的实现,但我想用 Java 来实现。
下面附上我尝试过的 3 个选项,并附上问题描述:
1。使用User32.INSTANCE.SendMessage()
public void click(KeyBindComponent keyBindComponent) {
final int WM_LBUTTONDOWN = 513;
final int WM_LBUTTONUP = 514;
final int MK_LBUTTON = 0x0001;
Map<String, Integer> cords = getCords(keyBindComponent);
if (!cords.isEmpty()) {
int xCord = cords.get("width");
int yCord = cords.get("height");
LPARAM lParam = makeLParam(xCord, yCord);
user32Library.SendMessage(warcraft3hWnd, WM_LBUTTONDOWN, new WPARAM(MK_LBUTTON), lParam);
user32Library.SendMessage(warcraft3hWnd, WM_LBUTTONUP, new WPARAM(MK_LBUTTON), lParam);
System.out.println("x = " + xCord + " y = " + yCord);
}
}
public static LPARAM makeLParam(int l, int h) {
// note the high word bitmask must include L
return new LPARAM((l & 0xffff) | (h & 0xffffL) << 16);
}
预计会在 test 坐标点(建筑物上)上进行不可见的点击。但是问题是该区域被分配了。我假设执行了以下顺序:在 С当前鼠标位置 向下单击鼠标并将光标移动到 Сoordinate point for click强>。但我不知道为什么会这样。
2.使用User32.INSTANCE.PostMessage()
public void click(KeyBindComponent keyBindComponent) {
final int WM_LBUTTONDOWN = 513;
final int WM_LBUTTONUP = 514;
Map<String, Integer> cords = getCords(keyBindComponent);
if (!cords.isEmpty()) {
int xCord = cords.get("width");
int yCord = cords.get("height");
LPARAM lParam = makeLParam(xCord, yCord);
user32Library.PostMessage(warcraft3hWnd, WM_LBUTTONDOWN, new WPARAM(0), lParam);
user32Library.PostMessage(warcraft3hWnd, WM_LBUTTONUP, new WPARAM(0), lParam);
System.out.println("x = " + xCord + " y = " + yCord);
}
}
public static LPARAM makeLParam(int l, int h) {
// note the high word bitmask must include L
return new LPARAM((l & 0xffff) | (h & 0xffffL) << 16);
}
同样的情况发生了,不是点击坐标,而是选择了区域,还有SendMessage()的情况,大概不会再重新贴两次图了。
3.使用User32.INSTANCE.SendInput()
public void click(KeyBindComponent keyBindComponent) {
Map<String, Integer> cords = getCords(keyBindComponent);
if (!cords.isEmpty()) {
int xCord = cords.get("width");
int yCord = cords.get("height");
mouseMove(xCord, yCord);
mouseClick();
System.out.println("x = " + xCord + " y = " + yCord);
}
}
void mouseMove(int x, int y) {
final int MOUSEEVENTF_LEFTUP = 0x0004;
final int MOUSEEVENTF_ABSOLUTE = 0x8000;
INPUT input = new INPUT();
INPUT[] move = (INPUT[]) input.toArray(2);
// Release the mouse before moving it
move[0].type = new DWORD(INPUT.INPUT_MOUSE);
move[0].input.setType("mi");
move[0].input.mi.dwFlags = new DWORD(MOUSEEVENTF_LEFTUP);
move[0].input.mi.dwExtraInfo = new BaseTSD.ULONG_PTR(0);
move[0].input.mi.time = new DWORD(0);
move[0].input.mi.mouseData = new DWORD(0);
move[1].type = new DWORD(INPUT.INPUT_MOUSE);
move[1].input.mi.dx = new LONG(x);
move[1].input.mi.dy = new LONG(y);
move[1].input.mi.mouseData = new DWORD(0);
move[1].input.mi.dwFlags = new DWORD(MOUSEEVENTF_LEFTUP + MOUSEEVENTF_ABSOLUTE);
user32Library.SendInput(new DWORD(2), move, move[0].size());
}
void mouseClick() {
final int MOUSEEVENTF_LEFTUP = 0x0004;
final int MOUSEEVENTF_LEFTDOWN = 0x0002;
INPUT input = new INPUT();
INPUT[] click = (INPUT[]) input.toArray(2);
click[0].type = new DWORD(INPUT.INPUT_MOUSE);
click[0].input.setType("mi");
click[0].input.mi.dwFlags = new DWORD(MOUSEEVENTF_LEFTDOWN);
click[0].input.mi.dwExtraInfo = new BaseTSD.ULONG_PTR(0);
click[0].input.mi.time = new DWORD(0);
click[0].input.mi.mouseData = new DWORD(0);
click[1].type = new DWORD(INPUT.INPUT_MOUSE);
click[1].input.setType("mi");
click[1].input.mi.dwFlags = new DWORD(MOUSEEVENTF_LEFTUP);
click[1].input.mi.dwExtraInfo = new BaseTSD.ULONG_PTR(0);
click[1].input.mi.time = new DWORD(0);
click[1].input.mi.mouseData = new DWORD(0);
user32Library.SendInput(new DWORD(2), click, click[0].size());
}
在这种情况下,坐标点上根本没有点击。相反,当按下某些键时,鼠标会在当前鼠标位置点击。
顺便说一句,我也尝试过使用 Java Robot,但它对我不起作用。不幸的是,鼠标光标从起始位置移动(消失)了大约一毫秒到您需要单击的点并返回到起始位置。
感谢您阅读到最后,对于如此繁琐的解释,我深表歉意。
谁能告诉我我在代码中犯了什么错误以及在哪里犯了错误?由于在所有 3 个选项中,我都没有达到预期的行为。
【问题讨论】:
-
您的系统(或应用程序)DPI 设置是否设置为默认值以外的设置?
-
@mnistic DPI参数在应用程序中没有变化,系统中也默认配置。如果我们在谈论鼠标,那么我有一个非常简单的旧鼠标,Sven RX-160,分辨率,DPI 800。
-
您有多个分辨率不同的显示器吗?
-
@DanielWiddis 没有,只有一个分辨率为 1920x1080。
-
@DanielWiddis 在我看来,最接近目标的是使用 SendInput () 方法的第三个选项,它执行点击,但不执行移动。也许我错误地实现了 mouseMove() 方法。虽然在 PostMessage 和 SendMessage 方法中我也实现了鼠标的点击和移动,但由于某种原因,移动是在按下按钮时发生的。这就是我猜该区域被选中的原因。