如何移动(或使用)鼠标

发布于 2024-12-20 09:10:31 字数 1911 浏览 3 评论 0原文

如何使用 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 数组的角度来思考,其中数组只是指向连续内存区域的指针。更多即将到来(我希望!)。

How to interact with the Windows API using Java and the JNA (Java Native Access)?. I'm trying to make the mouse do something by queuing a mouse event on the mouse input stream, and the code works, in that the SendInput(...) method returns 1 suggesting that it has successfully queued the event, but yet the mouse itself does nothing.

My SSCCE:

Edit: edited to fill in the dwFlags field. I've tried several combinations of constants either by themselves or bit-or combined without success still. Again, the SendInput method returns 1 as it should suggesting a functioning method, but the mouse doesn't budge:

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
   }
}

Edit 2:

Doing more reading, and it seems that my understanding of arrays with JNA is deficient, that I have to think in terms of C arrays where an array is simply a pointer to a region of contiguous memory. More to come (I hope!).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

请持续率性 2024-12-27 09:10:31

JNA 文档 使用结构和联合 内容如下:

联合通常可与结构互换,但要求您使用 setType 方法指示哪个联合字段处于活动状态,然后才能将其正确传递给函数调用。

我猜你错过了 setType 部分。此外,当使用 MOUSEEVENTF_ABSOLUTE 时,dxdy 被指定为鼠标坐标,而不是像素。

以下作品:

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));
    ...
}

JNA document Using Structures And Unions reads:

Unions are generally interchangeable with Structures, but require that you indicate which union field is active with the setType method before it can be properly passed to a function call.

I guess you missed setType part. Also, when using MOUSEEVENTF_ABSOLUTE, dx and dy are specified as the coordinate of the mouse, not pixels.

Following works:

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));
    ...
}
情话墙 2024-12-27 09:10:31

对结构调用 toArray() 方法以获得连续的内存块。

INPUT input = new INPUT();
INPUT[] arg = (INPUT[])input.toArray(1);

或者,您可以简单地为 SendInput 声明一个替代方法映射:

DWORD SendInput(int nInputs, INPUT pInputs, int cbSize);

但是,可能还会发生其他情况(也许是权限?请参阅 UIPI 上的 MS 注释),因为您的示例应该可以工作(至少对于单个数组元素)。

编辑: Union.setType() 答案确实是正确的。

Call the toArray() method on your structure to obtain a contiguous block of memory.

INPUT input = new INPUT();
INPUT[] arg = (INPUT[])input.toArray(1);

Alternatively, you can simply declare an alternate method mapping for SendInput:

DWORD SendInput(int nInputs, INPUT pInputs, int cbSize);

However, there may be something else going on (permissions, perhaps? see MS notes on UIPI), since your example ought to work (at least with a single array element).

EDIT: the Union.setType() answer is indeed the correct one.

墨小沫ゞ 2024-12-27 09:10:31
input.input.mi.dwFlags = new DWORD(0);

您没有指定任何鼠标输入标志,因此没有鼠标输入。

input.input.mi.dwFlags = new DWORD(0);

You didn't specify any of the mouse input flags, so there was no mouse input.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文