我编写了一个程序,用于捕获通过子进程打开的俄罗斯方块上的键盘事件。不,当我只想捕获事件而不打开俄罗斯方块我的键盘处理程序(pyHook)不会捕获事件:
# open Tetris
#Tetris = subprocess.Popen (["C:\Program Files (x86)TetrisTetris.exe"])
#start game by sending "F2" key
#for hwnd in get_hwnds_for_pid (Tetris.pid):
#win32gui.PostMessage (hwnd, win32con.WM_KEYDOWN, win32con.VK_F2, 0)
keyH = KeyHandler()
ToneT = ToneTimer()
keyH.setDaemon(True)
ToneT.setDaemon(True)
keyH.start()
ToneT.start()
在使用另一个子进程时工作得很好,但我不知道为什么现在卡住了。KeyHandler不会拾取键。
class KeyHandler(threading.Thread):
def run(self):
# watch for all keyboard events
KeyHandler.hm.KeyDown = self.OnKeyboardCharEvent
# set the hook
KeyHandler.hm.HookKeyboard()
# activate message pipeline
print "keyboardhooked"
pythoncom.PumpMessages()
print "thisshouldnotbeprinted"
除最后一条语句外的所有语句都打印出来,但诱发的键不打印,而是当我按下一个键时,应用程序冻结(我有一个函数来捕获与包含的子进程一起工作的事件…)
我猜在省略子进程时线程有问题。
我发现如果我在按下一个键之前切换到另一个GUI窗口,然后按下一个键,键被接受并且键事件被打印。
更精确的信息:这可能与在OpenSesame(实验软件)内部运行脚本有关,因为pyhook通常不会从他的窗口/窗口检索键盘响应,而只从gui窗口?!因此,我可能需要在这里寻找pyhook的替代方法
它不工作,由于Qt绕过windows消息循环——pyHook依赖于消息循环的功能。
现代图形界面框架,如Windows窗体,WindowsPresentation Foundation、MFC、Delphi、Qt等则没有通常要求应用程序直接访问Windows消息循环,而是自动路由事件,如按键和控件中定义的相应处理程序框架。
From Message Loop in MS Windows
run方法需要有一个循环。一旦离开run方法,线程就会结束。
class KeyHandler(threading.Thread):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.running = True
# end
def run(self):
while self.running:
# watch for all keyboard events
KeyHandler.hm.KeyDown = self.OnKeyboardCharEvent
# set the hook
KeyHandler.hm.HookKeyboard()
# activate message pipeline
print "keyboardhooked"
pythoncom.PumpMessages()
print "thisshouldnotbeprinted"
# end run
或者根本不需要创建它的子类
def catch_key(keyboard):
# watch for all keyboard events
KeyHandler.hm.KeyDown = keyboard.OnKeyboardCharEvent
# set the hook
KeyHandler.hm.HookKeyboard()
# activate message pipeline
print "keyboardhooked"
pythoncom.PumpMessages()
print "thisshouldnotbeprinted"
thread = threading.Thread(target=catch_key, args=(Keyboard()))
thread.start()
# Remember to use thread.join() to safely close the thread.