使用全局热键切换到Tkinter程序焦点

1 投票
1 回答
549 浏览
提问于 2025-04-18 05:43

我想注册一个全局热键,这样在我的Tkinter程序中按下这个热键就能触发一些操作。我参考了这个链接。当我运行那个链接里的代码时,一切都正常。但我现在遇到的问题是,怎么把那个循环和Tkinter的事件循环结合起来。

Tkinter的循环需要定期检查热键是否被按下。这应该很简单,可以用root.after()来实现。不过,程序似乎根本没有检测到热键被按下,即使在窗口聚焦的时候也没有。

这里有一个简短的代码示例——我尽量把它缩短到最简洁的形式。这段代码是我尝试修改链接中的代码,以便能和Tkinter配合得更好。

from tkinter import *
import ctypes
from ctypes import wintypes
import win32con

user32 = ctypes.windll.user32
byref = ctypes.byref

def hotkey_handler(root):
    msg = wintypes.MSG()
    if user32.GetMessageA(byref(msg), None, 0, 0) != 0:
        if msg.message == win32con.WM_HOTKEY:
            if msg.wParam == 1:
                print("hotkey pressed")
    user32.TranslateMessage(byref(msg))
    user32.DispatchMessageA(byref(msg))
    root.after(1, hotkey_handler, root)

root = Tk()

if user32.RegisterHotKey(None, 1, win32con.MOD_SHIFT, ord("v")) != 0:
    print("--Hotkey registered!")

root.after(1, hotkey_handler, root)

root.mainloop()

我注意到一个奇怪的现象,如果我把root.after()的第一个参数设为零,GUI就不会正确显示,有时Python还会崩溃。

1 个回答

1

eryksun 指出了问题所在 - 我使用了错误的字母大小写来设置快捷键。ord("v") 应该改成 ord("V")

撰写回答