怎么用脚本获取全局快捷键

wen 实用脚本 3

本文目录导读:

怎么用脚本获取全局快捷键

  1. Windows系统
  2. Linux系统
  3. 跨平台方案
  4. 注意事项

我来介绍几种获取全局快捷键的方法,包括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_())

注意事项

  1. 权限问题:某些系统可能需要管理员/root权限才能监听全局快捷键
  2. 系统限制:某些快捷键可能被系统保留(如Ctrl+Alt+Del)
  3. 性能影响:全局监听会消耗系统资源
  4. 兼容性:不同版本的操作系统API可能不同

选择哪种方法取决于你的具体需求、操作系统和你熟悉的编程语言。

抱歉,评论功能暂时关闭!