防止在设置高 DPI 时放大 Win32 应用程序的 UI 元素
Prevent my Win32 application's UI elements from being scaled up when high DPI is set
当windows设置为"调整文本大小为"125%"时,我的Win32应用程序的UI(但不是其窗口大小)缩放。这会导致文本字符串被截断,UI元素从窗口边缘消失。
我想防止这种情况发生,这样文本就不会按比例放大,应用程序也会正确显示。因为让这个旧的遗留应用程序正确地感知dpi的时间投入太高了,我只是想通过防止Windows通过调整UI元素来破坏UI,从而使应用程序可用。
我已经尝试在启动期间调用SetProcessDPIAware(),当它不起作用时,表明应用程序在其清单中是DPIAware。然而,这些措施都没有任何效果。
我用来指定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>
我在使用SDL OpenGL时有类似的问题。Windows DPI在不知情的应用程序上的缩放实现得非常糟糕,比如在全屏视图中缩放和裁剪。
我没拿到舱单。
我能够通过调用SetProcessDPIAware();
来解决它,但它必须在SDLmain执行之前发生。也许你的"创业期间"还不够早。我将它用作main
函数之前的全局变量初始化器:
BOOL dpi_result = SetProcessDPIAware();
int main( int argc, char **argv )
{
//...
对于125%的字体缩放,DPI感知设置无关紧要。会发生的是,文本会变大25%,然后你就有责任扩大你的UI来匹配。你的对话框通常需要扩大25%以适应更大的文本。你不仅需要调整大小,还需要调整位置。所有这些都由您来编码。或者使用一个UI框架来帮你完成。
对于大于125%的字体缩放,DPI感知设置开始发挥作用。结果是:
- 如果你的应用程序没有标记DPI感知,Windows将使用光栅图像调整大小缩放你的应用程序。这将导致你的视觉元素像素化。 如果你的应用程序被标记为DPI感知,Windows将忠实地呈现你的应用程序。同样,你有责任调整你的UI以适合文本。
这篇MSDN文章有所有血腥的细节。
回到你的具体问题。你说:
我想防止这种情况发生,这样文本就不会按比例放大,应用程序就会正确显示。
换句话说,你是在说你想忽略用户的字体缩放设置,并以100% DPI呈现,而不管他们的意愿。你可以通过将所有文本的大小减小25%来做到这一点。我真的不建议你这么做。
这只是一个警告,错误地怀疑MFC/Windows 7在这个问题上。
我也遇到了同样的问题。我们的(旧的)MFC应用程序,当在windows 7上运行时,字体设置为125%,显示的对话框大小错误。控件是缩放的,但是每个对话框都太小了25%。
首先,我在对话框代码中搜索任何可能设置其大小/位置的东西。然后我看到网上很多人在将MFC应用程序迁移到Windows 7时遇到对话框大小的问题,这错误地增加了我对MFC/Windows 7的怀疑。
最后,我读了一个类似的讨论,发现了一个由spy++维护者的评论,在退出时保存大小/位置的功能在字体/DPI更改后迫使窗口变成错误的大小。我们的软件也在做同样的事情,但是代码在主应用程序中,而不是在对话框中。
在我的团队的应用程序中,我们有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>
- WM_CTLCOLORSTATIC从未在WIN32应用程序中触发
- 如何从 Win32 C++ 应用程序输出到父控制台窗口?
- 将 Win32/WinAPI 应用程序移植到 wxWidgets
- 如何在 Win32 C++控制台应用程序中调用 UWP 类库
- 如何在 Win32 控制台应用程序中注册不可见的窗口类?
- 是否可以将键盘输入绑定到 Win32 中的单个应用程序?
- VS2017 中缺少 Win32 控制台应用程序.如何创建C++空项目?
- 在通用 Windows 应用程序C++上使用 win32 DLL 库
- C++ Win32 列表框和滑块创建 Windows 应用程序
- 如何在 Linux/Apache 虚拟主机上运行 win32 控制台应用程序?
- SWIG和Mingw-64与Python一起使用...不是有效的 Win32 应用程序
- 在 Win32 应用程序中承载 GTK+3 上下文
- Electron应用程序和Win32本机桌面应用程序之间的进程间通信
- 开发如何解决错误193:%1不是Dev C 中的Win32应用程序
- 您如何使用Winrt创建经典的Win32应用程序窗口
- 是否有一种简单的方法可以从普通的 win32 C++代码向应用程序见解提供数据?
- 链接错误时,使用CLION/CMAKE/MSVC 2015编译WIN32应用程序
- 如何在VS 2017 C++Win32应用程序中打印出gethostname结果
- 我如何将Win32应用程序迁移到X64
- 从"Resource Files"文件夹加载文件C++ Windows 应用程序 (win32)