使用 jna 在 java 中获取鼠标类型
get mouse type in java using jna
非常感谢@deFreitas
我正在尝试在 java
中创建远程控制程序。
我的问题是我使用 robot
class 的屏幕截图从远程计算机获取图像,因此我看不到远程光标。
我知道我可以在屏幕截图上绘制光标图像,但我怎样才能获得全局光标类型。
我搜索了很多,最接近的是这段代码:
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
class 获取光标类型...
有没有办法获取类型甚至光标位图?
编辑:
我找到了这个函数:
WinNT.HANDLE LoadImage(WinDef.HINSTANCE hinst,
String name,
int type,
int xDesired,
int yDesired,
int load)
但我不知道该给它哪种类型。我看到的每个网站都加载图像或特定的光标类型……
有可能,基本上你需要GetCursorInfo and LoadImage
BOOL GetCursorInfo(PCURSORINFO pci)
它获取当前游标句柄并将其存储在 PCURSORINFO.hCursor
中,这是实际的游标,但没有指示器知道它是什么类型,请注意它是 Windows 而不是 JNA 限制.不管怎样,如果你使用
HANDLE WINAPI LoadImage(...,PCTSTR cursorId,...)
它将 return 给定游标类型 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 -
* 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 无法识别它是哪种光标。
JNA版本
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'
非常感谢@deFreitas
我正在尝试在 java
中创建远程控制程序。
我的问题是我使用 robot
class 的屏幕截图从远程计算机获取图像,因此我看不到远程光标。
我知道我可以在屏幕截图上绘制光标图像,但我怎样才能获得全局光标类型。
我搜索了很多,最接近的是这段代码:
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
class 获取光标类型...
有没有办法获取类型甚至光标位图?
编辑: 我找到了这个函数:
WinNT.HANDLE LoadImage(WinDef.HINSTANCE hinst,
String name,
int type,
int xDesired,
int yDesired,
int load)
但我不知道该给它哪种类型。我看到的每个网站都加载图像或特定的光标类型……
有可能,基本上你需要GetCursorInfo and LoadImage
BOOL GetCursorInfo(PCURSORINFO pci)
它获取当前游标句柄并将其存储在 PCURSORINFO.hCursor
中,这是实际的游标,但没有指示器知道它是什么类型,请注意它是 Windows 而不是 JNA 限制.不管怎样,如果你使用
HANDLE WINAPI LoadImage(...,PCTSTR cursorId,...)
它将 return 给定游标类型 ID 的句柄,here a list 包含所有可用的游标 ID。这样你就可以使用 LoadImage
加载所有游标然后只用 GetCursorInfo
结果做一个等于,匹配的结果是实际的游标类型。这是一个使用 JNA
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 -
* 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 无法识别它是哪种光标。
JNA版本
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'