SOVED thanks to @deFreitas
I am trying to create remote control program in java
.
my problem is that I get image from remote computer using screenshot from the robot
class and therefore I can not see the remote cursor.
I know I can draw image of cursor on the screenshot but how can I get the global cursor type.
I have searched a lot for that and the closest I got was this code:
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();
}
but I don't understand how to get cursor type from HCursor
class…
Is there a way to get the type or even the cursor bitmap¿
EDIT:
I found this function:
WinNT.HANDLE LoadImage(WinDef.HINSTANCE hinst,
String name,
int type,
int xDesired,
int yDesired,
int load)
but I don't know whitch type to give it. every website I saw load image or a specific cursor type…
It's possible, basically you need GetCursorInfo and LoadImage
BOOL GetCursorInfo(PCURSORINFO pci)
It gets current cursor handle and store it inside PCURSORINFO.hCursor
, that's the actual cursor but there is not indicator to know what type it's, note that it is a Windows and not a JNA limitation. Anyway if you use
HANDLE WINAPI LoadImage(...,PCTSTR cursorId,...)
It will return a handle given the cursor type ID, here a list with all available cursor ids. This way you can use LoadImage
to load all cursors then just do a equals with GetCursorInfo
result, the result which match is the actual cursor type. Here a working JAVA program using 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 - 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: Not all possible cursors have available resource ids (like zoom in, zoom out), it's because the system default cursors are 15, the anothers are custom cursors created by the software(like chrome, firefox) this way windows cannot identify what kind cursor it's.
Jna version
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'