玩家社区LOGO

玩家社区

开发者集成文档

Player Community Integration Guide

HID定制协议 DLL Direct

高性能直驱方案,适用于宏盒子MINI。通过加载 DLL 即可直接接管物理鼠标控制流。

易语言声明示例:

================================================================ hid.dll - HID鼠标控制 DLL 易语言调用说明 ================================================================ 一、文件部署 ----------- 将 hid.dll 复制到64位程序的 exe 同目录下。 二、DLL命令声明 -------------- 在易语言中,新建一个"DLL命令"模块,添加以下声明: ┌─────────────────────────────────────────────────────────────┐ │ .版本 2 │ │ │ │ .DLL命令 MH_Open, 整数型, "hid.dll", "MH_Open" │ │ '自动扫描并连接设备, 返回0=成功 │ │ │ │ .DLL命令 MH_Close, , "hid.dll", "MH_Close" │ │ '断开设备 │ │ │ │ .DLL命令 MH_IsOpen, 整数型, "hid.dll", "MH_IsOpen" │ │ '检查是否已连接, 返回1=已连接, 0=未连接 │ │ │ │ .DLL命令 MH_GetLastError, 整数型, "hid.dll", "MH_GetLastError" │ │ '返回错误信息字符串指针 │ │ │ │ .DLL命令 MH_GetDeviceName, 整数型, "hid.dll", "MH_GetDeviceName" │ │ '返回设备名称字符串指针 │ │ │ │ .DLL命令 MH_Ping, 整数型, "hid.dll", "MH_Ping" │ │ .参数 版本缓冲区, 整数型 │ │ .参数 缓冲区大小, 整数型 │ │ '通信测试, 版本缓冲区传0则不获取版本 │ │ │ │ .DLL命令 MH_MouseMove, 整数型, "hid.dll", "MH_MouseMove" │ │ .参数 X位移, 整数型 │ │ .参数 Y位移, 整数型 │ │ '鼠标相对移动 │ │ │ │ .DLL命令 MH_MouseButton, 整数型, "hid.dll", "MH_MouseButton" │ │ .参数 按键位图, 整数型 │ │ '按键控制: 1=左键 2=右键 4=中键 8=侧键1 16=侧键2, 0=全松开 │ │ │ │ .DLL命令 MH_MouseClickLeft, 整数型, "hid.dll", "MH_MouseClickLeft" │ │ .参数 按住毫秒, 整数型 │ │ '左键点击, 传0则默认50ms │ │ │ │ .DLL命令 MH_MouseClickRight, 整数型, "hid.dll", "MH_MouseClickRight" │ │ .参数 按住毫秒, 整数型 │ │ '右键点击 │ │ │ │ .DLL命令 MH_MouseClickMiddle, 整数型, "hid.dll", "MH_MouseClickMiddle" │ │ .参数 按住毫秒, 整数型 │ │ '中键点击 │ │ │ │ .DLL命令 MH_MouseWheel, 整数型, "hid.dll", "MH_MouseWheel" │ │ .参数 滚轮值, 整数型 │ │ '滚轮: 正数=上滚, 负数=下滚, 范围-127~127 │ │ │ │ .DLL命令 MH_MouseAll, 整数型, "hid.dll", "MH_MouseAll" │ │ .参数 按键位图, 整数型 │ │ .参数 X位移, 整数型 │ │ .参数 Y位移, 整数型 │ │ .参数 滚轮值, 整数型 │ │ '全参数控制: 一次性设置按键+移动+滚轮 │ │ │ │ .DLL命令 MH_MouseAutoMove, 整数型, "hid.dll", "MH_MouseAutoMove" │ │ .参数 步数, 整数型 │ │ .参数 X数组指针, 整数型 │ │ .参数 Y数组指针, 整数型 │ │ .参数 间隔毫秒, 整数型 │ │ '多步平滑移动, 最多10步 │ │ │ │ .DLL命令 MH_MouseMoveClick, 整数型, "hid.dll", "MH_MouseMoveClick" │ │ .参数 X位移, 整数型 │ │ .参数 Y位移, 整数型 │ │ .参数 按住毫秒, 整数型 │ │ '移动后左键点击 │ │ │ │ .DLL命令 MH_MonitorStart, 整数型, "hid.dll", "MH_MonitorStart" │ │ .参数 模式, 整数型 │ │ .参数 回调指针, 整数型 │ │ '启用按键监听: 模式1=仅按键, 2=按键+移动; 回调传0则用轮询 │ │ │ │ .DLL命令 MH_MonitorStop, 整数型, "hid.dll", "MH_MonitorStop" │ │ '关闭按键监听 │ │ │ │ .DLL命令 MH_PollButtonEvent, 整数型, "hid.dll", "MH_PollButtonEvent" │ │ .参数 按键状态, 整数型, 传址 │ │ .参数 变化位, 整数型, 传址 │ │ .参数 按下位, 整数型, 传址 │ │ .参数 松开位, 整数型, 传址 │ │ '轮询按键事件, 返回1=有事件, 0=无事件 │ └─────────────────────────────────────────────────────────────┘ 三、常量定义 ----------- 返回码: 0 = 成功 -1 = 未找到设备 -2 = 打开设备失败 -3 = 设备未打开 -4 = 发送失败 -5 = 响应超时 -6 = 参数错误 按键位图: 1 = 左键 (0x01) 2 = 右键 (0x02) 4 = 中键 (0x04) 8 = 侧键1 (0x08) 16 = 侧键2 (0x10) 可以用"位或"组合多个按键, 例如: 1 + 2 = 同时按左键和右键 四、使用示例 ----------- 【示例1: 基本使用】 .子程序 测试鼠标控制 .局部变量 结果, 整数型 ' 连接设备 结果 = MH_Open () 如果 (结果 ≠ 0) 信息框 ("连接设备失败!", 0, ) 返回 () 如果结束 ' 移动鼠标 MH_MouseMove (100, 50) ' 向右100, 向下50 延时 (500) ' 左键点击 MH_MouseClickLeft (0) ' 默认50ms 延时 (500) ' 右键点击 MH_MouseClickRight (80) ' 按住80ms 延时 (500) ' 滚轮上滚 MH_MouseWheel (3) ' 断开 MH_Close () 【示例2: 独立按键控制】 ' 按下左键 (不松开) MH_MouseButton (1) 延时 (1000) ' 同时按下左键+右键 MH_MouseButton (1 + 2) 延时 (500) ' 只松开左键, 保持右键 MH_MouseButton (2) 延时 (500) ' 全部松开 MH_MouseButton (0) 【示例3: 移动+按键+滚轮 同时控制】 ' 按住左键的同时移动并滚轮 MH_MouseAll (1, 50, -30, 2) 延时 (100) ' 松开所有 MH_MouseAll (0, 0, 0, 0) 【示例4: 按键监听 (定时器轮询方式)】 .子程序 启动监听 MH_MonitorStart (1, 0) ' 模式1, 不用回调 时钟1.时钟周期 = 10 ' 10ms轮询 .子程序 时钟1_周期事件 .局部变量 按键, 整数型 .局部变量 变化, 整数型 .局部变量 按下, 整数型 .局部变量 松开, 整数型 如果 (MH_PollButtonEvent (按键, 变化, 按下, 松开) = 1) ' 有按键变化事件 如果 (位与 (按下, 1) ≠ 0) ' 左键被按下 如果结束 如果 (位与 (松开, 2) ≠ 0) ' 右键被松开 如果结束 如果结束 五、编译 DLL ----------- 1. 安装 Visual Studio (需要 C/C++ 工具) 2. 双击运行 build.bat 3. 首次运行会自动下载 hidapi 源码 (需要 git) 4. 编译完成后 hid.dll 在当前目录 如果没有 git, 手动下载: https://github.com/libusb/hidapi/archive/refs/heads/master.zip 解压后将 hidapi-master 文件夹重命名为 hidapi, 放到 dll 目录下 六、注意事项 ----------- 1. DLL 为 64 位, 程序也必须是 64位 2. 设备必须已通过 USB 连接到电脑 3. 同一时间只能有一个程序打开该设备 4. MH_Open 会自动扫描并选择最匹配的设备 (接口2) 5. 所有移动命令都是相对位移, 不是绝对坐标 6. MH_MouseButton 发送的是完整按键状态, 不是增量 例如: 先发 MH_MouseButton(1) 按下左键 再发 MH_MouseButton(0) 松开左键 不能发 MH_MouseButton(1) 然后 MH_MouseButton(2) 来"追加"右键 应该发 MH_MouseButton(1+2) = MH_MouseButton(3)
网络协议 TCP/UDP

通过 IP 连接,支持强大的监控模式(Monitor)。可以监听物理鼠标状态并同步发送补偿指令。

鼠标状态检测与移动控制 :

''' 按住鼠标左键右下移动 按住鼠标右键左上移动 ''' import kmNet import time #连接盒子 ip='192.168.2.188' port ='8888' uuid ='1234abcd' kmNet.init(ip,port,uuid) print('连接盒子ok') kmNet.monitor(12345) # 开启物理键鼠监控功能。使用端口号12345接收物理键鼠数据 kmNet.mask_left(1) kmNet.mask_right(1) print('按下鼠标左键斜向下移动,按下鼠标右键斜向上移动,按下鼠标中键退出测试') while 1: if kmNet.isdown_left() == 1:#如果鼠标左键按下 print('left down') kmNet.move(1, 1) if kmNet.isdown_right() == 1:#如果鼠标右键按下 print('right down') kmNet.move(-1, -1) if kmNet.isdown_middle() == 1:#如果鼠标中键按下 print('exit') break time.sleep(0.01) # 10ms移动一次 kmNet.monitor(0) #关闭监控 kmNet.unmask_all()#解除所有屏蔽

基础移动任务 (鼠标移动任务.py):

import kmNet import time #连接盒子 ip='192.168.1.10' port ='1000' uuid ='25ABDBB2' kmNet.init(ip,port,uuid) time.sleep(3) kmNet.left(1) time.sleep(0.05) kmNet.left(0) time.sleep(0.05) kmNet.right(1) time.sleep(0.05) kmNet.right(0) time.sleep(0.05) kmNet.enc_move_beizer(10,10,10,10,10,10,10) time.sleep(0.05) kmNet.enc_move_auto(10,10,10) time.sleep(0.05) kmNet.enc_move(10,10) time.sleep(0.05) kmNet.move(10,10) time.sleep(0.05) kmNet.move_auto(10,10,10) time.sleep(0.05) kmNet.move_beizer(10,10,10,10,10,10,10) time.sleep(0.05)
串口协议 COM

基于标准串口通信。适用于通过 USB 直接连接电脑的应用场景。

按键映射与移动测试 (test_button_and_move.py):

import serial import time print('打开串口\n') ser = serial.Serial('COM3', 115200, timeout=0.1) # 添加超时 print('向kmbox发送 import km') ser.write('import km\r\n'.encode('utf-8')) time.sleep(0.1) print('kmbox回码如下:', ser.read(ser.in_waiting or 1)) # ========== 配置 ========== # 监听的按键: 'left' 左键, 'right' 右键, 'middle' 中键, 'side1' 侧键1, 'side2' 侧键2 BUTTON = 'middle' MOVE_STEP = 1 # 每次移动的像素 MOVE_DELAY = 0.001 # 移动间隔时间(秒) # ========================== # 按键配置映射 BUTTON_CONFIG = { 'left': {'cmd': 'km.left()', 'name': '左键', 'dx': -MOVE_STEP, 'dy': -MOVE_STEP}, 'right': {'cmd': 'km.right()', 'name': '右键', 'dx': MOVE_STEP, 'dy': MOVE_STEP}, 'middle': {'cmd': 'km.middle()', 'name': '中键', 'dx': 0, 'dy': -MOVE_STEP}, 'side1': {'cmd': 'km.side1()', 'name': '侧键1', 'dx': -MOVE_STEP, 'dy': 0}, 'side2': {'cmd': 'km.side2()', 'name': '侧键2', 'dx': MOVE_STEP, 'dy': 0}, } config = BUTTON_CONFIG.get(BUTTON, BUTTON_CONFIG['right']) BUTTON_CMD = config['cmd'] BUTTON_NAME = config['name'] MOVE_DX = config['dx'] MOVE_DY = config['dy'] def get_button_state(): """发送命令并获取按钮状态,返回1表示按住,0表示松开,-1表示无效""" ser.write(f'{BUTTON_CMD}\r\n'.encode('utf-8')) time.sleep(0.01) # 等待回码返回 response = ser.read(ser.in_waiting or 1).decode('utf-8', errors='ignore').strip() print(f'{BUTTON_CMD} 回码: [{response}]') try: return int(response) except: return -1 def move_mouse(): """移动鼠标""" ser.write(f'km.move({MOVE_DX},{MOVE_DY})\r\n'.encode('utf-8')) # 按键状态 pressed = False print(f'监听 {BUTTON_NAME},按 Ctrl+C 退出...') try: while True: state = get_button_state() if state == 1: if not pressed: print(f'{BUTTON_NAME}按下 -> 开始移动') pressed = True elif state == 0: if pressed: print(f'{BUTTON_NAME}松开 -> 停止移动') pressed = False # state == -1 保持原状态 if pressed: move_mouse() time.sleep(MOVE_DELAY) except KeyboardInterrupt: print('\n退出程序') finally: ser.close() print('串口已关闭')

点击测试 (test_left_click.py):

import serial import time # ========== 配置 ========== # 测试的按键: 'left' 左键, 'right' 右键, 'middle' 中键, 'side1' 侧键1, 'side2' 侧键2 BUTTON = 'left' HOLD_TIME = 5 # 按住时间(秒) # ========================== # 按键配置 BUTTONS = { 'left': {'press': 'km.left(1)', 'release': 'km.left(0)', 'name': '左键'}, 'right': {'press': 'km.right(1)', 'release': 'km.right(0)', 'name': '右键'}, 'middle': {'press': 'km.middle(1)', 'release': 'km.middle(0)', 'name': '中键'}, 'side1': {'press': 'km.side1(1)', 'release': 'km.side1(0)', 'name': '侧键1'}, 'side2': {'press': 'km.side2(1)', 'release': 'km.side2(0)', 'name': '侧键2'}, } def send_cmd(cmd): """发送命令并打印回码""" ser.write(f'{cmd}\r\n'.encode('utf-8')) time.sleep(0.01) response = ser.read(ser.in_waiting or 1).decode('utf-8', errors='ignore').strip() print(f'{cmd} 回码: [{response}]') return response def test_button(button_key): """测试单个按键的按下和松开""" if button_key not in BUTTONS: print(f'未知按键: {button_key}') return btn = BUTTONS[button_key] print(f'\n===== 测试 {btn["name"]} =====') # 按下 print(f'按下 {btn["name"]}...') send_cmd(btn['press']) # 保持 print(f'保持 {HOLD_TIME} 秒...') time.sleep(HOLD_TIME) # 松开 print(f'松开 {btn["name"]}...') send_cmd(btn['release']) print(f'{btn["name"]} 测试完成') print('打开串口\n') ser = serial.Serial('COM3', 115200, timeout=0.1) print('向kmbox发送 import km') ser.write('import km\r\n'.encode('utf-8')) time.sleep(0.1) print('kmbox回码如下:', ser.read(ser.in_waiting or 1)) # 测试指定按键 test_button(BUTTON) # 如需测试所有按键,取消下面注释: # for btn in ['left', 'right', 'middle', 'side1', 'side2']: # test_button(btn) # time.sleep(0.5) ser.close() print('\n串口已关闭')