全局快捷键
本教程共 45 篇 · 第 23 篇 · 更新于 2026-08-03
23. 全局快捷键
本节目标
- 用 globalShortcut 注册系统级快捷键
- 区分应用内与应用外快捷键
- 处理快捷键被占用的情况
- 在退出时正确注销快捷键
普通快捷键只在应用窗口聚焦时生效,比如按下 Ctrl+S 保存。但有些功能你希望「无论焦点在哪」都能触发:全局截图、一键静音、随时唤出搜索框。Electron 用 globalShortcut 模块实现这种系统级快捷键。
本章讲如何注册与注销全局快捷键、应用内与应用外快捷键的区别、快捷键被占用时的处理,以及正确的注销时机。
23-1 注册一个全局快捷键
globalShortcut.register 接收加速器字符串和回调。注册成功返回 true,失败返回 false。它必须在 app 的 ready 事件之后才能用。
// main.js(主进程)
const { app, globalShortcut } = require('electron/main')
app.whenReady().then(() => {
const ret = globalShortcut.register('CommandOrControl+X', () => {
console.log('按下了 CommandOrControl+X')
})
if (!ret) {
console.log('注册失败')
}
})
加速器写法上,CommandOrControl 会自动在 macOS 映射成 Cmd、其他系统映射成 Ctrl。这样一套代码就能跨平台。单个字母、功能键(如 F12)、组合键都支持。
23-2 应用内与应用外快捷键的区别
这里要分清两类快捷键。用 globalShortcut 注册的是「全局」的:即使你的应用在后台、窗口没聚焦,甚至完全最小化到托盘,按下组合键依然触发。
应用内快捷键则不同:它只在窗口获得焦点时有效,一般用 Electron 的 Menu 加速器(见菜单章节)或页面里的键盘事件实现。两者的适用场景不一样:
- 全局快捷键:截屏、全局搜索、媒体播放控制等「随时可用」的功能。
- 应用内快捷键:保存、复制、切换标签等「操作时才需要」的功能。
选错类型会很别扭。比如把「保存」做成全局快捷键,用户在任何软件里按 Ctrl+S 都会触发你的应用,显然不合理。
23-3 冲突处理
全局快捷键是系统级资源,同一组合键只能被一个程序占用。globalShortcut.register 在快捷键已被别的程序占用时,会「静默失败」并返回 false——系统故意不让应用互相争抢。
const ret = globalShortcut.register('CommandOrControl+Shift+A', () => {
console.log('触发')
})
if (!ret) {
console.log('该快捷键可能被其他程序占用')
}
注册后可用 globalShortcut.isRegistered('CommandOrControl+X') 查询是否成功占用。想一次注册多个,用 globalShortcut.registerAll([...], callback),任一项被占用同样会失败。设计时应准备备选组合键,或友好提示用户去设置里改。
23-4 注销时机很重要
全局快捷键占用的是系统资源,必须显式注销,否则应用退出后组合键可能仍被锁住,别的程序用不了。标准做法是在 will-quit 时统一清理。
app.on('will-quit', () => {
// 注销单个
globalShortcut.unregister('CommandOrControl+X')
// 注销全部
globalShortcut.unregisterAll()
})
unregister 注销指定组合键,unregisterAll 注销本应用注册的所有全局快捷键。如果你的窗口关闭但应用仍常驻(如托盘程序),快捷键一般应保留;真正退出时再 unregisterAll。漏掉这一步是常见 bug 来源。
23-5 临时挂起(进阶)
v42.0.0 起新增 setSuspended 与 isSuspended。当你想临时让用户自由按键(比如在界面里重新绑定快捷键)时,可先挂起,结束后再恢复。
// 进入快捷键重绑界面时挂起
globalShortcut.setSuspended(true)
// 重绑完成后恢复
globalShortcut.setSuspended(false)
挂起期间所有已注册的全局快捷键都不再监听按键;恢复后自动继续工作。新注册在挂起状态下会失败。这个小特性在做「快捷键设置面板」时很实用。
23-6 macOS 的可访问性授权
在 macOS 10.14 Mojave 及以后,部分媒体类快捷键(如 Media Play/Pause、Media Next Track 等)只有在应用被授权为「受信任的辅助功能客户端」后才能注册成功。否则 register 会悄悄失败。
这不是代码问题,而是系统隐私保护。用户需要到「系统设置 - 隐私与安全性 - 辅助功能」里把你的应用加进白名单。开发时应检测注册结果,失败时给出引导提示,而不是静默无反应。
23-7 与窗口内快捷键的协作
实际项目里,全局快捷键和窗口内快捷键常常并存。建议用菜单的 accelerator 承载「应用聚焦时」的快捷键(保存、复制),用 globalShortcut 承载「随时可用」的快捷键(截屏、全局搜索)。
两者要避免冲突:同一个组合键不要既注册成全局、又绑成窗口内,否则行为会互相打架。统一管理快捷键的地方放在主进程,集中注册、集中注销,逻辑最清晰,也最容易在设置面板里展示给用户。
23-8 加速器的写法细节
加速器字符串有固定语法。修饰键用 CommandOrControl、Cmd、Ctrl、Alt、Shift,主键可以是字母、数字、功能键(F1–F24)或 Plus、Space 等符号。多个键用 + 连接。
globalShortcut.register('CommandOrControl+Shift+K', () => {})
globalShortcut.register('Alt+F4', () => {})
globalShortcut.register('F11', () => {})
写错语法时 register 会返回 false,可用此做校验。注意 CommandOrControl 才是跨平台正确写法,不要硬编码成 Ctrl,否则 macOS 上用户按 Cmd 不生效。统一用它,一套代码两边都能用。
23-9 完整示例:全局截图快捷键
把注册、冲突处理、注销串起来,下面是一个「随时截图」的骨架。无论应用是否聚焦,按下 Cmd/Ctrl+Shift+S 都触发回调;退出时统一注销。
// main.js(主进程)
const { app, globalShortcut } = require('electron/main')
app.whenReady().then(() => {
const ret = globalShortcut.register('CommandOrControl+Shift+S', () => {
console.log('触发全局截图')
})
if (!ret) {
console.log('快捷键被占用,请到设置更换')
}
})
app.on('will-quit', () => {
globalShortcut.unregisterAll()
})
真实场景里,回调通常会通知渲染进程开始截屏,或调用桌面捕获接口。重点是:注册结果要检查、占用要给提示、退出要注销。三件事都做对,全局快捷键才稳。
全局快捷键设计的小建议
全局快捷键是稀缺的系统资源,应只留给「随时需要」的核心功能,比如截屏、全局搜索、媒体控制。普通编辑类快捷键请留在应用内,不要占用系统级组合键,避免干扰用户在其他软件里的操作。
注册前最好让用户能在设置里自定义,并做冲突检测。被占用时给出明确提示和替代方案,而不是悄悄失效。退出或进入重绑界面时正确注销或挂起,是稳定体验的最后一块拼图。
小结
globalShortcut 注册系统级快捷键,应用失焦也能触发。注册用 register(返回是否成功),查询用 isRegistered,注销用 unregister / unregisterAll。
关键三点:第一,它和「应用内快捷键」用途不同,别乱用全局;第二,被占用会静默失败,要做 fallback;第三,务必在 will-quit 时注销,避免长期锁住系统组合键。