You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2下WM_GETDPISCALEDSIZE未触发咨询

DPI感知窗口跨显示器移动时WM_GETDPISCALEDSIZE消息缺失问题分析

问题核心

你创建了基于DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2的WinAPI应用,在两台分辨率相同但缩放比例分别为100%和150%的显示器间移动窗口时,发现有时只收到WM_DPICHANGED消息,而非预期的先WM_GETDPISCALEDSIZE后WM_DPICHANGED的消息序列。

原因拆解

  1. 窗口最大化状态的影响
    你的代码中,窗口创建时指定了WS_MAXIMIZE样式,并且立即调用ShowWindow(hwnd, SW_SHOWMAXIMIZED)让窗口处于最大化状态。当最大化窗口跨DPI显示器移动时,系统会直接接管窗口尺寸调整,适配目标显示器的最大化规格,这个流程不会触发WM_GETDPISCALEDSIZE——该消息的设计目的是让应用在窗口处于正常(非最大化/非最小化)状态下,自定义调整缩放后的窗口尺寸,只有这种场景才会触发。

  2. 系统消息触发逻辑
    根据WinAPI官方定义,WM_GETDPISCALEDSIZE仅在两个条件同时满足时发送:

  • 窗口位置变化导致其所在显示器的DPI发生变更
  • 窗口处于可自由调整尺寸的状态(正常状态)

如果窗口是最大化或最小化,系统会跳过应用自定义尺寸的环节,直接发送WM_DPICHANGED通知DPI变更完成。

代码修正与验证

针对你的测试代码,调整以下两点即可复现预期的消息序列:

  1. 移除窗口样式中的WS_MAXIMIZE,保留可最大化的按钮(WS_MAXIMIZEBOX)即可:
DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU |
    WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME; // 去掉WS_MAXIMIZE
  1. 将窗口显示方式改为正常状态,而非直接最大化:
ShowWindow(hwnd, SW_SHOW); // 替换SW_SHOWMAXIMIZED

修改后,先确保窗口处于正常非最大化状态,再跨显示器移动,就能按预期先收到WM_GETDPISCALEDSIZE,再收到WM_DPICHANGED。

额外注意事项

  • 如果窗口仅部分区域跨到不同DPI的显示器(而非整个窗口切换到目标显示器),系统也可能不会发送WM_GETDPISCALEDSIZE,只有当窗口的主要显示区域切换到新DPI显示器时,才会触发完整的消息序列。
  • 确认测试环境为Windows 10 1709及以上版本,PER_MONITOR_AWARE_V2在更早版本中存在兼容性问题。

内容的提问来源于stack exchange,提问作者Irbis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:12:28