【问题标题】:ctypes.windll.user32.GetKeyState not recognizing key pressesctypes.windll.user32.GetKeyState 无法识别按键
【发布时间】:2021-12-04 12:42:56
【问题描述】:

我有一个问题,ctypes.windll.user32.GetKeyState 无法检测到我键盘上的键(A、B、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 的一些限制?

【问题讨论】:

  • 我不使用 Windows,但可能 GetKeyState 使用不同的值,然后您从 ord('a') 获得。 ord() 提供char code,但系统可能使用不同的代码来检测密钥(硬件)在Linux 上,您可能会得到keycode,这与char code 不同。系统获取键码并转换为取决于键盘布局的字符码(相同的键为英语或法语布局提供不同的字符)顺便说一句:有像keyboardpynput 这样的 Python 模块可以检测按下的键。也许你应该检查源代码,看看他们是否使用GetKeyState

标签: python windows keyboard ctypes


【解决方案1】:

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

虚拟钥匙。如果所需的虚拟键是字母或数字(A 到 Z、a 到 z 或 0 到 9),则必须将 nVirtKey 设置为 ASCII 值 的那个字符。其他键必须是虚拟键码。

“有点”误导。

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

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

从键盘的 PoV 来看,情况有点不同(按下键时):

  • a:第 3rd 行和第 2nd 列的键,在 CapsLock 的右侧(在 美国键盘)
  • A同上,但使用以下任一:
    • CapsLock 开启
    • Shift 也按下了

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

函数使用示例:

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

【讨论】:

  • 感谢您的精彩回复!但是如何将字符代码转换为这些类型?
  • 什么意思?我举了一个 A (a) 的例子,所有其他字母/数字都是一样的。其他键码在第二个 URL.
  • 好的,我知道了。谢谢!
猜你喜欢
  • 2021-05-11
  • 2015-07-04
  • 1970-01-01
  • 1970-01-01
  • 2021-05-07
  • 1970-01-01
  • 2019-08-18
  • 2020-10-09
相关资源
最近更新 更多