Home > Net >  ctypes.windll.user32.GetKeyState not recognizing key presses
ctypes.windll.user32.GetKeyState not recognizing key presses

Time:10-18

I have a problem where ctypes.windll.user32.GetKeyState won't detect keys on my keyboard (A, B, C, e.t.c), but it does detect the left and right mouse buttons.

I am trying to make a simple script which detects the lowercase "a" key. I got the number 97 by doing ord('a').

import ctypes

def a_pressed():
    return ctypes.windll.user32.GetKeyState(97) > 1

while True:
    if a_pressed():
        print('a is pressed')

Am I doing something wrong or is it just some limitation of the API that I don't know about?

CodePudding user response:

[MS.Docs]: GetKeyState function (winuser.h) (emphasis is mine):

A virtual key. If the desired virtual key is a letter or digit (A through Z, a through z, or 0 through 9), nVirtKey must be set to the ASCII value of that character. For other keys, it must be a virtual-key code.

is "a bit" misleading.

From ASCII's PoV, there's a clear difference between (for example):

  • a: 0x61 (97)
  • A: 0x41 (65)

From keyboard's PoV, things are a bit different:

  • a: The key on the 3rd row and 2nd column, at the right of CapsLock (on US keyboards) pressed
  • A: Same as above, but with either:
    • CapsLock on
    • Shift pressed

[MS.Docs]: Virtual-Key Codes makes things clear: in order to check the state of A (or a), 0x41 (65) must be checked (97 corresponds to NumPad1).

code00.py:

#!/usr/bin/env python

import sys
import time
import ctypes as ct
from ctypes import wintypes as wt


def main(*argv):
    user32 = ct.WinDLL("User32.dll")
    GetKeyState = user32.GetKeyState
    GetKeyState.argtypes = (ct.c_int,)
    GetKeyState.restype = wt.USHORT  # !!! It's actually wt.SHORT, but chose unsigned for display purposes !!!

    while 1:
        vkc = 0x41  # 65, 'A'
        ks = GetKeyState(vkc)
        print("Key (0x{:02X}) state: 0x{:04X}\nPressed: {:d}".format(vkc, ks, ks >> 15))
        time.sleep(0.5)


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                   64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.")
    sys.exit(rc)

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q069599484]> "e:\Work\Dev\VEnvs\py_pc064_03.08.07_test0\Scripts\python.exe" code00.py
Python 3.8.7 (tags/v3.8.7:6503f05, Dec 21 2020, 17:59:51) [MSC v.1928 64 bit (AMD64)] 064bit on win32

Key (0x41) state: 0x0000
Pressed: 0
Key (0x41) state: 0x0000
Pressed: 0
Key (0x41) state: 0x0000
Pressed: 0
Key (0x41) state: 0x0000
Pressed: 0
Key (0x41) state: 0xFF81
Pressed: 1
Key (0x41) state: 0xFF81
Pressed: 1
Key (0x41) state: 0xFF81
Pressed: 1
Key (0x41) state: 0xFF81
Pressed: 1
Key (0x41) state: 0x0001
Pressed: 0
...
  • Related