这是处理Windows 10运行时DPI(文本大小)变化的后续问题
Windows 10允许运行时更改DPI而无需重新启动(登录/注销)系统。当DPI发生变化,并且系统检测到应用程序无法处理运行时DPI变化时,它按像素缩放应用程序窗口。这与以前版本的Windows中看到的兼容性行为相似。除了在这种情况下,系统甚至可以缩小,而不仅仅是扩大。
奇怪的是,应用程序重启没有帮助。系统似乎记得应用程序没有正确响应缩放的变化,并且仍然表现得像以前一样(应用程序认为缩放没有改变,系统按像素缩放窗口)。只有系统登录/注销才能帮助重置到正确的缩放。
是否有办法以编程方式重置兼容模式,以允许用户重新启动应用程序,而不是整个系统?(这是迈向完全支持运行时DPI更改的第一步)
我正在使用c++ Builder,所以我正在寻找一个纯WinAPI解决方案,没有WinForms。
事实证明,问题不是由应用程序不响应DPI更改引起的。当DPI更改时,应用程序是否正在运行,这实际上并不重要。
根本原因是当DPI在Windows会话期间更改时,只有每个监视器的DPI更改(即使在单个监视器系统上)。系统(遗留)DPI未更新。
因此,当您运行一个应用程序时,它没有声明每个监视器的DPI感知,并且依赖于系统DPI,它运行时就好像DPI没有改变一样。但是系统会根据新的DPI对窗口像素进行缩放。
只有在下线/登录后,系统DPI才会与监视器DPI保持一致。
一种解决方案是通过将dpiAwareness
设置为PerMonitorV2
(以及额外的PerMonitor
值并将dpiAware
设置为True/PM
以向后兼容旧版本的Windows 10和Windows 8.1)在应用程序清单中声明支持:
<?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/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
应用程序窗口缩放必须重新实现,以使用新的GetDpiForMonitor
WinAPI函数而不是传统的GetDeviceCaps(DC, LOGPIXELSX/LOGPIXELSY)
。