以编程方式确定 Windows DPI 设置?
我们的一个不支持 dpi 的 MFC 应用程序遇到了问题。
如果您将系统设置更改为高 dpi(例如 120 或 144 dpi),任务栏上的应用程序图标看起来会很糟糕。不幸的是,我们必须为大型机注册我们自己的WNDCLASS
,并且在WNDCLASS.hIcon
成员中您必须设置一个图标。该图标是使用LoadIcon
函数加载的。该函数尝试加载标准尺寸的图像(与 GetSystemMetrics(SM_CXICON) 返回的相同),对于 120dpi 来说是 40x40 像素。不幸的是,我们不提供该尺寸的图标。但有一个解决方法:奇怪的是,dpi 虚拟化似乎对 120 dpi 不起作用,GetDeviceCaps(..., LOGPIXELSX)
确实返回 120 dpi 和 GetSystemMetrics(SM_CXICON) )
返回 40。因此我们可以捕捉到这一点并以不同的大小加载图标。但对于 144 dpi 来说它不起作用,因为现在虚拟化似乎已经生效,我们得到 96 dpi 和 32 像素,这再次导致图标看起来非常难看。
我发现如果我将 WNDCLASS.hIcon
成员设置为 NULL
,图标就会显示得很好。但我想知道这是否可以,因为根据 MSDN:
hIcon
类图标的句柄。这 成员必须是图标的句柄 资源。如果该成员为 NULL,则 系统提供了默认图标。
那么,即使我将该成员设置为 NULL,我可以指望图标始终显示吗? 另一种方法是以正确的尺寸加载图标,但为此我必须知道系统实际上设置为 144 dpi。这就是我最初的问题。 有谁知道是否可以确定系统的 DPI 设置(从 dpi 虚拟化应用程序内)?请注意,我也考虑过做一些肮脏的事情,比如让 dpi 感知应用程序告诉我实际的 dpi 之类的东西,但如果可能的话,我想避免这样的事情。
最好的问候,
humbagumba
更新:
我发现将 WNDCLASS.hIcon
成员设置为 NULL
不是一个好主意,因为这样主机的图标就会被默认图标替换(即使它看起来在任务栏上很好...) - 我在第一次测试期间没有注意到这一点。
we've got a problem with one of our non dpi aware MFC applications.
If you change the system setting to high dpi (e.g. 120 or 144 dpi), the application icon on the taskbar looks screwed up. Unfortunately, we have to register our own WNDCLASS
for the mainframe, and in the WNDCLASS.hIcon
member you have to set an icon. This icon is loaded using the LoadIcon
function. And that function tries to load the image in a standard size (the same as being returned by GetSystemMetrics(SM_CXICON)
), which for 120dpi is 40x40 pixels. That's unfortunate because we do not provide an icon in that size. But there's a workaround for this: Since strangely, the dpi virtualization seems to not be in effect for 120 dpi, GetDeviceCaps(..., LOGPIXELSX)
does indeed return 120 dpi and GetSystemMetrics(SM_CXICON)
returns 40. So we can catch that and just load the icon in a different size. But for 144 dpi it doesn't work, because now the virtualization seems to be in effect, and we get 96 dpi and 32 pixels, which again cause the icon to look very ugly.
I found out that if I just set the WNDCLASS.hIcon
member to NULL
, the icon shows up fine. But I wonder if that's ok because according to MSDN:
hIcon
Handle to the class icon. This
member must be a handle to an icon
resource. If this member is NULL, the
system provides a default icon.
So can I count on the icon showing always up even if I set that member to NULL?
The other way would be to also load the icon in the correct size but for that I would have to know that the system is actually set to 144 dpi. And there we are at my initial question.
Does anyone know if it is possible to determine the system's DPI setting (from within a dpi virtualized application)? Note that I've also thought about doing something dirty like having a dpi aware application tell me the actual dpi and stuff like that, but I wanna avoid such things if possible.
Best regards,
humbagumba
Update:
I found out that setting the WNDCLASS.hIcon
member to NULL
is not a good idea, because then the icon of the mainframe is replaced by a default icon (even though it looks fine on the taskbar...) - I didn't notice that during my first test.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您必须向程序添加清单(或编辑现有清单)才能关闭 DPI 虚拟化。它应该看起来像这样:
这不太可能导致几个新问题。您想了解的所有内容都在此 MSDN 库文章。
You will have to add a manifest to your program (or edit the existing one) to turn DPI Virtualization off. It should look like this:
That's not unlikely to cause several new problems. Everything you'd want to know about this is covered very well in this MSDN Library article.