Windows用EnumDisplaySettings获取当前刷新率,需配合EnumDisplayDevices获取真实设备名;Linux用xrandr解析输出;macOS用CGDisplayModeGetRefreshRate;VSync状态无法跨平台直接查询。

Windows平台用 EnumDisplaySettings 读取当前刷新率
Windows下最直接的方式是调用GDI API的 EnumDisplaySettings,它能获取当前活动显示器的 DEVMODE 结构体,其中 dmDisplayFrequency 字段就是垂直同步刷新频率(单位:Hz)。注意这不是“VSync开关状态”,而是当前生效的扫描频率。
常见错误是传入错误的设备名——必须用 EnumDisplayDevices 获取真实设备名(如 "\.DISPLAY1"),不能硬写 "DISPLAY" 或空字符串;否则在多屏或重命名显示器时返回0或失败。
- 调用前确保
dmSize = sizeof(DEVMODE),否则Windows忽略后续字段 - 只对主显示器调用?错——需循环遍历所有显示器,用
EnumDisplayDevices+EnumDisplaySettings组合获取每块屏的值 - 返回值为0表示失败,此时应检查
GetLastError(),常见原因是设备名无效或权限不足(极少)
DEVMODE dm = {};
dm.dmSize = sizeof(dm);
if (EnumDisplaySettings(L"\\.\DISPLAY1", ENUM_CURRENT_SETTINGS, &dm)) {
int freq = dm.dmDisplayFrequency; // 如60、144、240
}
Linux上通过 xrandr 解析EDID或调用XRandR API
Linux没有统一系统API,主流做法是执行 xrandr --verbose 命令并解析输出——其中每块输出(output)的当前模式行会带 + 或 <code>*n 标记,* 表示当前激活模式,后面的数字即刷新率。EDID解析更底层但复杂,一般没必要。
容易踩的坑是没处理多输出场景:脚本或C++中调用 popenv 执行 xrandr 时,必须按 connected 状态过滤,并识别当前激活的 primary 或 current 行。X11环境下也可用 XRRGetScreenResources + XRRGetOutputInfo 获取,但需链接 -lXrandr。
立即学习“C++免费学习笔记(深入)”;
-
xrandr输出中刷新率可能带小数(如59.95),需用std::stof而非std::stoi - Wayland会禁用
xrandr,此时需走特定协议(如wp-desktop-dlna非标准)或依赖桌面环境DBus接口(GNOME/KDE各不相同) - 无GUI环境(如SSH)下
xrandr报错或返回空,应先检查getenv("DISPLAY")是否存在
VSync开启状态无法跨平台直接查询
垂直同步“是否启用”不是系统级全局开关,而是渲染上下文(OpenGL/Vulkan/DirectX)的配置项,且通常只在应用层生效。操作系统本身不维护一个“VSync on/off”的布尔状态——显卡驱动可能强制开启(如NVIDIA的“垂直同步”全局设置),但该设置不暴露给用户态程序查询。
这意味着:你无法用标准C++代码可靠地读取“当前VSync是否打开”。唯一接近的办法是反向推断——比如在OpenGL中调用 glXQueryDrawable(X11)或 wglGetSwapIntervalEXT(Windows)获取当前swap interval,值为1通常对应开启,0为关闭,但前提是你的程序已创建了GL上下文。
-
wglGetSwapIntervalEXT依赖扩展,需先调用wglGetProcAddress("wglGetSwapIntervalEXT") - Vulkan中无等效查询接口,
VK_PRESENT_MODE_FIFO_KHR模式隐含VSync,但驱动可自行优化,不可靠 - 即使查到swap interval=1,也不能代表全系统VSync开启——只是当前上下文的请求值,驱动仍可能忽略
macOS需用 CGDisplayMode 和 IOSurface 组合判断
macOS通过Core Graphics框架提供 CGDisplayModeGetRefreshRate 获取当前模式刷新率,比Windows更干净。但同样不提供VSync开关状态——Apple明确文档指出“VSync由系统自动管理,开发者不应也不必控制”。
实操时先用 CGGetActiveDisplayList 获取活跃显示器列表,再对每个ID调用 CGDisplayCopyDisplayMode,最后提取 refreshRate 字段。注意:该值是浮点数,且某些HiDPI缩放模式下可能返回0(需fallback到 CGDisplayModeGetWidth/Height 推算)。
- 必须链接
-framework CoreGraphics,否则链接失败 - macOS 12+ 对后台进程限制更严,若从命令行工具调用,需确保有Accessibility权限或运行在GUI会话中
- 不要用
CGDisplayModeGetIOFlags判断VSync——该标志位与同步无关,仅表示是否支持硬件加速
跨平台获取刷新率可行,但“VSync状态”本质是个伪需求:它依附于具体图形API上下文,且现代驱动常动态调整,硬要查反而容易误导。


















