Search code examples
pythonpython-2.7inputkeyboardpywin32

Win32api's keybd_event() function problems


I'm having some issues creating inputs with the win32api. I'm creating a voice recognition script that needs to work just like a keyboard in all contexts (including fullscreen games and such). I've tried a few other solutions besides win32api's keybd_event() function but most don't even register in fullscreen applications. I'm using Civilization IV as the test program. Win32api's keybd_event() function does work in-game, but I'm getting some weird results. I've tried a few different things:

win32api.keybd_event(win32con.VK_UP, 0, win32con.KEYEVENTF_EXTENDEDKEY, 0)
win32api.Sleep(50)
win32api.keybd_event(win32con.VK_UP, 0, win32con.KEYEVENTF_KEYUP, 0)

Does not work regardless of whether the second or third line is in there. It correctly registers as an up arrow press in applications like notepad. In Civilization, it correctly registers as an up arrow press (as opposed to the next solution below), but the key is never released and it tries to go up forever, seemingly ignoring the third line.

win32api.keybd_event(win32con.VK_UP, 0, 0, 0)
win32api.Sleep(50)
win32api.keybd_event(win32con.VK_UP, 0, win32con.KEYEVENTF_KEYUP, 0)

Has a completely different problem. In Civilization that code tries to press not the up arrow key, but the numpad up (8) key regardless of whether numlock is on or off.

It's weird because the two inputs do different things in game: The first block of code is clearly pressing the arrow up key (but not letting go of it) and the second block of code is clearly pressing the numpad up (8) key, even though the first argument (which key to press) is the same.

What is wrong with the first block of code? What is wrong with the second block of code? What is a good solution? Thanks for your time and help!


Solution

  • I'm unsure exactly why this works, but experimenting randomly I have found a solution using the bitwise OR. The code that I partially copied is here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms646304%28v=vs.85%29.aspx

    My solution:

    win32api.keybd_event(win32con.VK_UP, 0, win32con.KEYEVENTF_EXTENDEDKEY, 0) #press
    win32api.Sleep(50)
    win32api.keybd_event(win32con.VK_UP, 0, win32con.KEYEVENTF_EXTENDEDKEY | win32con.KEYEVENTF_KEYUP, 0) #release
    

    I'll mark this as the accepted answer for now since it works and there are no other answers, (and I still can't find any good documentation) but if anyone has a good explanation of exactly what is going on here then that would be great. Thanks!