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

How to reset compatibility mode imposed on application when it does not handle runtime change of DPI?

这是

的后续问题

Windows 10 允许运行时更改 DPI 而无需重新启动系统 (logon/logoff)。当 DPI 更改时,系统检测到应用程序无法处理运行时 DPI 更改,它会按像素缩放应用程序 windows。与以前版本 Windows 中看到的兼容性行为有什么相似之处。除了在这种情况下,系统甚至可以缩小,而不仅仅是放大。

奇怪的是,应用程序重启没有帮助。系统似乎记得应用程序没有正确响应缩放比例的变化并且仍然像以前一样运行(应用程序认为缩放比例没有改变并且系统按像素缩放 windows)。只有系统 logon/logoff 有助于重置为正确的缩放比例。

有没有办法以编程方式重置兼容模式,让用户只重启应用程序,而不是整个系统? (这是全面支持运行时 DPI 更改的第一步)


我正在使用 C++ Builder,所以我正在寻找一个纯 WinAPI 解决方案,没有 WinForms。

原来问题不是应用程序没有响应 DPI 变化引起的。如果 DPI 更改时应用程序处于 运行ning 状态,这实际上并不重要。

根本原因是在 Windows 会话期间更改 DPI 时,只有每个显示器的 DPI 发生变化(即使在单个显示器系统上)。系统(旧版)DPI 未更新。

因此,当您 运行 一个应用程序没有声明每个显示器的 DPI 感知,并且依赖于系统 DPI 时,它 运行 就像 DPI 没有改变一样。但是系统将其 windows 像素缩放到新的 DPI。

只有在logoff/logon之后,系统DPI才与显示器DPI对齐。


一个解决方案是 declare the support in an application manifest 通过将 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>

并且必须重新实现应用程序 window 缩放才能使用新的 GetDpiForMonitor WinAPI function instead of the legacy GetDeviceCaps(DC, LOGPIXELSX/LOGPIXELSY)