简体   繁体   中英

JNA - Changing the Windows Cursor

I'm trying to set the Windows Cursor to a random one from an array named cursorOptions which holds the values for each cursor type.

int[] cursorOptions = new int[]{32650, 32515, 32649, 32651, 32513, 32648, 32646, 32643, 32645, 32642, 32644, 32516, 32514, 32512};

I'm using the SetCursor(WinDef.LONG hcur) JNA method (found on line 1157 at: https://github.com/br45entei/SWT-Win32-Extension/blob/master/src/org/sf/feeling/swt/win32/extension/jna/win32/User32.java ) but have no idea what value I should put for hcur. I tried to send the new cursor value from the array but that evaluated to false.

WinDef.LONG u = new WinDef.LONG(cursorOptions[rand.nextInt(cursorOptions.length-1)]);
user32.SetCursor(u);
user32.ShowCursor(true);

Next, I tried to assign the hashCode value of different cursor values (65541 for the IBar cursor) which evaluated to true but that didn't change the cursor value.

WinDef.LONG g = new WinDef.LONG(65541);
user32.SetCursor(g);
user32.ShowCursor(true);

What value of hcur is expected to change the cursor? Why does the hashCode value of a cursor evaluate as true yet not change the cursor when sent in SetCursor(WinDef.LONG hcur)?

Full Code:

import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.win32.W32APIOptions;
import java.awt.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;

class MouseManipulation {

private User32 user32;

MouseManipulation() {
    user32 = User32.INSTANCE;
}
/**
* @return cursorInfo.hCursor Returns the HCURSOR of the cursor on screen
 */
WinDef.HCURSOR getCurrentCursor(){
    CursorInfo cursorInfo = new CursorInfo();
    this.user32.GetCursorInfo(cursorInfo);
    return cursorInfo.hCursor;
}

/*
 * Set the cursor to be a random cursor within the defined scope of cursorOptions
 */
void ChangeMouseCursor() {
    try {
        int[] cursorOptions = new int[]{32650, 32515, 32649, 32651, 32513, 32648, 32646, 32643, 32645, 32642, 32644, 32516, 32514, 32512};
        Random rand = new Random();

        WinDef.HCURSOR hc = getCurrentCursor();
        System.out.println("The HCURSOR: "+hc.toString());
        System.out.println("The HCURSOR hashCode: "+hc.hashCode());

        //I want this to randomly pick from the Array of cursor values and set that as the newest cursor icon 
        //but I have no clue what value for WinDef.LONG should be
        WinDef.LONG u = new WinDef.LONG(cursorOptions[rand.nextInt(cursorOptions.length-1)]);
        user32.SetCursor(u);
        user32.ShowCursor(true);
        System.out.println("When using the array: "+user32.SetCursor(u));

       //This evaluates to true yet doesn't change the cursor icon on screen; 
       //for instance 65541 is the hashCode for IBar and when cursor is NormalPointer it doesn't change.
        WinDef.LONG g = new WinDef.LONG(65541);
        user32.SetCursor(g);
        user32.ShowCursor(true);
        System.out.println("When using the hashCode: "+user32.SetCursor(g));

    }
    //Sometimes the cursor won't be found so we catch the NullPointerException
    catch (NullPointerException e){
        e.printStackTrace();
    }
}

/*
* Take advantage of the JNA 4.5.2 and the JNA 4.5.2 platform to interact with the Win32 API
*/
public interface User32 extends com.sun.jna.Library {
    MouseManipulation.User32 INSTANCE = (MouseManipulation.User32) Native.loadLibrary("user32", MouseManipulation.User32.class, W32APIOptions.DEFAULT_OPTIONS);
    boolean SetCursor(WinDef.LONG hcur);
    int GetCursorInfo(CursorInfo cursorInfo);
    int ShowCursor(boolean bShow);
}

/*
* This class was made to get the cursor's information such as its pointer and then later gets its hashCode value
Credits: deFreitas at: https://stackoverflow.com/questions/47634213/get-mouse-type-in-java-using-jna
*/
public static class CursorInfo extends Structure {

    public int cbSize;//Access must be public
    public int flags;
    public WinDef.HCURSOR hCursor;//Access must be public
    public WinDef.POINT ptScreenPos;

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

Used Libraries:

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

Calling:

final MouseManipulation mouse = new MouseManipulation();
mouse.ChangeMouseCursor();

Note: I want the windows cursor to change even if not on a java application so JFrame solutions and other such things are unwarranted.

I thank you in advance!

Effect of the SetCursor lasts only until next SetCursor call. The SetCursor is called a lot from windows procedures in reaction to messages send by Windows Manager to give user feedback by changing cursor shape when you move mouse over windows and in newer Windows versions even if mouse is stationary.

To change the cursor permanently you can use the SetClassLongPtr( hwnd, GCLP_HCURSOR, cursor_handle ); or subclass window procedure and handle the WM_SETCURSOR message (this is unfortunately in C):

case WM_SETCURSOR:
    // If you omit test below, you will change cursor also for scrollbars, frames, etc.
    if ( LOWORD( lparam ) == HTCLIENT )
        SetCursor( cursor_handle );
    else
        // This will also handle cursor for scrollbars and frames.
        return DefWindowProc( hwnd, msg, wparam, lparam );
    return TRUE;

The cursor_handle must be a valid handle for a process witch created window.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM