floatwf 2024-05-11 15:54 采纳率: 0%
浏览 30

JNA postMessage

###### 问题遇到的现象和发生背景 
最近在写一个游戏脚本,使用后台 JNA postMessage(sendMessage) 模拟鼠标点击事件,向游戏窗口发送鼠标事件的时候,如果发送的坐标是游戏窗口处刚好有一个按钮(组件),这样运行正常,当坐标处于游戏窗口的空白处时,模拟的鼠标单击的位置 是实际鼠标的位置,LPrama里面的 输入坐标失效
###### 操作环境、软件版本等信息 
JDK1.8  WIN10  JNA5.12.1
###### 尝试过的解决方法 
robot前台使用完全没问题,就是后台向游戏窗口空白处无法完成 指定坐标的单击(单击的永远是实际鼠标的位置),只能单击窗口内有组件的位置,目前怀疑是游戏屏蔽了 这种后台操作,有大神可以给点建议吗
###### 我想要达到的结果
可以指定游戏窗口任意空白位置单击
public static void mouseLeftClick(WinDef.HWND hwnd, int x, int y, long pressTime) {
        try {
            WinDef.LPARAM param = makeLParam(x,y);
            user32.PostMessage(hwnd, 513, null, param);
            Thread.sleep(pressTime);
            user32.PostMessage(hwnd, 514, null, param);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 写回答

4条回答 默认 最新

  • 笑面虎 2024-05-11 15:54
    关注

    以下内容由CHATGPT及笑面虎共同生成、有用望采纳:


    【您想要解决的问题】: 您想要解决的问题是在编写游戏脚本时,使用Java Native Access (JNA) 库通过 PostMessage 方法模拟鼠标点击事件,但当目标坐标位于游戏窗口的空白区域时,点击事件总是发生在实际鼠标的位置,而不是指定的坐标。您希望找到一个方法,能够在游戏窗口的任意空白位置模拟鼠标单击。

    【问题出现原因】: 这个问题可能出现的原因有几个:

    1. 游戏可能具有反作弊机制,能够识别并阻止非前台的模拟鼠标操作。
    2. PostMessage 方法可能在游戏窗口的某些区域无法正确模拟鼠标点击,尤其是当这些区域没有UI组件时。
    3. 游戏可能对鼠标事件的模拟有一定的限制,只允许在游戏的UI组件上触发事件。

    【问题解决方案】: 要解决这个问题,您可以尝试以下几种方法:

    1. 使用DirectX:如果游戏是基于DirectX开发的,您可以尝试直接通过DirectX API来模拟鼠标点击,这样可以绕过游戏的某些反作弊机制。
    2. 模拟键盘操作:如果可能,您可以尝试模拟键盘操作来触发游戏内的事件,有时候键盘事件比鼠标事件更难被检测。
    3. 使用图像识别:通过图像识别技术找到游戏中的UI组件,然后模拟鼠标点击到这些组件上,而不是空白区域。

    【提供代码】: 由于您的问题涉及到模拟鼠标点击,且可能受到游戏反作弊机制的影响,提供一个通用的解决方案比较困难。但是,我可以提供一个基本的JNA使用示例,您可以在此基础上进行修改和扩展:

    import com.sun.jna.*;
    import com.sun.jna.win32.*;
    import java.awt.*;
    
    public interface User32 extends StdCallLibrary {
        User32 INSTANCE = (User32) Native.load("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS);
    
        int WM_LBUTTONDOWN = 0x0201;
        int WM_LBUTTONUP = 0x0202;
        int WM_MOUSEMOVE = 0x0200;
    
        boolean PostMessage(int hWnd, int Msg, int wParam, POINT lParam);
    
        class POINT extends Structure {
            public int x;
            public int y;
    
            public POINT() {
            }
    
            protected List<String> getFieldOrder() {
                return Arrays.asList("x", "y");
            }
        }
    }
    
    public class GameClickSimulator {
        public static void main(String[] args) {
            // 假设您已经有了游戏窗口的句柄
            int hwnd = ...; 
            int x = ...; // 指定的x坐标
            int y = ...; // 指定的y坐标
    
            // 将坐标转换为POINT结构体
            User32.POINT point = new User32.POINT();
            point.x = x;
            point.y = y;
    
            // 发送鼠标按下事件
            User32.INSTANCE.PostMessage(hwnd, User32.WM_LBUTTONDOWN, 0, point);
    
            // 这里可以添加一个延迟,模拟鼠标按下的时间
            try {
                Thread.sleep(pressTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            // 发送鼠标释放事件
            User32.INSTANCE.PostMessage(hwnd, User32.WM_LBUTTONUP, 0, point);
        }
    }
    

    【代码运行方式】: 您需要将上述代码集成到您的Java项目中,并确保JNA库已经添加到项目的依赖中。您需要有游戏窗口的句柄以及您想要模拟点击的坐标。

    【代码预期运行结果】: 如果代码能够正常运行且游戏没有阻止后台操作,那么它将在指定的游戏窗口坐标模拟一次鼠标左键单击。

    【推荐相关链接】:

    请注意,模拟鼠标和键盘事件可能违反游戏的使用条款,并且可能涉及到法律风险。在尝试这些方法之前,请确保您了解相关的法律和游戏政策。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 5月11日