ctypes.windll.user32.GetKeyState 无法识别按键

ctypes.windll.user32.GetKeyState not recognizing key presses

我遇到一个问题,ctypes.windll.user32.GetKeyState 无法检测到我键盘上的按键(A、B、C、e.t.c),但它确实检测到左键和鼠标右键。

我正在尝试制作一个简单的脚本来检测小写的“a”键。我通过 ord('a').

得到了数字 97
import ctypes

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

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

我是做错了什么,还是我不知道 API 的某些限制?

[MS.Docs]: GetKeyState function (winuser.h)重点是我的):

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.

“有点”误导。

来自ASCIIPoV,有明显区别(例如):

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

从键盘的 PoV,情况有点不同(当按下一个键时):

  • a:第3行第2nd列的键,位于CapsLock 的右侧(在 US 键盘上)
  • A同上,但有:
    • 大写锁定
    • Shift 也按下

[MS.Docs]: Virtual-Key Codes 说清楚了:为了检查 A(或 a)的状态,0x41 (65)必须勾选(97对应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)

输出:

[cfati@CFATI-5510-0:e:\Work\Dev\Whosebug\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
...

如何使用函数的示例:

def is_key_pressed(virtual_key_code):
    return bool(GetKeyState(virtual_key_code) >> 15)


# Examples

is_key_pressed(ord("A"))  # A (a)
is_key_pressed(0x1B)  # Esc