使用jna在java中获取鼠标类型

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用jna在java中获取鼠标类型相关的知识,希望对你有一定的参考价值。

求助于@deFreitas

我正在尝试在java创建远程控制程序。我的问题是我使用robot类的截图从远程计算机获取图像,因此我看不到远程光标。我知道我可以在屏幕截图上绘制光标图像但是如何获取全局光标类型。

我已经搜索了很多,我得到的最接近的是这段代码:

public interface User32 extends com.sun.jna.Library {
  public static User32 INSTANCE = (User32) com.sun.jna.Native
          .loadLibrary("User32", User33.class);
  public com.sun.jna.platform.win32.WinDef.HCURSOR GetCursor();

}

但我不明白如何从HCursor类获取游标类型...是否有办法获取类型甚至光标位图?

编辑:我发现这个功能:

WinNT.HANDLE LoadImage(WinDef.HINSTANCE hinst,
                   String name,
                   int type,
                   int xDesired,
                   int yDesired,
                   int load)

但我不知道给它的类型。我看到的每个网站加载图片或特定的光标类型......

答案

这是可能的,基本上你需要GetCursorInfoLoadImage

BOOL GetCursorInfo(PCURSORINFO pci)

它获取当前光标句柄并将其存储在PCURSORINFO.hCursor中,这是实际的光标,但没有指示器知道它是什么类型,请注意它是Windows而不是JNA限制。无论如何,如果你使用

HANDLE WINAPI LoadImage(...,PCTSTR cursorId,...)

它将返回一个句柄,给定光标类型ID,here a list以及所有可用的游标ID。这样你可以使用LoadImage加载所有游标然后只用GetCursorInfo结果做一个等于,匹配的结果是实际的游标类型。这是一个使用JNA的工作JAVA程序

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.*;

import java.io.IOException;
import java.util.*;

/**
 * https://msdn.microsoft.com/pt-br/library/windows/desktop/ms648029(v=vs.85).aspx
 * Test cursors - https://developer.mozilla.org/en-US/docs/Web/CSS/cursor
 * Chromium cursor map -  https://github.com/mageddo/chromium/blob/master/webkit/glue/webcursor_win.cc
 * Load icon example - https://github.com/java-native-access/jna/blob/master/contrib/platform/test/com/sun/jna/platform/win32/GDI32Test.java#L54
 * understanding makeintresource - https://stackoverflow.com/questions/3610565/why-does-makeintresource-work
 * all possible windows error codes - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681386(v=vs.85).aspx
 * Cursor ids - https://msdn.microsoft.com/en-us/library/windows/desktop/ms648391(v=vs.85).aspx
 *
 */
public class Main {

    public static void main(String[] args) throws Exception {
        while(true){
            final Main main = new Main();
            System.out.println(main.getCurrentCursor());
            Thread.sleep(2000);
        }
    }

    private final Map<WinNT.HANDLE, Cursor> cursors;
    private final User32 user32;

    public Main(){
        user32 = User32.INSTANCE;
        cursors = loadCursors();
    }


    /**
     * Load all possible cursors to a map
     */
    private Map<WinNT.HANDLE, Cursor> loadCursors() {
        final Map<WinNT.HANDLE, Cursor> cursors = new HashMap<>();
        for (final Cursor cursor : Cursor.values()) {

            final Memory memory = new Memory(Native.getNativeSize(Long.class, null));
            memory.setLong(0, cursor.getCode());
            final Pointer resource = memory.getPointer(0);
            final WinNT.HANDLE hcursor = this.user32.LoadImageA(
                null, resource, WinUser.IMAGE_CURSOR, 0, 0, WinUser.LR_SHARED
            );
            if(hcursor == null || Native.getLastError() != 0){
                throw new Error("Cursor could not be loaded: " + String.valueOf(Native.getLastError()));
            }

            cursors.put(hcursor, cursor);
        }
        return Collections.unmodifiableMap(cursors);
    }

    public Cursor getCurrentCursor(){
        final CURSORINFO cursorinfo = new CURSORINFO();
        final int success = this.user32.GetCursorInfo(cursorinfo);
        if(success != 1){
            throw new Error("Could not retrieve cursor info: " + String.valueOf(Native.getLastError()));
        }

        // you can use the address printed here to map the others cursors like ALL_SCROLL
        System.out.printf("currentPointer=%s%n", cursorinfo.hCursor);
        // some times cursor can be hidden, in this case it will be null
        if(cursorinfo.hCursor != null && cursors.containsKey(cursorinfo.hCursor)){
            return cursors.get(cursorinfo.hCursor);
        }
        return null;
    }

//  typedef struct {
//      DWORD   cbSize;
//      DWORD   flags;
//      HCURSOR hCursor;
//      POINT   ptScreenPos;
//  } CURSORINFO, *PCURSORINFO, *LPCURSORINFO;
    public static class CURSORINFO extends Structure {

        public int cbSize;
        public int flags;
        public WinDef.HCURSOR hCursor;
        public WinDef.POINT ptScreenPos;

        public CURSORINFO() {
            this.cbSize = Native.getNativeSize(CURSORINFO.class, null);
        }
        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("cbSize", "flags", "hCursor", "ptScreenPos");
        }
    }

    public interface User32 extends com.sun.jna.Library {
        User32 INSTANCE = Native.loadLibrary("User32.dll", User32.class);

        //      BOOL WINAPI GetCursorInfo(
//          _Inout_ PCURSORINFO pci
//      );
        int GetCursorInfo(CURSORINFO cursorinfo);

//      HANDLE WINAPI LoadImage(
//          _In_opt_ HINSTANCE hinst,
//          _In_     LPCTSTR   lpszName,
//          _In_     UINT      uType,
//          _In_     int       cxDesired,
//          _In_     int       cyDesired,
//          _In_     UINT      fuLoad
//      );
        WinNT.HANDLE LoadImageA(
            WinDef.HINSTANCE hinst,
            Pointer lpszName,
            int uType,
            int cxDesired,
            int cyDesired,
            int fuLoad
        );
    }

    public enum Cursor {
        APPSTARTING(32650),
        NORMAL(32512),
        CROSS(32515),
        HAND(32649),
        HELP(32651),
        IBEAM(32513),
        NO(32648),
        SIZEALL(32646),
        SIZENESW(32643),
        SIZENS(32645),
        SIZENWSE(32642),
        SIZEWE(32644),
        UP(32516),
        WAIT(32514),
        PEN(32631)
        ;

        private final int code;

        Cursor(final int code) {
            this.code = code;
        }

        public int getCode() {
            return code;
        }
    }
}

Obs:并非所有可能的游标都有可用的资源ID(如放大,缩小),这是因为系统默认游标是15,其他人是由软件创建的自定义游标(如chrome,firefox)这样windows无法识别哪种类型光标吧。

Jan版

compile group: 'net.java.dev.jna', name: 'jna', version: '4.5.0'
compile group: 'net.java.dev.jna', name: 'jna-platform', version: '4.5.0'

以上是关于使用jna在java中获取鼠标类型的主要内容,如果未能解决你的问题,请参考以下文章

未找到 Java JNA sendMessage()

使用jna和CreateProcessW时如何获取进程输出

使用JNA,让java调用原生代码

在 Java 中使用 ImageSearchDll.dll(来自 AutoIt)编辑:JNA

使用 JNA 将本机 C 函数映射到 Java 接口时的指针问题

#yyds干货盘点#java高级用法之:在JNA中将本地方法映射到JAVA代码中