java使用jna获取鼠标类型

说明

通过jna获取鼠标类型

依赖

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.7.0</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna-platform</artifactId>
    <version>5.7.0</version>
</dependency>

java

鼠标状态的枚举类

package top.malaoshi.cursor;

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

鼠标状态,原windows定义的内容:


#define IDC_ARROW           MAKEINTRESOURCE(32512)
#define IDC_IBEAM           MAKEINTRESOURCE(32513)
#define IDC_WAIT            MAKEINTRESOURCE(32514)
#define IDC_CROSS           MAKEINTRESOURCE(32515)
#define IDC_UPARROW         MAKEINTRESOURCE(32516)
#define IDC_SIZE            MAKEINTRESOURCE(32640)  /* OBSOLETE: use IDC_SIZEALL */
#define IDC_ICON            MAKEINTRESOURCE(32641)  /* OBSOLETE: use IDC_ARROW */
#define IDC_SIZENWSE        MAKEINTRESOURCE(32642)
#define IDC_SIZENESW        MAKEINTRESOURCE(32643)
#define IDC_SIZEWE          MAKEINTRESOURCE(32644)
#define IDC_SIZENS          MAKEINTRESOURCE(32645)
#define IDC_SIZEALL         MAKEINTRESOURCE(32646)
#define IDC_NO              MAKEINTRESOURCE(32648) /*not in win3.1 */
#if(WINVER >= 0x0500)
#define IDC_HAND            MAKEINTRESOURCE(32649)
#endif /* WINVER >= 0x0500 */
#define IDC_APPSTARTING     MAKEINTRESOURCE(32650) /*not in win3.1 */
#if(WINVER >= 0x0400)
#define IDC_HELP            MAKEINTRESOURCE(32651)
#endif /* WINVER >= 0x0400 */

相应的解释:


#define IDC_ARROW           MAKEINTRESOURCE(32512)
#define IDC_IBEAM           MAKEINTRESOURCE(32513)
#define IDC_WAIT            MAKEINTRESOURCE(32514)
#define IDC_CROSS           MAKEINTRESOURCE(32515)
#define IDC_UPARROW         MAKEINTRESOURCE(32516)
#define IDC_SIZE            MAKEINTRESOURCE(32640)  /* OBSOLETE: use IDC_SIZEALL */
#define IDC_ICON            MAKEINTRESOURCE(32641)  /* OBSOLETE: use IDC_ARROW */
#define IDC_SIZENWSE        MAKEINTRESOURCE(32642)
#define IDC_SIZENESW        MAKEINTRESOURCE(32643)
#define IDC_SIZEWE          MAKEINTRESOURCE(32644)
#define IDC_SIZENS          MAKEINTRESOURCE(32645)
#define IDC_SIZEALL         MAKEINTRESOURCE(32646)
#define IDC_NO              MAKEINTRESOURCE(32648) /*not in win3.1 */
#if(WINVER >= 0x0500)
#define IDC_HAND            MAKEINTRESOURCE(32649)
#endif /* WINVER >= 0x0500 */
#define IDC_APPSTARTING     MAKEINTRESOURCE(32650) /*not in win3.1 */
#if(WINVER >= 0x0400)
#define IDC_HELP            MAKEINTRESOURCE(32651)
#endif /* WINVER >= 0x0400 */

鼠标结构体

package top.malaoshi.cursor;

import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef;

import java.util.Arrays;
import java.util.List;

//  typedef struct {
//      DWORD   cbSize;
//      DWORD   flags;
//      HCURSOR hCursor;
//      POINT   ptScreenPos;
//  } top.malaoshi.cursor.CURSORINFO, *PCURSORINFO, *LPCURSORINFO;


public 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");
    }
}

引用的windows api

package top.malaoshi.cursor;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinGDI;
import com.sun.jna.platform.win32.WinNT;

public interface User32 extends com.sun.jna.Library {
    User32 INSTANCE = Native.load("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
    );

    boolean GetIconInfo(WinDef.HICON hicon, WinGDI.ICONINFO iconinfo);

    WinDef.HDC GetDC(WinDef.HWND hwdn);

    void DestroyIcon(WinDef.HICON hicon);
}

主启动类

package top.malaoshi.cursor;

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

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 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 {
        Main main = new Main();
        while(true){
            System.out.println(main.getCurrentCursor());
            Thread.sleep(500);
        }
    }

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

    public Main(){
        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 = user32.GetCursorInfo(cursorinfo);
        if(success != 1){
            throw new Error("Could not retrieve cursor info: " + String.valueOf(Native.getLastError()));
        }

        System.out.printf("currentPointer=%s%n", cursorinfo.hCursor);
        return cursors.get(cursorinfo.hCursor);

    }




}

参考

https://www.coder.work/article/4732041
https://blog.csdn.net/moiit/article/details/50700265
https://blog.csdn.net/qq_22642239/article/details/99633129