I'm attempting to track the number of keypresses from the user, but I've come to realise that anything to do with Steam, whether it's the client itself or a game launched through it, it stops working. If using GetKeyState
instead of GetAsyncKeyState
, it can pick up the bits around the edge of the keyboard, such as ctrl, shift, tab, backspace, enter, but nothing else. I've also found the same behaviour on a small number of other programs, such as Task Manager and Discord.
I've tried with both ctypes
and pywin32
, using GetKeyState
and GetAsyncKeyState
.
Also after IInspectable suggested looking at low level keyboard hooks, I tried two different versions and found they suffered the exact same problem.
Here's some code to demonstrate the problem with all of the functions:
import ctypes
try:
import win32api
except ImportError:
win32api = None
def get_key_press1(key):
return win32api.GetAsyncKeyState(key)
def get_key_press2(key):
return win32api.GetKeyState(key) < 0
def get_key_press3(key):
return ctypes.windll.user32.GetKeyState(key) > 1
def get_key_press4(key):
return ctypes.windll.user32.GetAsyncKeyState(key)
KEYS = {
'BACK': 8,
'TAB': 9,
'CLEAR': 12,
'RETURN': 13,
'PAUSE': 19,
'CAPSLOCK': 20,
'ESC': 27,
'SPACE': 32,
'PGUP': 33,
'PGDOWN': 34,
'END': 35,
'HOME': 36,
'LEFT': 37,
'UP': 38,
'RIGHT': 39,
'DOWN': 40,
'INSERT': 45,
'DELETE': 46,
'LWIN': 91,
'RWIN': 92,
'MENU': 93,
'NUM0': 96,
'NUM1': 97,
'NUM2': 98,
'NUM3': 99,
'NUM4': 100,
'NUM5': 101,
'NUM6': 102,
'NUM7': 103,
'NUM8': 104,
'NUM9': 105,
'MULTIPLY': 106,
'ADD': 107,
'SUBTRACT': 109,
'DECIMAL': 110,
'DIVIDE': 111,
'F1': 112,
'F2': 113,
'F3': 114,
'F4': 115,
'F5': 116,
'F6': 117,
'F7': 118,
'F8': 119,
'F9': 120,
'F10': 121,
'F11': 122,
'F12': 123,
'F13': 124,
'F14': 125,
'F15': 126,
'F16': 127,
'F17': 128,
'F18': 129,
'F19': 130,
'F20': 131,
'F21': 132,
'F22': 133,
'F23': 134,
'F24': 135,
'NUMLOCK': 144,
'SCROLLLOCK': 145,
'LSHIFT': 160,
'RSHIFT': 161,
'LCTRL': 162,
'RCTRL': 163,
'LALT': 164,
'RALT': 165,
'COLON': 186,
'EQUALS': 187,
'COMMA': 188,
'UNDERSCORE': 189,
'PERIOD': 190,
'FORWARDSLASH': 191,
'AT': 192,
'LBRACKET': 219,
'BACKSLASH': 220,
'RBRACKET': 221,
'HASH': 222,
'TILDE': 223
}
for c in list('ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'):
KEYS[c] = ord(c)
while True:
all_pressed = []
for k in KEYS:
if win32api:
if get_key_press1(KEYS[k]):
all_pressed.append((k, 1))
if get_key_press2(KEYS[k]):
all_pressed.append((k, 2))
if get_key_press3(KEYS[k]):
all_pressed.append((k, 3))
if get_key_press4(KEYS[k]):
all_pressed.append((k, 4))
if all_pressed:
print all_pressed
From anywhere on the computer, if you were to press "c" for example, you would get [('C', 1), ('C', 2), ('C', 3), ('C', 4)]
, which shows all 4 functions are picking it up. Press that when focused in anything related to Steam and nothing shows. If however you were to hit one of the working buttons, you get [('LCTRL', 2), ('LCTRL', 3)]
, which means only the GetKeyState
functions are picking it up.
I've tested the script on roughly 30 games over the past couple of months and without fail the Steam ones are the only ones that don't have working keyboard tracking. I even just downloaded the standalone version of Factorio to compare to the Steam version, and it worked flawlessly.
Is there something obvious I'm missing, or is there a better way to get key presses? It's a little annoying as it should be the most simple part of the script, yet it's the part which appears unfixable.
Just to clarify, I'd ideally like to stick with a function to return True
/False
depending on if the key is being pressed at the time.