BaLiK
BaLiK

Reputation: 99

Extract cursor size via WinAPI (Windows 10)

I need to extract the cursor image for using it in my swing application (Java).

Firstly, I found similar question, modified code snippet from an answer, and got this sandbox application.

Shortly, it gets cursor image via JNA and WinAPI, then shows this image on JFrame and sets custom cursor for this frame.

In most cases, this code works correctly and suits my tasks. But then I found that when the user changes the cursor's size or color(Windows 10 feature), the program extracts an invalid cursor image that matches the original cursor neither in color nor in size.

When the user has standard cursor:

enter image description here

When the user has e.g. pink cursor then bigger than standard one:

enter image description here

After this situation, I decided to do the same sandbox application, but via C++ and WinAPI. I used answers for this question, but solved only troubles with color.

enter image description here

I think the main bottleneck is that GetSystemMetrics function returns default cursor size (32x32) and it doesn't change after the cursor's size changing. I found some proves for this here, but I'm not sure.

So my question is:

How can I get the real size of cursor?

Thanks a lot in advance!

Upvotes: 4

Views: 1757

Answers (2)

BaLiK
BaLiK

Reputation: 99

Thanks @Rita Han - MSFT for giving the initial point to start searching.

You can get a real cursor size in two ways:

  1. The first way is mentioned before: we need to get value from registry value CursorBaseSize under HKEY_CURRENT_USER\Control Panel\Cursors.
  2. The second way was found here: we can get cursor size multiplier form registry value CursorSize under HKEY_CURRENT_USER\Software\Microsoft\Accessibility and then calculate the cursor size yourself. It can be done somehow like this: newHeight = cursorHeight + (multiplier - 1) * (cursorHeight / 2); where cursorHeight is value from GetSystemMetrics(SM_CYCURSOR) and multiplier is value from the registry. The cursor real width value will be the same as newHeight. All values are unsigned long if we use C++.`

Both methods of finding the size lead to the same result.

If you need to find to get cursor real size value from the registry in Java, you can use Advapi32Util class from JNA-platform:

        // Read an int (& 0xFFFFFFFFL for large unsigned int)
        int baseSize = Advapi32Util.registryGetIntValue(
                WinReg.HKEY_CURRENT_USER, "Control Panel\\Cursors", "CursorBaseSize");

Upvotes: 2

Rita Han
Rita Han

Reputation: 9700

I think the main bottleneck is that GetSystemMetrics function returns default cursor size (32x32) and it doesn't change after the cursor's size changing.

When user change cursor size via Settings. System Settings will update this change to registry value CursorBaseSize under HKEY_CURRENT_USER\Control Panel\Cursors.

You can get notification when change happens via WM_SETTINGCHANGE or SetWinEventHook (EVENT_OBJECT_SHOW, OBJID_CURSOR).

Then read CursorBaseSize register value to get new size and get other information using GetIconInfoEx to creates a cursor having the specified size. (CreateCursor)

More references: How can I get notified when the cursor changes?

Upvotes: 5

Related Questions