提取光标大小通过WinAPI(Windows 10)

huangapple go评论102阅读模式
英文:

Extract cursor size via WinAPI (Windows 10)

问题

我需要提取光标图像以在我的Swing应用程序(Java)中使用它。

首先,我找到了类似的问题,从一个答案中修改了代码片段,得到了这个沙盒应用程序

简而言之,它通过JNA和WinAPI获取光标图像,然后在JFrame上显示这个图像,并为此框架设置自定义光标。

在大多数情况下,这段代码运行正确,并且适合我的任务。但后来我发现,当用户更改光标的大小或颜色Windows 10功能)时,程序提取了一个无效的光标图像,既不匹配原始光标的颜色,也不匹配大小。

当用户使用标准光标时:

提取光标大小通过WinAPI(Windows 10)

当用户使用例如粉色光标且比标准光标更大时:

提取光标大小通过WinAPI(Windows 10)

在这种情况下,我决定以相同的沙盒应用程序方式,但使用C++和WinAPI。我使用了这个问题的答案,但只解决了颜色方面的问题。

提取光标大小通过WinAPI(Windows 10)

我认为主要的瓶颈是GetSystemMetrics函数返回默认光标大小(32x32),并且在光标大小更改后不会改变。我在这里找到了一些证据,但我不确定。

所以我的问题是:

我如何获得光标的真实大小?

非常感谢!
1: https://stackoverflow.com/questions/739870/extract-cursor-image-in-java/740528
2: https://pastebin.com/uDvH3HL7
3: https://pureinfotech.com/change-mouse-pointer-size-windows-10/
4: https://i.stack.imgur.com/vjVo5.png
5: https://i.stack.imgur.com/2tZfi.png
6: https://stackoverflow.com/questions/10469538/winapi-get-mouse-cursor-icon
7: https://i.stack.imgur.com/kQhWj.png
8: https://stackoverflow.com/questions/1699666/how-do-i-know-the-size-of-a-hcursor-object

英文:

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:

提取光标大小通过WinAPI(Windows 10)

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

提取光标大小通过WinAPI(Windows 10)

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.

提取光标大小通过WinAPI(Windows 10)

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!

答案1

得分: 5

我认为主要瓶颈是GetSystemMetrics函数返回默认的光标大小(32x32),并且在光标大小更改后不会改变。

当用户通过设置更改光标大小时,系统设置会将此更改更新到注册表值HKEY_CURRENT_USER\Control Panel\Cursors下的CursorBaseSize

您可以通过WM_SETTINGCHANGESetWinEventHookEVENT_OBJECT_SHOWOBJID_CURSOR)来获取更改时的通知。

然后读取CursorBaseSize注册值以获取新大小,并使用GetIconInfoEx来获取其他信息以创建指定大小的光标(CreateCursor)。

更多参考资料:如何在光标更改时获得通知?

英文:

> 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?

答案2

得分: 2

感谢 @Rita Han - MSFT 提供了开始搜索的初始点。

您可以通过两种方式获得真实的光标大小:
1)第一种方法在之前提到过:我们需要从注册表值 HKEY_CURRENT_USER\Control Panel\Cursors 下的 CursorBaseSize 中获取值。
2)第二种方法在这里找到:我们可以从注册表值 HKEY_CURRENT_USER\Software\Microsoft\Accessibility 中获取光标大小的乘数,然后自己计算光标大小。可以像这样完成:newHeight = cursorHeight + (multiplier - 1) * (cursorHeight / 2); 其中 cursorHeight 是来自 GetSystemMetrics(SM_CYCURSOR) 的值,multiplier 是来自注册表的值。光标的真实宽度值将与 newHeight 相同。所有值都是 unsigned long 如果我们使用 C++。

找到大小的两种方法都会导致相同的结果。

如果您需要在 Java 中从注册表中获取光标的真实大小值,您可以使用 JNA-platform 中的 Advapi32Util 类:

// 读取一个 int (& 0xFFFFFFFFL 用于大型无符号 int)
int baseSize = Advapi32Util.registryGetIntValue(
        WinReg.HKEY_CURRENT_USER, "Control Panel\\Cursors", "CursorBaseSize");
英文:

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

huangapple
  • 本文由 发表于 2020年8月7日 00:09:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/63287678.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定