Windows平台下Python指定键盘输入读取与宏转换问题求助
在Windows下用Python识别特定键盘输入的方案
方案1:使用Raw Input API(推荐,原生支持设备区分)
Windows的Raw Input API是区分不同输入设备的可靠方式,通过pywin32库即可调用,步骤如下:
1. 枚举所有键盘设备,定位目标键盘
先获取所有连接的键盘设备信息,找到旧键盘对应的设备句柄或名称:
import win32api import win32con from ctypes import windll, Structure, c_int, c_void_p, POINTER, sizeof class RAWINPUTDEVICELIST(Structure): _fields_ = [("hDevice", c_void_p), ("dwType", c_int)] def enum_keyboard_devices(): devices = [] count = c_int(0) # 获取设备列表长度 windll.user32.GetRawInputDeviceList(None, count, sizeof(RAWINPUTDEVICELIST)) device_list = (RAWINPUTDEVICELIST * count.value)() windll.user32.GetRawInputDeviceList(device_list, count, sizeof(RAWINPUTDEVICELIST)) for i in range(count.value): device = device_list[i] if device.dwType == win32con.RIM_TYPEKEYBOARD: # 获取设备名称缓冲区大小 buf_size = c_int(0) windll.user32.GetRawInputDeviceInfo(device.hDevice, win32con.RIDI_DEVICENAME, None, buf_size) name_buf = (c_int * buf_size.value)() windll.user32.GetRawInputDeviceInfo(device.hDevice, win32con.RIDI_DEVICENAME, name_buf, buf_size) device_name = win32api.GetUnicodeString(name_buf) devices.append({"hDevice": device.hDevice, "name": device_name}) return devices # 运行获取所有键盘设备,找到目标旧键盘的条目 keyboards = enum_keyboard_devices() for kb in keyboards: print(kb["name"])
运行后会输出所有键盘设备的名称,记录目标键盘的hDevice值。
2. 监听目标键盘的输入
注册Raw Input监听,只处理目标设备的输入(需管理员权限运行):
import win32api import win32gui import win32con from ctypes import windll, Structure, c_ushort, c_int, c_void_p, POINTER, sizeof class RAWINPUTHEADER(Structure): _fields_ = [ ("dwType", c_int), ("dwSize", c_int), ("hDevice", c_void_p), ("wParam", c_int) ] class RAWKEYBOARD(Structure): _fields_ = [ ("MakeCode", c_ushort), ("Flags", c_ushort), ("Reserved", c_ushort), ("VKey", c_ushort), ("Message", c_int), ("ExtraInformation", c_int) ] class RAWINPUT(Structure): _fields_ = [ ("header", RAWINPUTHEADER), ("data", RAWKEYBOARD) ] # 替换为目标键盘的hDevice TARGET_DEVICE_HANDLE = None def raw_input_proc(hwnd, msg, wparam, lparam): if msg == win32con.WM_INPUT: buf_size = c_int(0) windll.user32.GetRawInputData(lparam, win32con.RID_INPUT, None, buf_size, sizeof(RAWINPUTHEADER)) raw_input_buf = (c_int * buf_size.value)() windll.user32.GetRawInputData(lparam, win32con.RID_INPUT, raw_input_buf, buf_size, sizeof(RAWINPUTHEADER)) raw_input = RAWINPUT.from_buffer(raw_input_buf) # 过滤目标设备的输入 if raw_input.header.hDevice == TARGET_DEVICE_HANDLE: vkey = raw_input.data.VKey key_char = win32api.MapVirtualKey(vkey, win32con.MAPVK_VK_TO_CHAR) print(f"目标键盘输入: {chr(key_char) if key_char else vkey}") # 此处添加宏输出逻辑,比如用win32api模拟按键 # win32api.keybd_event(win32con.VK_RETURN, 0, 0, 0) # win32api.keybd_event(win32con.VK_RETURN, 0, win32con.KEYEVENTF_KEYUP, 0) return win32gui.DefWindowProc(hwnd, msg, wparam, lparam) # 创建隐藏窗口接收消息 wc = win32gui.WNDCLASS() wc.lpfnWndProc = raw_input_proc wc.lpszClassName = "RawInputListener" wc.hInstance = win32api.GetModuleHandle(None) class_atom = win32gui.RegisterClass(wc) hwnd = win32gui.CreateWindow(class_atom, "", 0, 0, 0, 0, 0, 0, 0, wc.hInstance, None) # 注册Raw Input监听键盘 raw_input_device = win32gui.RAWINPUTDEVICE() raw_input_device.usUsagePage = 1 raw_input_device.usUsage = 6 # 键盘设备的Usage ID raw_input_device.dwFlags = win32con.RIDEV_INPUTSINK raw_input_device.hwndTarget = hwnd win32gui.RegisterRawInputDevices([raw_input_device]) # 消息循环保持监听 while True: win32gui.PumpWaitingMessages()
方案2:使用pynput库(更简洁)
pynput封装了底层API,可快速实现特定设备监听:
1. 枚举设备并定位目标
from pynput import keyboard for device in keyboard.Device.list(): print(f"设备: {device}, 名称: {device.name}")
找到旧键盘对应的device对象。
2. 监听目标设备
from pynput import keyboard # 替换为目标键盘的名称关键词 target_device = None for d in keyboard.Device.list(): if "旧键盘名称关键词" in d.name: target_device = d break def on_press(key): print(f"目标键盘按下: {key}") # 宏输出逻辑示例:模拟回车 # controller = keyboard.Controller() # controller.press(keyboard.Key.enter) # controller.release(keyboard.Key.enter) def on_release(key): pass # 启动仅监听目标设备的监听器 listener = keyboard.Listener( on_press=on_press, on_release=on_release, device=target_device) listener.start() listener.join()
方案3:修复hid库的使用问题
若之前用hid库失败,大概率是未获取正确的设备VID/PID或权限不足:
- 打开设备管理器,找到旧键盘→属性→详细信息→硬件ID,提取
VID_XXXX和PID_XXXX(转为十进制)。 - 使用
hidapi连接并读取:
import hid # 替换为目标设备的VID和PID(十六进制转十进制) VID = 0xXXXX PID = 0xXXXX device = hid.device() device.open(VID, PID) device.set_nonblocking(True) while True: data = device.read(64) if data: # 按HID键盘协议解析数据:第2位为修饰键,第4位起为按键码 print(f"收到原始数据: {data}") # 此处可添加按键解析和宏输出逻辑 device.close()
内容的提问来源于stack exchange,提问作者Xandras
相关产品推荐
相关产品推荐

