Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JNA/WinAPI。模拟鼠标单击而不移动光标';我不能正常工作_Java_C++_C_Winapi_Jna - Fatal编程技术网

Java JNA/WinAPI。模拟鼠标单击而不移动光标';我不能正常工作

Java JNA/WinAPI。模拟鼠标单击而不移动光标';我不能正常工作,java,c++,c,winapi,jna,Java,C++,C,Winapi,Jna,编辑:对不起,我不确定我的问题是否正确结束。有人建议我这样做,但它不能回答我的问题。我能够模拟鼠标点击,但它不能像我在问题中描述的那样正常工作 我仍在学习JNA,并在我的Java应用程序(JNA 5.6.0和JNA平台5.6.0)中使用它,但我希望熟悉C语言的人也能理解我,因为JNA使用的是WinAPI函数。我的操作系统是Windows10 我所拥有的: 启动魔兽争霸III游戏的Swing应用程序运行游戏的exe文件 低级键盘钩子,用于拦截击键低级键盘proc()并调用单击()方法,如下所述

编辑:对不起,我不确定我的问题是否正确结束。有人建议我这样做,但它不能回答我的问题。我能够模拟鼠标点击,但它不能像我在问题中描述的那样正常工作


我仍在学习JNA,并在我的Java应用程序(JNA 5.6.0和JNA平台5.6.0)中使用它,但我希望熟悉C语言的人也能理解我,因为JNA使用的是WinAPI函数。我的操作系统是Windows10

我所拥有的:

  • 启动魔兽争霸III游戏的Swing应用程序运行游戏的exe文件
  • 低级键盘钩子,用于拦截击键
    低级键盘proc()
    并调用
    单击()
    方法,如下所述
  • 在按下某些键后(如下图所示),模拟鼠标点击游戏窗口的坐标(库存、技能和控制位置)的逻辑

问题是我无法在游戏窗口的坐标上正确执行鼠标点击

我想提前说,我没有违反游戏许可协议的规定,我只想在旧版游戏1.26中出于个人目的使用它。另外,我在其他编程语言中也看到过类似的实现,但我想在Java中实现它

下面我附上了我尝试过的3个选项,并对问题进行了描述:

1。使用
User32.INSTANCE.SendMessage()

同样的情况发生了,没有单击坐标,而是选择了该区域,并且在
SendMessage()
的情况下,我可能不会重新附加图片两次

3.使用
User32.INSTANCE.SendInput()

public void单击(KeyBindComponent KeyBindComponent){
映射跳线=获取跳线(键绑定组件);
如果(!cords.isEmpty()){
int xCord=跳线。获取(“宽度”);
int yCord=跳线。获取(“高度”);
mouseMove(xCord,yCord);
鼠标点击();
System.out.println(“x=“+xCord+”y=“+yCord”);
}
}
无效鼠标移动(整数x,整数y){
最终int MOUSEEVENTF_LEFTUP=0x0004;
最终int MOUSEEVENTF_绝对值=0x8000;
输入=新输入();
INPUT[]移动=(INPUT[])INPUT.toArray(2);
//在移动鼠标之前释放鼠标
移动[0]。类型=新DWORD(输入。输入\鼠标);
移动[0].input.setType(“mi”);
移动[0]。input.mi.dwFlags=新的DWORD(MOUSEEVENTF_LEFTUP);
移动[0]。input.mi.dwExtraInfo=new BaseTSD.ULONG_PTR(0);
移动[0]。input.mi.time=新DWORD(0);
移动[0]。input.mi.mouseData=新DWORD(0);
移动[1]。类型=新DWORD(输入。输入\鼠标);
移动[1]。input.mi.dx=新长(x);
移动[1]。input.mi.dy=新长(y);
移动[1]。input.mi.mouseData=新的DWORD(0);
move[1]。input.mi.dwFlags=新的DWORD(MOUSEEVENTF_LEFTUP+MOUSEEVENTF_ABSOLUTE);
user32Library.SendInput(新DWORD(2),move,move[0].size());
}
void mouseClick(){
最终int MOUSEEVENTF_LEFTUP=0x0004;
最终int MOUSEEVENTF_LEFTDOWN=0x0002;
输入=新输入();
INPUT[]点击=(INPUT[])INPUT.toArray(2);
单击[0]。键入=新DWORD(输入。输入\鼠标);
单击[0]。input.setType(“mi”);
单击[0]。input.mi.dwFlags=新DWORD(MOUSEEVENTF_LEFTDOWN);
单击[0]。input.mi.dwExtraInfo=new BaseTSD.ULONG_PTR(0);
单击[0]。input.mi.time=new DWORD(0);
单击[0]。input.mi.mouseData=new DWORD(0);
单击[1]。键入=新DWORD(输入。输入\鼠标);
单击[1].input.setType(“mi”);
单击[1]。input.mi.dwFlags=新DWORD(MOUSEEVENTF_LEFTUP);
单击[1]。input.mi.dwExtraInfo=new BaseTSD.ULONG_PTR(0);
单击[1]。input.mi.time=new DWORD(0);
单击[1]。input.mi.mouseData=new DWORD(0);
user32Library.SendInput(新建DWORD(2),单击,单击[0].size());
}
在这种情况下,根本不需要单击坐标点。相反,当按下某些键时,将在当前鼠标位置单击鼠标

顺便说一下,我也尝试过使用JavaRobot,但它对我不起作用。不幸的是,鼠标光标从起始位置移动(消失)了大约一毫秒,直到您需要单击并返回起始位置

void click(int xCord, int yCord) {
    //mouseMove(xCord, yCord);
    POINT p = {};
    GetCursorPos(&p);
    mouseMoveClick(xCord, yCord);
    SetCursorPos(p.x, p.y);
}
谢谢你把这篇文章读到最后,我为这么麻烦的解释道歉


谁能告诉我我在代码中犯了什么和哪里的错误?因为在所有3个选项中,我没有达到预期的行为。

对于第3种情况,您没有使用
MOUSEEVENTF\u MOVE
标志移动鼠标,因此鼠标实际上没有移动。并且根据:

如果指定了
MOUSEEVENTF\u绝对值
dxdy包含 0和65535之间的标准化绝对坐标

然后使用
MOUSEEVENTF_LEFTDOWN
MOUSEEVENTF_LEFTUP
单击当前位置

或者,您可以直接将鼠标移动合并到单击事件中:

void mouseMoveClick(int x, int y) {
    INPUT click[3] = {};

    click[0].type = INPUT_MOUSE;
    click[0].mi.dwFlags = MOUSEEVENTF_LEFTUP;// Release the mouse before moving it

    DWORD fScreenWidth = ::GetSystemMetrics(SM_CXSCREEN);
    DWORD fScreenHeight = ::GetSystemMetrics(SM_CYSCREEN);
    click[1].type = INPUT_MOUSE;
    click[1].mi.dx = click[2].mi.dx= MulDiv(x, 65535, fScreenWidth);
    click[1].mi.dy = click[2].mi.dy= MulDiv(y, 65535, fScreenHeight);
    click[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;

    click[2].type = INPUT_MOUSE;
    click[2].mi.dwFlags = MOUSEEVENTF_LEFTUP | MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;

    SendInput(3, click, sizeof(INPUT));
}
如果要在鼠标单击后移回原始位置,可以使用在移动前记录当前位置。然后使用mouseMove事件或更简单的方法返回该位置

void click(int xCord, int yCord) {
    //mouseMove(xCord, yCord);
    POINT p = {};
    GetCursorPos(&p);
    mouseMoveClick(xCord, yCord);
    SetCursorPos(p.x, p.y);
}

您的系统(或应用程序)DPI设置是否设置为默认值以外的其他值?@mni如果DPI参数在应用程序中没有更改,则在系统中也会默认配置该参数。如果我们谈论的是鼠标,那么我有一个非常简单的旧鼠标,Sven RX-160,分辨率,DPI 800。你有m吗
void mouseMove(int x, int y) {
    INPUT move[2] = {};
    
    DWORD fScreenWidth = ::GetSystemMetrics(SM_CXSCREEN);
    DWORD fScreenHeight = ::GetSystemMetrics(SM_CYSCREEN);
    move[0].type = move[1].type = INPUT_MOUSE;
    move[0].mi.dwFlags = MOUSEEVENTF_LEFTUP;// Release the mouse before moving it
    move[1].mi.dx = MulDiv(x, 65535, fScreenWidth);
    move[1].mi.dy = MulDiv(y, 65535, fScreenHeight);
    move[1].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;

    SendInput(2, move, sizeof(INPUT));
}
void mouseMoveClick(int x, int y) {
    INPUT click[3] = {};

    click[0].type = INPUT_MOUSE;
    click[0].mi.dwFlags = MOUSEEVENTF_LEFTUP;// Release the mouse before moving it

    DWORD fScreenWidth = ::GetSystemMetrics(SM_CXSCREEN);
    DWORD fScreenHeight = ::GetSystemMetrics(SM_CYSCREEN);
    click[1].type = INPUT_MOUSE;
    click[1].mi.dx = click[2].mi.dx= MulDiv(x, 65535, fScreenWidth);
    click[1].mi.dy = click[2].mi.dy= MulDiv(y, 65535, fScreenHeight);
    click[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;

    click[2].type = INPUT_MOUSE;
    click[2].mi.dwFlags = MOUSEEVENTF_LEFTUP | MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;

    SendInput(3, click, sizeof(INPUT));
}
void click(int xCord, int yCord) {
    //mouseMove(xCord, yCord);
    POINT p = {};
    GetCursorPos(&p);
    mouseMoveClick(xCord, yCord);
    SetCursorPos(p.x, p.y);
}