必须调用systemparametersinfo(spi_getkeyboarddelay/spi_getkeyboardspeed)读取windows键盘重复延迟和速率,返回bool需检查,否则可能使用未初始化值;linux需解析xset q输出,wayland无标准接口,跨平台统一封装不可行。

Windows 下用 SystemParametersInfo 读取键盘重复延迟和速率
Windows 的键盘重复行为由两个参数控制:按下键后多久开始重复(KeyboardDelay),以及之后每秒重复多少次(KeyboardSpeed)。这两个值不能直接从注册表或配置文件里“读出来”,必须调用 SystemParametersInfo,且需指定 SPI_GETKEYBOARDDELAY 和 SPI_GETKEYBOARDSPEED。
常见错误是传错参数类型或忽略返回值检查——该函数返回 BOOL,失败时不修改输出变量,若没检查就直接用,会拿到未初始化的垃圾值。
-
KeyboardDelay是 0–3 的整数,对应 250ms / 500ms / 750ms / 1000ms 延迟 -
KeyboardSpeed是 0–31 的整数,对应约 2.5–30 次/秒(实际映射非线性,微软未公开公式) - 必须链接
User32.lib,否则链接报错LNK2019: unresolved external symbol __imp__SystemParametersInfoA@16
int delay = 0, speed = 0;
if (SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &delay, 0)) {
SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &speed, 0);
}
// delay=2 → 750ms;speed=20 → 约 22 次/秒(实测值)Linux 下无法用 xset 直接获取数值,得解析输出
xset q 是唯一能查当前 X11 键盘重复设置的命令,但它输出的是纯文本,不是结构化数据。没有 API、没有 sysfs 接口、也没有标准库函数封装——你得自己 parse。
容易踩的坑是假设输出格式稳定:xset q 在不同 X server 版本、不同桌面环境(GNOME/KDE/XFCE)下,段落顺序和缩进可能变化,但“auto repeat delay”和“auto repeat rate”这两行关键词基本固定。
立即学习“C++免费学习笔记(深入)”;
- 延迟单位是毫秒,速率单位是“每秒重复次数”,和 Windows 的整数编码完全不同
- 如果用户用 Wayland,
xset根本不生效——Wayland 没有全局键盘重复设置,由每个 compositor 自行实现(如sway用input * repeat_rate配置) - 脚本中用
grep -A1 "auto repeat delay" | tail -n1这类写法脆弱,推荐用awk '/auto repeat delay/{getline; gsub(/[^0-9]/,""); print}'
C++ 跨平台读取不可行,别硬封装统一接口
Windows 和 Linux 的键盘重复机制底层完全不兼容:Windows 是内核级策略,Linux 是 X11 客户端协议层行为(Wayland 下甚至不存在“系统级”设置)。强行写一个 get_keyboard_repeat_params() 函数,只会让调用方误以为它在所有环境下都可靠。
更现实的做法是明确区分构建目标:
- Windows 平台:只编译
SystemParametersInfo分支,加#ifdef _WIN32 - X11 平台:调用
popen("xset q", "r")解析,但必须检查DISPLAY环境变量是否存在 - Wayland 平台:直接返回错误或默认值(例如
{250, 20}),因为没有标准方式查询
试图用 Qt 或 GTK 的抽象层绕过这个问题也不行——它们只是把平台差异藏得更深,底层仍是上述逻辑。
注意:用户改设置后,你的程序不会自动收到通知
无论是 Windows 的 SystemParametersInfo 还是 Linux 的 xset,修改都是“一次性快照”。系统不会广播键盘参数变更事件,也没有类似 WM_SETTINGCHANGE 的通用通知机制。
如果你的程序需要响应用户后续调整(比如游戏里动态适配按键灵敏度),只能靠轮询——但别太频繁:
- Windows:每 2–3 秒调一次
SystemParametersInfo,避免干扰 UI 线程 - Linux:
xset q启动开销不小,建议至少间隔 5 秒,且首次失败后退回到缓存值 - 轮询时记得处理权限/环境失效情况,比如 X11 连接断开、
DISPLAY变为空字符串
最常被忽略的是:没人会在意这个值,除非它突然变了还导致你的输入逻辑异常——所以真要加轮询,务必加日志开关和采样率控制,别让它变成性能黑洞。










