当应用程序不处理DPI的运行时更改时,如何重置强加于应用程序的兼容模式



这是处理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)

最新更新