windows平台用enumdisplaysettings获取当前显示器刷新率最直接可靠,需传入有效设备名和enum_current_settings标志,初始化devmode结构体dmsize,读取dmdisplayfrequency字段(单位hz),为0时表明驱动未报告。

Windows平台用 EnumDisplaySettings 获取当前显示器刷新率
在 Windows 上,EnumDisplaySettings 是最直接、最可靠的方式获取当前活动显示器的垂直刷新率(dmDisplayFrequency),它返回的是显卡驱动实际提交给显示器的值,而非 EDID 声称的最大能力或系统设置界面里显示的“推荐”值。
关键点在于:必须传入当前主显示器名称(如 \.DISPLAY1)和 ENUM_CURRENT_SETTINGS 标志,否则可能读到过时缓存或默认配置。
- 调用前建议先用
EnumDisplayDevices确认主显示器设备名,避免硬编码NULL(此时行为依赖系统策略,不稳定) -
DEVMODE结构体需初始化为 0,并设置dmSize = sizeof(DEVMODE),否则EnumDisplaySettings可能失败并静默返回FALSE - 返回的
dmDisplayFrequency为 0 表示驱动未报告刷新率(常见于某些虚拟显示器或远程桌面会话),此时不应当作 60Hz 处理
Linux X11 下用 xrandr 解析输出并提取 --verbose 中的刷新率
X11 没有统一 API 直接查“当前生效刷新率”,xrandr 命令行工具是事实标准。核心思路是解析 xrandr --verbose 输出中当前激活输出(标记为 connected (primary) 或含 current 行)所对应的 Monitor name 后紧跟的 preferred 或带 + 的模式行,再匹配该模式的 h: ... v: ... 部分计算刷新率。
注意:xrandr --query 不够用——它只显示分辨率和是否启用,不包含时序参数;必须用 --verbose 才有完整信息。
- 执行
xrandr --verbose后,查找类似HDMI-1 connected primary 1920x1080+0+0 (0x47) normal (native) <strong>60.00</strong>Hz这样的行,其中60.00是最终结果 - 若输出中某模式行含
+(如1920x1080 60.00*+),星号表示当前使用,加号表示首选,优先取带+的数值 - 不能仅靠
grep "connected"就认为该输出在用——有些显示器即使物理断开也可能显示connected (off),需结合current或+标记判断
Linux Wayland 下无法通过用户态 API 获取真实刷新率
Wayland 协议本身不向客户端暴露刷新率信息。所有主流 compositor(sway, gnome-shell, hyprland)均未提供标准接口供应用查询当前帧率。部分 compositor 提供私有 D-Bus 接口(如 sway 的 swaymsg -t get_outputs),但返回的 refresh_rate 字段常为 0 或固定值(如 60),不代表实际 VSync 频率。
根本原因:Wayland 将时序控制完全交给 compositor,客户端只管提交帧,不参与调度。所谓“当前刷新率”对应用而言没有明确定义——它取决于 compositor 的帧合并策略、GPU 负载、vsync 开关等动态因素。
- 若你正在开发 OpenGL/Vulkan 应用,唯一可靠方式是测量两次
glFinish()或vkQueueWaitIdle()的时间差,再取倒数估算——但这反映的是渲染吞吐,不是显示器物理刷新率 -
drmModeGetConnector和drmModeGetEncoder在用户态可读,但需要 root 权限且结果与当前生效设置无必然关联(尤其多显示器混用场景) - 不要尝试解析
/sys/class/drm/*/modes——该路径只列支持模式,不表示当前使用哪个
macOS 上用 CGDisplayModeGetRefreshRate 但需注意返回值含义
macOS 提供了清晰的 Core Graphics API:CGMainDisplayID() 获取主屏 ID,再传给 CGDisplayModeGetRefreshRate(CGDisplayCopyDisplayMode(displayID))。但要注意:该函数返回值并非总是整数,例如 Pro Display XDR 在 120Hz 模式下可能返回 119.98,而 MacBook Pro 内建屏在自适应刷新(ProMotion)开启时,返回值是当前动态帧率(如 48/60/120),不是固定值。
- 必须检查
CGDisplayModeGetRefreshRate返回是否 > 0,某些老旧模式(如镜像模式)可能返回 0.0 - 若需稳定帧同步(如游戏循环),不要依赖该值做硬性 vsync 控制——macOS 的
CADisplayLink才是正确抽象,它自动适配当前刷新策略 - 调用
CGDisplayCopyDisplayMode后记得用CFRelease释放,否则泄漏CGDisplayModeRef
跨平台代码里最容易被忽略的是:Windows/Linux/macOS 对“当前刷新率”的定义并不一致——Windows 和 macOS 返回的是显卡驱动协商后的实际提交值,X11 下是 xrandr 解析出的模式时序计算值,而 Wayland 下根本没有权威值。如果你的应用逻辑强依赖该参数(比如音视频同步或帧率锁定),务必在目标平台实测验证,而不是假设它等于显示器标称值或系统设置界面显示的数字。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











