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

WM_DPICHANGED异常及跨显示器DPI获取不符问题求助

解决Per-Monitor DPI感知的两个常见问题

嘿,我来帮你拆解这两个DPI感知的问题,都是新手入门时容易踩的坑,咱们一步步来搞定:

1. 应用启动时收到WPARAM/LPARAM全为0的WM_DPICHANGED消息

这种情况其实是系统在应用初始化阶段发送的预通知消息,此时窗口还没完全完成创建和初始化,参数自然是空的。你只需要在消息处理逻辑里加个判断就能跳过:

case WM_DPICHANGED:
    if (wParam == 0 && lParam == 0) {
        // 忽略初始化阶段的空参数消息
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    // 正常处理DPI变更逻辑
    // ...
    break;

另外要确认你已经正确设置了Per-Monitor DPI感知上下文,Win10 1607及以上版本推荐用:

SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);

避免使用旧的SetProcessDPIAware(),它会强制应用为系统DPI感知,导致Per-Monitor模式失效。

2. GetDeviceCaps始终返回固定DPI,无法获取对应显示器的正确值

GetDeviceCaps(hDC, LOGPIXELSX/LOGPIXELSY)的局限性在于它依赖于你传入的设备上下文(DC):如果你的DC是从主窗口或默认屏幕获取的,它只会返回主显示器的DPI值,根本不会感知当前窗口所在的显示器。

解决办法是使用Win10引入的Per-Monitor DPI专用API:

方法1:直接获取窗口所在显示器的DPI

用GetDpiForWindow可以直接拿到窗口当前所在显示器的DPI,简单高效:

UINT dpi = GetDpiForWindow(hWnd);
// dpi就是当前窗口所在显示器的DPI值(比如144对应150%,168对应175%)

方法2:获取指定显示器的DPI

如果需要更精细的控制,先拿到窗口对应的显示器句柄,再调用GetDpiForMonitor:

HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
UINT dpiX, dpiY;
GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
// dpiX和dpiY就是目标显示器的水平/垂直DPI

记得要包含头文件Shcore.h,并链接Shcore.lib才能使用这些API。

另外可以额外验证:用GetWindowRect获取窗口的位置,确认窗口确实位于175%缩放的显示器上,避免窗口跨屏导致的判断误差。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:15:09