本文目录导读:

我来介绍几种实现全局热键的Python方法,并提供完整的案例。
使用 keyboard 库(最简单)
import keyboard
import time
class GlobalHotkey:
def __init__(self):
self.is_running = False
def on_ctrl_shift_a(self):
print("按下: Ctrl+Shift+A - 执行操作A")
def on_ctrl_shift_b(self):
print("按下: Ctrl+Shift+B - 执行操作B")
def on_esc(self):
print("按下: ESC - 退出程序")
self.is_running = False
return False # 停止监听
def start(self):
# 注册热键
keyboard.add_hotkey('ctrl+shift+a', self.on_ctrl_shift_a)
keyboard.add_hotkey('ctrl+shift+b', self.on_ctrl_shift_b)
keyboard.add_hotkey('esc', self.on_esc)
print("全局热键启动成功!")
print("Ctrl+Shift+A: 执行操作A")
print("Ctrl+Shift+B: 执行操作B")
print("ESC: 退出程序")
print("按下 Ctrl+C 也可以退出...")
self.is_running = True
try:
keyboard.wait() # 等待按键
except KeyboardInterrupt:
pass
finally:
keyboard.unhook_all()
# 使用示例
if __name__ == "__main__":
hotkey = GlobalHotkey()
hotkey.start()
使用 pynput 库(更专业)
from pynput import keyboard
from pynput.keyboard import Key, Controller
import threading
import time
class PynputHotkey:
def __init__(self):
self.current_keys = set()
self.hotkeys = {
frozenset({Key.ctrl, Key.shift, keyboard.KeyCode.from_char('a')}): self.action_a,
frozenset({Key.ctrl, Key.shift, keyboard.KeyCode.from_char('b')}): self.action_b,
frozenset({Key.ctrl, Key.alt, keyboard.KeyCode.from_char('c')}): self.action_c,
}
self.key_controller = Controller()
def action_a(self):
print("执行操作A: 复制选中内容")
# 模拟Ctrl+C
with self.key_controller.pressed(Key.ctrl):
self.key_controller.press('c')
self.key_controller.release('c')
def action_b(self):
print("执行操作B: 粘贴内容")
# 模拟Ctrl+V
with self.key_controller.pressed(Key.ctrl):
self.key_controller.press('v')
self.key_controller.release('v')
def action_c(self):
print("执行操作C: 显示通知")
# 这里可以执行任何操作
self.show_notification()
def show_notification(self):
try:
from plyer import notification
notification.notify(
title="全局热键",
message="执行操作C成功!",
timeout=3
)
except ImportError:
print("提示: 如需显示系统通知,请安装plyer库")
def on_press(self, key):
try:
self.current_keys.add(key)
# 检查是否匹配任何热键组合
for hotkey_set in self.hotkeys:
if hotkey_set.issubset(self.current_keys):
self.hotkeys[hotkey_set]()
self.current_keys.clear() # 防止重复触发
break
except Exception as e:
print(f"按键处理错误: {e}")
def on_release(self, key):
try:
if key in self.current_keys:
self.current_keys.remove(key)
# 退出条件
if key == Key.esc:
print("ESC按下,退出程序...")
return False
except Exception as e:
print(f"释放按键错误: {e}")
def start(self):
print("全局热键启动成功!")
print("Ctrl+Shift+A: 复制")
print("Ctrl+Shift+B: 粘贴")
print("Ctrl+Alt+C: 显示通知")
print("ESC: 退出程序")
# 启动监听器
with keyboard.Listener(
on_press=self.on_press,
on_release=self.on_release
) as listener:
listener.join()
# 使用示例
if __name__ == "__main__":
hotkey = PynputHotkey()
hotkey.start()
使用 ctypes(Windows原生API)
import ctypes
from ctypes import wintypes
import threading
import sys
class WindowsGlobalHotkey:
# Windows API 常量
WM_HOTKEY = 0x0312
MOD_ALT = 0x0001
MOD_CONTROL = 0x0002
MOD_SHIFT = 0x0004
MOD_WIN = 0x0008
def __init__(self):
self.hotkeys = {}
self.running = True
# 加载user32.dll
self.user32 = ctypes.windll.user32
# 获取消息函数
self.GetMessage = self.user32.GetMessageW
self.GetMessage.argtypes = [
ctypes.POINTER(ctypes.wintypes.MSG),
wintypes.HWND,
wintypes.UINT,
wintypes.UINT
]
self.GetMessage.restype = ctypes.wintypes.BOOL
def register_hotkey(self, hotkey_id, modifiers, vk_code, callback):
"""
注册全局热键
:param hotkey_id: 热键ID
:param modifiers: 修饰键组合 (MOD_ALT, MOD_CONTROL, MOD_SHIFT, MOD_WIN)
:param vk_code: 虚拟键码
:param callback: 回调函数
"""
result = self.user32.RegisterHotKey(
None, # hWnd
hotkey_id, # id
modifiers, # fsModifiers
vk_code # vk
)
if result:
self.hotkeys[hotkey_id] = callback
print(f"热键 {hotkey_id} 注册成功")
else:
print(f"热键 {hotkey_id} 注册失败")
def unregister_all(self):
"""注销所有热键"""
for hotkey_id in self.hotkeys:
self.user32.UnregisterHotKey(None, hotkey_id)
self.hotkeys.clear()
def start(self):
"""开始监听热键"""
print("Windows全局热键启动成功!")
# 创建消息结构体
msg = ctypes.wintypes.MSG()
while self.running:
# 获取消息
ret = self.GetMessage(
ctypes.byref(msg),
None,
0,
0
)
if ret == 0: # WM_QUIT
break
elif ret == -1: # 错误
print("消息获取错误")
break
# 处理热键消息
if msg.message == self.WM_HOTKEY:
hotkey_id = msg.wParam
if hotkey_id in self.hotkeys:
try:
self.hotkeys[hotkey_id]()
except Exception as e:
print(f"热键执行错误: {e}")
def stop(self):
"""停止监听"""
self.running = False
# 发送退出消息
self.user32.PostQuitMessage(0)
self.unregister_all()
# 热键操作类
class HotkeyActions:
@staticmethod
def action_1():
print("执行操作1: Ctrl+Shift+A")
@staticmethod
def action_2():
print("执行操作2: Ctrl+Shift+B")
@staticmethod
def action_3():
print("执行操作3: Ctrl+Alt+D")
@staticmethod
def exit_action():
print("退出程序")
sys.exit(0)
# 使用示例
if __name__ == "__main__":
# Windows虚拟键码
VK_A = 0x41
VK_B = 0x42
VK_D = 0x44
VK_ESCAPE = 0x1B
hotkey = WindowsGlobalHotkey()
# 注册热键
actions = HotkeyActions()
# Ctrl+Shift+A
hotkey.register_hotkey(
1,
WindowsGlobalHotkey.MOD_CONTROL | WindowsGlobalHotkey.MOD_SHIFT,
VK_A,
actions.action_1
)
# Ctrl+Shift+B
hotkey.register_hotkey(
2,
WindowsGlobalHotkey.MOD_CONTROL | WindowsGlobalHotkey.MOD_SHIFT,
VK_B,
actions.action_2
)
# Ctrl+Alt+D
hotkey.register_hotkey(
3,
WindowsGlobalHotkey.MOD_CONTROL | WindowsGlobalHotkey.MOD_ALT,
VK_D,
actions.action_3
)
# ESC退出
hotkey.register_hotkey(
4,
0,
VK_ESCAPE,
actions.exit_action
)
try:
hotkey.start()
except KeyboardInterrupt:
hotkey.stop()
使用万能的热键管理器
import sys
import threading
from typing import Dict, Callable, Set
from dataclasses import dataclass
from enum import Enum
class KeyModifier(Enum):
NONE = 0
CTRL = 1
SHIFT = 2
ALT = 3
WIN = 4
@dataclass
class HotkeyConfig:
"""热键配置"""
keys: tuple # 按键组合
modifiers: tuple # 修饰键
callback: Callable
description: str = ""
class SmartHotkeyManager:
"""智能热键管理器"""
def __init__(self):
self.hotkeys: Dict[str, HotkeyConfig] = {}
self.use_library = self._detect_best_library()
def _detect_best_library(self) -> str:
"""检测最佳可用的库"""
try:
import keyboard
return 'keyboard'
except ImportError:
try:
import pynput
return 'pynput'
except ImportError:
return 'fallback'
def add_hotkey(self, name: str, keys: tuple, modifiers: tuple,
callback: Callable, description: str = ""):
"""添加热键"""
config = HotkeyConfig(
keys=keys,
modifiers=modifiers,
callback=callback,
description=description
)
self.hotkeys[name] = config
def remove_hotkey(self, name: str):
"""移除热键"""
if name in self.hotkeys:
del self.hotkeys[name]
def _format_hotkey(self, config: HotkeyConfig) -> str:
"""格式化热键显示"""
parts = []
for mod in config.modifiers:
if mod == KeyModifier.CTRL:
parts.append('Ctrl')
elif mod == KeyModifier.SHIFT:
parts.append('Shift')
elif mod == KeyModifier.ALT:
parts.append('Alt')
elif mod == KeyModifier.WIN:
parts.append('Win')
for key in config.keys:
parts.append(key.upper() if len(key) == 1 else key)
return '+'.join(parts)
def show_help(self):
"""显示帮助信息"""
print("\n=== 全局热键帮助 ===")
print(f"使用库: {self.use_library}")
print("-" * 40)
for name, config in self.hotkeys.items():
hotkey_str = self._format_hotkey(config)
desc = config.description or name
print(f"{hotkey_str:20s} - {desc}")
print("=" * 40)
def start(self):
"""启动热键监听"""
if self.use_library == 'keyboard':
self._start_with_keyboard()
elif self.use_library == 'pynput':
self._start_with_pynput()
else:
print("警告: 未检测到keyboard或pynput库")
print("请安装: pip install keyboard 或 pip install pynput")
def _start_with_keyboard(self):
"""使用keyboard库启动"""
import keyboard
for name, config in self.hotkeys.items():
hotkey_str = self._format_hotkey(config).lower()
keyboard.add_hotkey(hotkey_str, config.callback)
self.show_help()
print("按 ESC 退出程序")
try:
keyboard.wait('esc')
except KeyboardInterrupt:
pass
finally:
keyboard.unhook_all()
def _start_with_pynput(self):
"""使用pynput库启动"""
from pynput import keyboard
class PynputHandler:
def __init__(self, hotkeys):
self.hotkeys = hotkeys
self.current_keys = set()
def format_pynput_hotkey(self, config: HotkeyConfig) -> set:
result = set()
for mod in config.modifiers:
if mod == KeyModifier.CTRL:
result.add(keyboard.Key.ctrl)
elif mod == KeyModifier.SHIFT:
result.add(keyboard.Key.shift)
elif mod == KeyModifier.ALT:
result.add(keyboard.Key.alt)
elif mod == KeyModifier.WIN:
result.add(keyboard.Key.cmd)
for key in config.keys:
if len(key) == 1:
result.add(keyboard.KeyCode.from_char(key))
else:
result.add(getattr(keyboard.Key, key.lower(), None))
return result
def on_press(self, key):
try:
self.current_keys.add(key)
for config in self.hotkeys.values():
hotkey_set = self.format_pynput_hotkey(config)
if hotkey_set.issubset(self.current_keys):
config.callback()
self.current_keys.clear()
break
except Exception as e:
print(f"错误: {e}")
def on_release(self, key):
try:
self.current_keys.discard(key)
if key == keyboard.Key.esc:
return False
except:
pass
handler = PynputHandler(self.hotkeys)
self.show_help()
with keyboard.Listener(
on_press=handler.on_press,
on_release=handler.on_release
) as listener:
listener.join()
# 使用示例
if __name__ == "__main__":
def action_copy():
print("复制操作!")
def action_paste():
print("粘贴操作!")
def action_custom():
print("自定义操作!")
# 创建热键管理器
manager = SmartHotkeyManager()
# 注册热键
manager.add_hotkey(
"copy",
keys=('c',),
modifiers=(KeyModifier.CTRL,),
callback=action_copy,
description="复制"
)
manager.add_hotkey(
"paste",
keys=('v',),
modifiers=(KeyModifier.CTRL,),
callback=action_paste,
description="粘贴"
)
manager.add_hotkey(
"custom",
keys=('f1',),
modifiers=(KeyModifier.CTRL, KeyModifier.SHIFT),
callback=action_custom,
description="自定义操作"
)
# 启动
manager.start()
安装依赖
# 方法一 (推荐): keyboard pip install keyboard # 方法二: pynput pip install pynput # 可选: 系统通知 pip install plyer
使用建议
- 简单使用: 使用
keyboard库,代码最简单 - 跨平台: 使用
pynput库,支持Windows/Linux/Mac - Windows专用: 使用Windows API,性能最好
- 通用方案: 使用智能管理器,自动选择最佳库
选择哪种方法取决于你的具体需求和应用场景。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播