设置高 DPI 时防止我的 Win32 应用程序的 UI 元素按比例放大
Posted
技术标签:
【中文标题】设置高 DPI 时防止我的 Win32 应用程序的 UI 元素按比例放大【英文标题】:Prevent my Win32 application's UI elements from being scaled up when high DPI is set 【发布时间】:2013-04-10 08:02:04 【问题描述】:当窗口设置为“将文本大小调整为“125%”时,我的 Win32 应用程序的 UI(但不是它的窗口大小)会按比例放大。这会导致文本字符串被截断并且 UI 元素从边缘消失窗户。
我想防止这种情况发生,这样文本就不会被放大,并且应用程序可以正确显示。由于让这个旧的旧版应用程序正确识别 DPI 的时间投入太高,我只想通过调整 UI 元素的大小来防止 Windows 破坏 UI 来使该应用程序可用。
我曾尝试在启动期间调用 SetProcessDPIAware(),但当它不起作用时,表明应用程序在其清单中是 DPI Aware。但是,这些措施都没有任何效果。
我用来指定 DPI 感知的清单片段:
<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<asmv3:application
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:windowsSettings
xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
【问题讨论】:
“manifest”和“assembly”听起来不像标准的 C++。您使用的是 C++/CLI 还是 C#?您应该正确地重新标记您的问题。 @ArneMertz,不幸的是,微软也为常规 C++ 制作了必要的清单。例如,这是获得 UAC 提升的方法。 @ArneMertz 程序集清单是标准的 Win32 并且从 Windows XP 开始使用,当时它允许主题化(除其他外),然后是 Vista/7,它指定了所需的权限和提升。 mackenir,这是视图还是对话框? @Deanna “需要计算标签定位”。确实——考虑到在 WTL 中实现这样的简单东西所需的努力,我不会打扰 :)。很遗憾,没有办法只说“Windows,请不要通过无能地尝试扩大我的 UI 来破坏我的 UI”... 【参考方案1】:我在使用 SDL OpenGL 时遇到了类似的问题。在不知情的应用程序上进行 Windows DPI 缩放的实现非常糟糕,例如放大全屏视口和裁剪侧面。
我对清单没有任何运气。
我可以通过调用SetProcessDPIAware();
来解决它,但它必须在 SDLmain 执行之前发生。也许您的“启动期间”还不够早。我将它用作main
函数之前的全局变量初始化器:
BOOL dpi_result = SetProcessDPIAware();
int main( int argc, char **argv )
//...
【讨论】:
【参考方案2】:对于 125% 的字体缩放,DPI 感知设置不相关。发生的情况是文本将大 25%,然后您有责任扩展您的 UI 以匹配。您的对话框通常需要大 25% 才能容纳更大的文本。您不仅需要缩放尺寸,还需要缩放位置。由你来编写所有这些代码。或者使用为您完成此任务的 UI 框架。
对于大于 125% 的字体缩放,DPI 感知设置开始发挥作用。会发生什么:
-
如果您的应用未标记为 DPI 感知,Windows 将使用光栅图像调整大小来缩放您的应用。这将导致您的视觉元素被像素化。
如果您的应用被标记为 DPI 感知,Windows 将忠实地呈现您的应用。同样,您有责任调整 UI 以适应文本。
这个MSDN article拥有所有血腥细节。
回到您的具体问题。你说:
我想防止这种情况发生,这样文本就不会被放大,并且应用程序可以正确显示。
换句话说,您是说您想忽略用户的字体缩放设置并以 100% DPI 渲染,而不考虑他们的意愿。您可以通过将所有文本的大小减小 25% 来做到这一点。我真的不建议你这样做。
【讨论】:
对话框的大小通常不是以对话框单元为单位的吗,它已经基于字体大小了吗? 好点@Mark - 这应该放在答案中以使其更正确。 @David 回滚了我的修订,如果你想看看它在历史中。【参考方案3】:这只是对在此问题上错误怀疑 MFC / Windows 7 的警告。
我遇到了同样的问题。我们的(较旧的)MFC 应用程序在 Windows 7 上运行且字体设置为 125% 时,以错误的大小显示对话框。控件被缩放,但每个对话框都小了大约 25%。
起初,我在对话框代码中搜索了可能设置其大小/位置的任何内容。然后我看到网上很多人在将MFC应用程序迁移到Windows 7时遇到对话框大小的问题,这增加了我对MFC/Windows 7的怀疑。
最后,我阅读了一个类似的讨论,发现 spy++ 的维护者评论说,它在退出时保存大小/位置的功能在字体/DPI 更改后强制窗口大小错误。我们的软件也在做同样的事情,但代码在主应用程序中,而不是在对话框中。
【讨论】:
【参考方案4】:在我团队的应用程序中,我们在程序集属性而不是应用程序属性上具有 asmv3 的 xmlns 属性。
代替这一行:
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
这一行:
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0' xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
我获取了我产品的应用清单并将其剥离为仅父节点和父节点。供参考:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
【讨论】:
以上是关于设置高 DPI 时防止我的 Win32 应用程序的 UI 元素按比例放大的主要内容,如果未能解决你的问题,请参考以下文章