开发者集成文档
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串口已关闭')