Windows用GetSystemMetrics获取物理分辨率,GetDpiForWindow(需DPI感知)得逻辑缩放;Linux依赖xrandr或环境变量;macOS通过NSScreen一次性获取逻辑尺寸与backingScaleFactor。

Windows平台用GetSystemMetrics和GetDpiForWindow最可靠
在Windows上,GetSystemMetrics(SM_CXSCREEN)和GetSystemMetrics(SM_CYSCREEN)能拿到主屏原始像素宽高,但注意:它不随DPI缩放变化——返回的是物理像素值,不是逻辑像素。真正反映UI布局用的“逻辑分辨率”,得结合DPI缩放算。
获取当前窗口DPI缩放比例推荐用GetDpiForWindow(Windows 10 1607+),它返回每英寸点数(如96、120、144),除以96就是缩放百分比(120/96 = 1.25 → 125%)。旧系统可用GetDpiForSystem,但它是全局DPI,不感知多显示器不同缩放。
- 必须传入一个有效的窗口句柄(
HWND),传NULL会失败或返回默认值 - 如果程序未声明支持DPI感知(清单中没设
dpiAware=true),GetDpiForWindow可能始终返回96,哪怕系统设了150% - 多显示器场景下,每个屏幕可有独立DPI,务必对目标窗口调用,别用主屏假设
Linux下靠xrandr命令或X11/XCB API取原生分辨率
Linux没有统一API暴露DPI缩放——桌面环境(GNOME/KDE)自己实现缩放,应用层通常不直接读取。分辨率可用xrandr --query解析输出,例如:
Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 8192 x 8192
其中current 1920 x 1080即当前主屏逻辑分辨率。DPI缩放比例需查环境变量或配置文件:gsettings get org.gnome.desktop.interface scaling-factor(GNOME)或echo $QT_SCALE_FACTOR(Qt应用)。
本地 Ollama 文生图工具。使用 x/z-image-turbo 模型生成图片,分辨率 1024x1024,每张图约耗时 90 秒。当用户说"生成图片"、"文生图"、"画一张图"、或提交中文提示词生成图像时使用。
立即学习“C++免费学习笔记(深入)”;
-
xrandr输出格式不稳定,不同版本字段顺序可能变,建议用--verbose并匹配current行+数字对 - Wayland下
xrandr不可用,得走xdg-output协议(需Wayland客户端库),普通C++程序几乎无法直接获取 - 没有“系统级DPI”概念,
xdpyinfo | grep dots返回的dots per inch是X server硬编码值(常为96),和实际UI缩放无关
macOS用NSScreen一次拿齐分辨率与缩放因子
macOS最干净:每个NSScreen对象自带frame(逻辑坐标)、backingScaleFactor(缩放因子,通常是2.0视网膜屏)、pixelWidth/pixelHeight(物理像素)。C++需通过Objective-C++桥接:
#import <AppKit/AppKit.h>
NSScreen* screen = [NSScreen mainScreen];
CGFloat scale = [screen backingScaleFactor]; // 1.0 或 2.0
NSRect frame = [screen frame]; // 逻辑尺寸,如 {0,0,1440,900}
NSInteger pW = [screen pixelWidth]; // 物理像素,如 2880
- 必须链接
-framework AppKit,且源文件后缀改为.mm启用Objective-C++ -
backingScaleFactor不是百分比,而是乘数:2.0对应200%缩放,1.0对应100% - 主屏不等于活跃屏,用
[NSScreen screens]遍历所有屏时,注意frame.origin.y在macOS向下增长(Y轴原点在左下)
跨平台时别信“一次封装就搞定”的工具库
像SDL_GetDesktopDisplayMode或glfwGetVideoMode只返回主显示器原生分辨率,不提供DPI信息;sf::VideoMode::getDesktopMode()同理。它们对游戏渲染够用,但做UI适配远远不够。
真正跨平台UI框架(如Qt、ImGui)内部都各自实现了平台适配逻辑:Qt读QScreen::devicePixelRatio(),ImGui靠后端设置io.DisplayFramebufferScale。纯C++项目若需精确适配,建议按平台条件编译,而不是强求统一接口。
- Windows上
GetDpiForWindow要求进程DPI感知,否则缩放值恒为1.0——这比代码写错更难调试 - Linux下“DPI缩放”本质是字体/图标/窗口管理器各自放大,应用无统一钩子,硬要取只能走DBus或环境变量,且不保证一致
- macOS的
backingScaleFactor虽稳定,但部分外接显示器可能报告1.0(即使物理是Retina),需结合hasShadow等属性辅助判断

















