我的 Win32 C++ 应用程序在资源文件中有一个清单,其中包含:
<asmv3:windowsSettings xmlns='https://schemas.microsoft.com/SMI/2016/WindowsSettings'>
<dpiAwareness>PerMonitorV2,PerMonitor</dpiAwareness>"
</asmv3:windowsSettings>
在程序开始时,我调用
GetAwarenessFromDpiAwarenessContext()
来检查 DPI_AWARENESS
并返回 DPI_AWARENESS_PER_MONITOR_AWARE
。到目前为止,一切都很好。
我有两个显示器。一个是 3840x1200 超宽,另一个是真正的 4K。当我查询缩放信息时,它们都声称 DPI 为 96。显示设置中的 DWM 未缩放这两个显示器。使用
EnumDisplayMonitors()
给出:
\\.\DISPLAY1
monitor rect: (0,0)-(3840,1200)
work rect: (0,0)-(3840,1200)
DPI (effective): 96,96
DPI (angular): 91,91
DPI (raw): 92,92
BPP: 32
resolution: 3840,1200
frequency: 144
\\.\DISPLAY2
monitor rect: (3240,-2160)-(7080,0)
work rect: (3240,-2160)-(7080,0)
DPI (effective): 96,96
DPI (angular): 156,159
DPI (raw): 157,160
BPP: 32
resolution: 3840,2160
frequency: 60
我猜想当我将窗口从一个监视器移到另一个监视器时我的应用程序没有收到
WM_DPICHANGED
消息的原因是因为Windows认为它们的DPI都是96。但是我已经在我的清单中告诉Windows并且验证了我的应用程序是每个显示器 DPI 感知的事实。
谁能解释这个差异?在这种情况下如何开发高 DPI 感知应用程序?
编辑 1: 我确定将第二台显示器的缩放比例更改为 150% 会导致当我将它拖到该显示器时,我的应用程序会收到
WM_DPICHANGED
消息。
总而言之,具有 dpi 感知能力意味着您的 DPI 在所有显示器和窗口中都是默认值 (96)。默认值不是显示器本身的默认 DPI。然后该值由 DWM 比例因子更改,该比例因子与另一个比例因子之间的差异是导致消息发送的原因。
编辑2:
所以我重构了我的应用程序以在收到消息时使用缩放。我打开了我的 4K 显示器。我将它设置为 150%。主显示器是100%。当我将应用程序拖到 4K 显示器上时,我DO NOT 收到 WM_DPICHANGED 消息。当我上周尝试时,我确实收到了这条消息。
注意:如果我在 4K 显示器上启动应用程序,我会得到正确的比例因子(在本例中为 x 2)。当我将窗口拖到它上面时,我的顶级 Win32 窗口没有收到更改通知。我断言在程序启动时是DPI_AWARENESS_PER_MONITOR_AWARE,所以我知道不是那样。
进一步:当我将应用程序放在另一台显示器上并在显示属性中调整显示器的缩放比例时,我没有收到此消息。