windows LoadCursor和混合DPI多显示器

6ovsh4lw  于 2023-06-24  发布在  Windows
关注(0)|答案(2)|浏览(145)

LoadCursor函数用于从资源加载游标时,生成的HCURSOR可以跨不同的监视器使用,并且始终以正确的大小显示。
即:典型地:

  • 在96dpi监视器上使用32 × 32资源,
  • 在192dpi监视器上使用64 × 64资源。

但是,当游标是从内存中以编程方式创建的(比如使用LookupIconIdFromDirectoryExCreateIconFromResourceEx),生成的游标具有固定的分辨率。这意味着在混合DPI多显示器设置中,它至少在一台显示器上显示为错误的大小。
我还检查了LoadCursorFromFile,它也提供了像LoadCursor这样的动态分辨率行为。
有没有一种方法可以编程地创建一个光标,它可以根据显示在哪个监视器上而动态切换?加载了LoadCursor的游标以不同的方式工作,在幕后发生了什么神奇的事情?

aurhwmvo

aurhwmvo1#

经过多次实验,我终于发现WPF可以从资源和内存流加载游标,并在使用scaleWithDpi选项时获得正确的DPI行为:

public Cursor(Stream cursorStream, bool scaleWithDpi)

查看引用源代码,它在函数LoadFromStream中结束,该函数通过将流写入临时文件并从文件加载来加载流。见来源
总而言之:

  • 似乎获得这样的动态DPI光标的唯一方法是使用Win32本机资源加载函数和从文件加载。似乎不能通过这种行为直接从内存中加载游标。
  • 此行为的“动态dpi”部分似乎与传递给LoadImage函数的LR_DEFAULTSIZE标志有关。
0h4hbjxa

0h4hbjxa2#

加载了LoadCursor的游标以不同的方式工作,在幕后发生了什么神奇的事情?
提供hInst/MAKEINTRESOURCE(resId)LR_LOADFROMFILE标志的LoadImageLoadCursorFromFile API确实在返回的HCURSOR/HICON中保存了额外的信息。
DrawIconExDI_DEFAULTSIZE以及其他API可能正在使用此信息来绘制与用户监视器DPI对应的图标。它尝试从资源源中获取最适合当前监视器/窗口的DPI相关大小的图标图像。
此图标源信息可通过自Windows Vista以来可用的ICONINFOEX结构的szModName/wResID/szResName成员中的GetIconInfoEx手动获取。
CreateIconFromResourceEx不设置此信息,因为它只接收到指向图标/光标位的内存指针。在这种情况下,简单的图像缩放应用于DrawIconEx调用。
除了使用从文件/exe/dll加载之外,似乎没有其他方法可以使用此DPI感知绘制机制。
关于这个主题的一些信息在Raymond Chen博客:

PS:作为一个解决方案我认为可以处理WM_SETCURSOR窗口消息,计算窗口的DPI感知光标大小(使用wParamGetDpiForWindowGetSystemMetricsForDpiSM_CXCURSOR/SM_CYCURSOR)加载相应的HCURSOR并使用它调用SetCursor函数。
此外,Windows 10中还有一个新的用户光标大小设置,也可能被考虑在内。下面是一些Qt代码来处理它并返回正确的光标大小。

相关问题