python实现自己的全局热键的第2种方法
之前有过一版python实现的全局热键, 但是在实际运行中发现, 有时候不太灵敏, 明明按下了目标热键, 为什么没有反应呢? 通过定位发现, 有时候键盘勾子捕获不到ctrl down消息, 特别是一段时间不操作电脑后容易出现这种情况, 这时候ctrl键确实处于按下的状态(通过GetKeyState函数可以获取到当时的状态).
于是我又重新实现了一版热键功能, 如下代码:
class HotkeyMatch2:
def __init__(self,hotkey:str):
'''hotkey: 形如: 'ctrl+a';'''
self.hotkey = hotkey
self.keys = hotkey.split('+') # 热键的列表
self.target_key = 'VK_' + self.keys[-1].upper() # 目标键, 形如'VK_A'
# 确定目标ctrl键和alt键状态, True表示被按下
self.target_ctrl = 'ctrl' in self.keys
self.target_alt = 'alt' in self.keys
def is_match(self,key:str,etype:str)->bool:
'''
key: 形如: VK_A
etype: 形如: DOWN|UP
返回值: True: 表示热键匹配, 否则表示不匹配
'''
if etype!='DOWN': return False # 只接受down消息
if key!=self.target_key: return False # 判断是否是目标键
if is_control_pressing()!=self.target_ctrl: return False # 判断ctrl键是否按下
if is_alt_pressing()!=self.target_alt: return False # 判断alt键是否按下
return True
def add_hotkey2(hotkey:str,callback:callable):
'''
增加一个热键
hotkey: 形如: 'ctrl+a'
callback: 回调函数: void f()
'''
hotkey_match = HotkeyMatch2(hotkey)
def on_key(key:str,etype:str)->bool:
result = hotkey_match.is_match(key,etype)
ctx = msg.Context() # 订阅消息的回调函数的返回对象
ctx.tag = result
if result==True: # 触发热键
cmn.run_in_thread(callback)() # 在新线程中运行回调函数
ctx.discontinued = True
return ctx
msg.sub('23090501_KeyMsg',on_key) # 订阅键盘消息
add_hotkey = add_hotkey2
初步测试, 应该是解决了问题.