Question

I wrote a program that catches keyboard events on tetris, which was opened via a subprocess. no when i only want to catch events without opening Tetris my keyboard handler (pyHook) won't catch the events:

# open Tetris
#Tetris = subprocess.Popen (["C:\\Program Files (x86)\Tetris\Tetris.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()

this worked fine when using another subprocess but i do not know why this is stuck now. KeyHandler won't pick up the keys.

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"

all but the last statement gets printed, but evoked keys are not printed, but instead when i press a key the app freezes (I have a function to catch events that works fine with the subprocess included...)

I guess there is something wrong with the threading when leaving out the subprocess.

I found out that if I switch to another GUI window before pressing a key, and then press a key, keys get accepted and keyevents printed.

More precise info: This probably has to do with running the script inside of OpenSesame (experimental software) as somehow pyhook does not retrieve keyboard responses from his window / windows in general but only from gui windows?! Thus I might need to seek an alternative for pyhook here ?

Was it helpful?

Solution

It's not working due to Qt bypassing the windows message loop -- pyHook relies on the message loop to function.

Modern graphical interface frameworks, such as Windows Forms, Windows Presentation Foundation, MFC, Delphi, Qt and others do not typically require applications to directly access the Windows message loop, but instead automatically route events such as key presses and mouse clicks to their appropriate handlers as defined within the framework.

From Message Loop in MS Windows

OTHER TIPS

The run method needs to have a loop. The thread ends once it leaves the run method.

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

or You don't have to subclass it at all.

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.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top