本文目录导读:

我来介绍几种获取全局快捷键的方法,包括Windows和Linux系统。
Windows系统
使用AutoHotkey (AHK) 监听全局快捷键
; 监听并捕获所有已注册的全局快捷键
#Persistent
SetTimer, CheckHotkeys, 1000
return
CheckHotkeys:
; 这里可以检查特定的热键状态
; 或者使用热键覆盖来检测
return
; 检测已注册的热键
^!F1:: ; Ctrl+Alt+F1
MsgBox, 检测到热键 Ctrl+Alt+F1
return
!F2:: ; Alt+F2
MsgBox, 检测到热键 Alt+F2
return
#F3:: ; Win+F3
MsgBox, 检测到热键 Win+F3
return
; 取消注册某些热键
#!F4:: ; Win+Alt+F4
return
使用PowerShell 查询已注册的全局快捷键
# 枚举所有窗口并检查热键
$shell = New-Object -ComObject Shell.Application
$windows = $shell.Windows()
# 检测特定的热键注册状态
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class HotKeyManager {
[DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
[DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
}
"@
# 尝试注册热键来检测是否已被占用
$modifiers = 0x0001 # MOD_ALT
$virtualKey = 0x70 # F1
try {
[HotKeyManager]::RegisterHotKey(0, 1, $modifiers, $virtualKey)
Write-Host "热键 Alt+F1 可用"
[HotKeyManager]::UnregisterHotKey(0, 1)
} catch {
Write-Host "热键 Alt+F1 已被占用"
}
使用Python + pywin32
import win32api
import win32con
import win32gui
import ctypes
from ctypes import wintypes
# 定义全局钩子
user32 = ctypes.windll.user32
kernel32 = ctypes.windll.kernel32
# 获取当前进程ID
current_thread_id = kernel32.GetCurrentThreadId()
# 设置键盘钩子
WH_KEYBOARD_LL = 13
HC_ACTION = 0
# 键盘事件回调函数
def keyboard_proc(nCode, wParam, lParam):
if nCode >= 0:
if wParam == win32con.WM_KEYDOWN:
# 获取按键信息
vk_code = ctypes.cast(lParam, ctypes.POINTER(ctypes.c_uint32)).contents.value
# 检查修饰键状态
modifiers = 0
if win32api.GetAsyncKeyState(win32con.VK_CONTROL):
modifiers |= 0x0002 # MOD_CONTROL
if win32api.GetAsyncKeyState(win32con.VK_MENU):
modifiers |= 0x0001 # MOD_ALT
if win32api.GetAsyncKeyState(win32con.VK_LWIN) or win32api.GetAsyncKeyState(win32con.VK_RWIN):
modifiers |= 0x0004 # MOD_WIN
if win32api.GetAsyncKeyState(win32con.VK_SHIFT):
modifiers |= 0x0004 # MOD_SHIFT
# 输出检测到的组合键
key_name = win32api.GetKeyNameText(vk_code << 16)
print(f"检测到按键: {key_name}, 修饰键: {modifiers}")
# 调用下一个钩子
return user32.CallNextHookEx(None, nCode, wParam, lParam)
# 设置钩子
HOOKPROC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_uint32))
hook_proc = HOOKPROC(keyboard_proc)
hook = user32.SetWindowsHookExA(WH_KEYBOARD_LL, hook_proc, kernel32.GetModuleHandleW(None), 0)
# 消息循环
try:
print("开始监听全局快捷键...")
msg = wintypes.MSG()
while user32.GetMessageA(ctypes.byref(msg), None, 0, 0) != 0:
user32.TranslateMessage(ctypes.byref(msg))
user32.DispatchMessageA(ctypes.byref(msg))
finally:
user32.UnhookWindowsHookEx(hook)
Linux系统
使用xdotool + xbindkeys
#!/bin/bash
# 监听全局快捷键组合
# 使用xdotool获取当前键盘状态
while true; do
# 检查特定按键状态
if xdotool get_desktop; then
# 监听按键事件
xev -event keyboard &
XEV_PID=$!
sleep 1
kill $XEV_PID 2>/dev/null
fi
sleep 0.1
done
使用Python + evdev
import evdev
from evdev import InputDevice, ecodes, InputEvent, categorize
import asyncio
async def listen_keyboard():
# 查找键盘设备
devices = [InputDevice(path) for path in evdev.list_devices()]
keyboard_devices = []
for device in devices:
if 'keyboard' in device.name.lower() or 'keyboard' in device.phys:
keyboard_devices.append(device)
if not keyboard_devices:
print("未找到键盘设备")
return
print("找到以下键盘设备:")
for i, dev in enumerate(keyboard_devices):
print(f"{i}: {dev.name} ({dev.path})")
# 监听所有键盘设备
async for event in keyboard_devices[0].async_read_loop():
if event.type == ecodes.EV_KEY:
key_event = categorize(event)
if key_event.keystate == key_event.key_down:
# 获取按键名称
key_name = evdev.ecodes.KEY[event.code]
print(f"检测到按键: {key_name}")
# 检测修饰键组合
try:
alt_pressed = keyboard_devices[0].active_keys().count(56) > 0 # Alt_L
ctrl_pressed = keyboard_devices[0].active_keys().count(29) > 0 # Control_L
shift_pressed = keyboard_devices[0].active_keys().count(42) > 0 # Shift_L
if alt_pressed and ctrl_pressed:
print(f"检测到 Ctrl+Alt+{key_name}")
elif alt_pressed:
print(f"检测到 Alt+{key_name}")
elif ctrl_pressed:
print(f"检测到 Ctrl+{key_name}")
except:
pass
# 运行监听
asyncio.run(listen_keyboard())
使用xinput + xdotool
#!/bin/bash
# 使用xinput监听全局快捷键
# 获取键盘设备ID
KEYBOARD_ID=$(xinput list | grep -i "keyboard" | grep -v "mouse" | head -n1 | grep -oP 'id=\K\d+')
if [ -z "$KEYBOARD_ID" ]; then
echo "无法找到键盘设备"
exit 1
fi
echo "键盘设备ID: $KEYBOARD_ID"
echo "开始监听全局快捷键..."
# 创建临时文件存储按键数据
TMPFILE=$(mktemp)
# 监听按键事件
xinput test "$KEYBOARD_ID" | while read line; do
echo "$line"
# 处理按键事件
if echo "$line" | grep -q "key press"; then
KEYCODE=$(echo "$line" | awk '{print $3}')
# 获取当前修饰键状态
ALT=$(xdotool getactivewindow getwindowmodifiers | grep -c "alt")
CTRL=$(xdotool getactivewindow getwindowmodifiers | grep -c "control")
SHIFT=$(xdotool getactivewindow getwindowmodifiers | grep -c "shift")
WIN=$(xdotool getactivewindow getwindowmodifiers | grep -c "meta")
# 获取按键名称
KEYNAME=$(xmodmap -pke | grep "keycode $KEYCODE" | awk '{$1=$2=$3=$4=""; print $0}' | xargs)
echo "按键: $KEYNAME (代码: $KEYCODE)"
[ "$ALT" -gt 0 ] && echo " + Alt"
[ "$CTRL" -gt 0 ] && echo " + Ctrl"
[ "$SHIFT" -gt 0 ] && echo " + Shift"
[ "$WIN" -gt 0 ] && echo " + Win/Super"
echo "---"
fi
done
跨平台方案
使用Qt5
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import Qt, QTimer
from PyQt5 import QtCore
class GlobalHotKeyDetector(QtCore.QObject):
def __init__(self):
super().__init__()
self.app = QApplication(sys.argv)
# 使用定时器轮询键盘状态
self.timer = QTimer()
self.timer.timeout.connect(self.check_hotkey)
self.timer.start(100) # 每100ms检查一次
def check_hotkey(self):
# 这里需要平台特定的实现
# Windows: 使用win32api
# Linux: 使用xlib
# macOS: 使用CGEvent
pass
if __name__ == "__main__":
detector = GlobalHotKeyDetector()
sys.exit(detector.app.exec_())
注意事项
- 权限问题:某些系统可能需要管理员/root权限才能监听全局快捷键
- 系统限制:某些快捷键可能被系统保留(如Ctrl+Alt+Del)
- 性能影响:全局监听会消耗系统资源
- 兼容性:不同版本的操作系统API可能不同
选择哪种方法取决于你的具体需求、操作系统和你熟悉的编程语言。