getdpiforwindow是windows 10 1607+及win11获取窗口dpi的首选api,返回dpi值(如120),除以96得缩放比;需提前设置permonitorv2感知级别,否则可能恒返96。

Windows平台用GetDpiForWindow最可靠
在Windows 10 1607+(含Win11),GetDpiForWindow是获取当前窗口DPI缩放比例的首选方式,返回值是每英寸点数(如96、120、144),除以96即得缩放百分比(如120/96=1.25 → 125%)。它比旧API(如GetDeviceCaps)准确,且支持Per-Monitor DPI Aware程序。
使用前必须确保程序声明了DPI感知级别(否则系统会虚拟化缩放,返回固定96):
- 在manifest中设置
dpiAware=true或dpiAwareness="perMonitorV2" - 或调用
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)(需Windows 10 1703+) - 若未设置,
GetDpiForWindow可能返回96,即使系统设为150%
GetScaleFactorForMonitor只适用于多显示器不同缩放场景
当用户为不同显示器设置了不同缩放比例(比如主屏125%,副屏100%),GetScaleFactorForMonitor能按指定HMONITOR获取对应缩放因子(返回100、125、150等整数),但它不返回小数精度,也不直接给出DPI值。
典型用法是先用MonitorFromWindow拿到当前窗口所在显示器句柄,再传入该函数:
HMONITOR hmon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
SCALE_FACTOR scale;
if (SUCCEEDED(GetScaleFactorForMonitor(hmon, &scale))) {
// scale 可能是 SCALE_FACTOR_100_PERCENT、SCALE_FACTOR_125_PERCENT 等
}
注意:SCALE_FACTOR枚举值不是百分比数字,需映射转换;且该函数在旧系统(如Win8.1)不可用,需检查GetProcAddress。
Linux和macOS没有统一API,需走平台特定路径
Linux下无标准接口,主流方案依赖桌面环境:
- X11:读取
_NET_SCALE_FACTOR属性(GNOME)或QT_SCALE_FACTOR/GDK_SCALE环境变量 - Wayland:通过
xdg-output协议或wp-output-layout获取,但需Wayland客户端库支持 - Qt或GTK应用可直接用
QGuiApplication::primaryScreen()->devicePixelRatio()或gdk_monitor_get_scale_factor()
macOS相对明确:调用NSScreen.mainScreen().backingScaleFactor(Objective-C/Swift),C++需通过objc_msgSend桥接,或用CGDisplayGetScaleFactorForDisplay配合CGMainDisplayID()。注意:后者返回的是逻辑像素到设备像素的比率(如2.0),即“缩放因子”,非百分比。
跨平台封装时别硬套Windows逻辑
很多开发者试图用“DPI / 96”统一所有平台,但实际含义不同:
- Windows:DPI值(96=100%),缩放由系统UI层控制
- macOS:backingScaleFactor(1.0/2.0/3.0),直接决定绘制分辨率
- Linux:环境变量或Wayland协议返回的浮点因子(如1.25),但行为因WM而异
真正需要适配的是渲染和布局逻辑——比如字体大小乘以缩放因子,控件尺寸按devicePixelRatio()调整。硬写一个get_system_scale_factor()函数时,务必标注各平台返回值语义,并预留fallback路径(如默认1.0)。忽略这点,多显示器切换或HiDPI唤醒后界面错位几乎必然发生。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











