Windows下PyQt如何区分USB RFID阅读器与真实键盘的按键事件?
在PyQt中区分RFID虚拟键盘与真实键盘,以及其他数据获取方案(Windows)
一、区分按键事件的来源(真实键盘 vs RFID虚拟键盘)
Qt的QKeyEvent本身不携带设备来源信息,但可以通过调用Windows原生API实现区分:
- 核心思路:利用Windows的
GetMessageExtraInfo()函数获取按键消息的额外信息,其中包含发送消息的HID设备标识;提前获取RFID阅读器的设备ID,在事件触发时对比判断。 - 具体实现步骤:
- 用
ctypes调用Windows API,获取当前按键消息对应的设备句柄/ID; - 从设备管理器中查看你的Elatec阅读器的VID/PID(格式为
0xXXXX),作为设备唯一标识; - 在PyQt的
keyPressEvent中,获取当前设备标识并与阅读器的对比,从而区分来源。
- 用
整合后的测试代码:
import sys import ctypes from PyQt5.QtWidgets import (QApplication, QWidget) # Windows API定义 user32 = ctypes.WinDLL('user32', use_last_error=True) GetMessageExtraInfo = user32.GetMessageExtraInfo GetMessageExtraInfo.restype = ctypes.LPARAM # 替换为你的RFID阅读器的VID和PID(从设备管理器获取) RFID_VID = 0xXXXX RFID_PID = 0xXXXX def get_device_vid_pid(handle): # 通过设备句柄获取VID/PID,需调用setupapi.dll相关函数 # 此处为简化示例,实际需补充完整的设备枚举逻辑 # 可参考Windows SDK中SetupDiGetDeviceRegistryProperty等函数的用法 return (0, 0) class MainWindow(QWidget): def __init__(self): super().__init__() def keyPressEvent(self, event): extra_info = GetMessageExtraInfo() # 提取设备句柄(低32位) device_handle = ctypes.c_void_p(extra_info & 0xFFFFFFFF) vid, pid = get_device_vid_pid(device_handle) if vid == RFID_VID and pid == RFID_PID: print(f"来自RFID阅读器的按键: {event.key()}") else: print(f"来自真实键盘的按键: {event.key()}") if __name__ == '__main__': app = QApplication(sys.argv) demo = MainWindow() demo.show() sys.exit(app.exec_())
二、其他获取RFID数据的方式
针对Elatec TWN4系列阅读器,除虚拟键盘模式外,还有更可靠的方案:
- 使用厂商官方SDK:Elatec提供Windows平台的SDK,包含直接与设备通信的API,无需依赖键盘模拟,可直接获取RFID标签的完整数据,还能配置设备工作模式。
- 切换到HID数据模式:查看设备文档,将阅读器切换为HID数据模式(非键盘模拟),此时设备会以HID报告的形式发送数据,可通过Python的
hidapi库直接读取并解析。 - Raw Input API监听:通过Windows的Raw Input API捕获HID设备的原始输入,绕过键盘模拟层直接获取数据,需处理HID报告的解析逻辑。
HID模式读取示例(使用hidapi)
- 安装依赖库:
pip install hidapi - 示例代码(替换为你的设备VID/PID):
import hid # 替换为你的设备VID和PID VID = 0xXXXX PID = 0xXXXX try: device = hid.device() device.open(VID, PID) print("成功连接RFID阅读器") while True: # 读取HID报告,长度参考设备文档调整 data = device.read(64) if data: rfid_data = bytes(data).hex() print(f"读取到RFID数据: {rfid_data}") except Exception as e: print(f"连接失败: {e}") finally: device.close()
内容的提问来源于stack exchange,提问作者ddhb
相关产品推荐
相关产品推荐

