英文:
Extract cursor size via WinAPI (Windows 10)
问题
我需要提取光标图像以在我的Swing应用程序(Java)中使用它。
首先,我找到了类似的问题,从一个答案中修改了代码片段,得到了这个沙盒应用程序。
简而言之,它通过JNA和WinAPI获取光标图像,然后在JFrame上显示这个图像,并为此框架设置自定义光标。
在大多数情况下,这段代码运行正确,并且适合我的任务。但后来我发现,当用户更改光标的大小或颜色(Windows 10功能)时,程序提取了一个无效的光标图像,既不匹配原始光标的颜色,也不匹配大小。
当用户使用标准光标时:
当用户使用例如粉色光标且比标准光标更大时:
在这种情况下,我决定以相同的沙盒应用程序方式,但使用C++和WinAPI。我使用了这个问题的答案,但只解决了颜色方面的问题。
我认为主要的瓶颈是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:
When the user has e.g. pink cursor then bigger than standard one:
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.
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_SETTINGCHANGE
或SetWinEventHook
(EVENT_OBJECT_SHOW
,OBJID_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:
- The first way is mentioned before: we need to get value from registry value
CursorBaseSize
underHKEY_CURRENT_USER\Control Panel\Cursors
. - The second way was found here: we can get cursor size multiplier form registry value
CursorSize
underHKEY_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);
wherecursorHeight
is value fromGetSystemMetrics(SM_CYCURSOR)
andmultiplier
is value from the registry. The cursor real width value will be the same asnewHeight
. All values areunsigned 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");
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论