GetDpiForSystem返回系统默认DPI(如96对应100%),需除以96.0得缩放因子,但仅适用于单屏基础适配;多屏场景应使用GetDpiForWindow配合Per-Monitor V2感知获取当前显示器真实缩放值。

Windows平台下用GetDpiForSystem获取系统级缩放因子
Windows 10 1703+ 和 Windows 11 默认启用Per-Monitor DPI Awareness,但GetDpiForSystem返回的是系统全局DPI(通常为96对应100%),不是当前显示器的实际缩放比例。它适合做基础适配,但不能反映多显示器不同缩放时的差异。
- 返回值是DPI数值(如144表示150%),需除以96.0得到缩放因子:
double scale = GetDpiForSystem() / 96.0; - 该函数无需额外manifest声明,但仅反映“系统默认DPI”,在多屏不同缩放场景下会误导——比如主屏125%、副屏100%,它仍返回125%对应的DPI
- 若进程未声明DPI Awareness(通过manifest或
SetProcessDpiAwareness),调用可能被系统虚拟化,结果不可靠
获取当前窗口所在显示器的实际缩放因子:用GetDpiForWindow
这是更实用的方式,尤其对GUI程序——它返回窗口当前所在显示器的DPI值,且要求进程已启用Per-Monitor DPI Awareness。
- 必须先调用
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)(推荐V2)或通过manifest声明dpiAwareness="perMonitorV2" -
UINT dpi = GetDpiForWindow(hwnd); double scale = dpi / 96.0;—— 这才是真实生效的缩放因子 - 注意:窗口跨屏移动时,该值会变;应在
WM_DPICHANGED消息中重新获取并调整UI布局 - 若未正确设置DPI Awareness,
GetDpiForWindow可能始终返回96(即1.0),而非实际值
Linux/X11下没有统一API,靠环境变量和Wayland协议探测
X11本身不提供标准DPI查询接口,主流做法是读取QT_SCALE_FACTOR、GDK_SCALE等桌面环境变量,或解析xrandr --listmonitors输出结合物理尺寸估算。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- GNOME/KDE应用常依赖
gdk_monitor_get_scale_factor()(GTK)或QScreen::devicePixelRatio()(Qt),底层由桌面环境提供 - 纯X11程序可尝试读
XCURSOR_SIZE或GDK_SCALE,但不可靠——有些环境根本不设这些变量 - Wayland下需通过xdg-output协议(如wl_output的scale事件)获取,但需Wayland客户端库支持,且C++原生调用复杂度高
- 没有
GetDpiForWindow那样的系统级函数,跨桌面环境兼容性差,建议封装成运行时探测逻辑而非编译期假设
macOS用NSScreen的backingScaleFactor
Cocoa平台最直接:每个NSScreen对象都暴露backingScaleFactor,返回1.0(标准)、2.0(Retina)或更高(如3.0用于Pro Display XDR)。
立即学习“C++免费学习笔记(深入)”;
- 主线程调用:
[[NSScreen mainScreen] backingScaleFactor]获取主屏因子;遍历[NSScreen screens]可得各屏值 - 该值与系统“缩放”设置强相关——“更大文字”模式下可能返回2.0,即使物理非Retina屏(macOS会软件插值)
- 需链接AppKit.framework,且只能在Objective-C++混合文件中使用;纯C++项目需封装bridge层
- 注意:macOS不区分“系统级”和“显示器级”——每个屏幕独立报告,不存在全局缩放因子概念
跨平台代码里最容易出错的是把Windows的GetDpiForSystem当成真·当前屏缩放,或者在Linux上硬编码2.0假设Retina——实际场景中,用户可能手动设为125%、175%,甚至不同显示器混用。真正可靠的逻辑永远基于运行时获取+监听变化,而不是启动时查一次就缓存。

















