Windows下通过USB虚拟的键盘鼠标总结
产品级详见:https://www.usbzh.com/article/detail-1182.html
哐哐铛铛的,终于把以前搞的虚拟键盘、鼠标的驱动代码重新整理完成,并且在此基础上将USB虚拟的键盘和鼠标整合到一个驱动中。
将键盘和鼠标的代码合并在一起的原因很简单:
- 第一是为了验证自己写的这个虚拟的总线的功能
- 第二就是键盘一般和鼠标是联系在一起的,用键盘的地方大部也要用到鼠标。所以干脆将这两个设备合并到一起,这样在创建的时候可以一起创建,也可以一起销毁。当然键盘和鼠标的数据可以通过应用层分开下发给驱动的。
实现的最终效果如下图:
该驱动被命名为USBzhVKM,usbzh当然是本站USB中文网的词牌名了。VKM就是virtual keyboard & mouse的缩写了。
本人开发的这个驱动使用的是VS2019+WDK10实现的,可以编译成X64也可以编译成X86的,对于老的系统如win7之类的系统的支持可以参考本人在pnpon内核开发网发的这篇文章 Win10和Win7驱动security_init_cookie蓝屏兼容问题 http://www.pnpon.com/article/detail-120.html 进行工程的修改。
工程我这就不修改了,因为本人使用的电脑环境现在全是win10环境了。
这里介绍一下自己写的应用层通读接口,之前也发过鼠标的应用及调试文章,可见:
- Win10使用虚拟USB鼠标实现自动挂机测试功能 http://www.usbzh.com/article/detail-476.html
- Windows10下开发虚拟USB鼠标之枚举子设备失败(STATUS_DEVICE_DATA_ERROR)http://www.usbzh.com/article/detail-510.html
驱动层:
使用VS2019打开工程如下图:
可以看到,本人还是将代码整理的比较清晰的(哈哈~),基本上做了代码属于那层的在那个文件中…
或程编译后,生成的文件如下:
usbzhvkm.cat
UsbzhVKM.inf
UsbzhVKM.sys
驱动的安装这里可以调用本人写的一个批处理文件 install.bat,代码比较简单,是直接使用devcon.exe来进行驱动的安装的。
CD /d %~dp0
devcon.exe install UsbzhVKM.inf "root\UsbzhVKM"
应用层
应用层本人鬼使神差的命名了一个D2004的工程.界面如下:
程序主要是通过DeviceIoControl与自己写的驱动进行数据通讯,本人编写了一个类,封装了几个函数:
class CUsb
{
public:
CUsb();
~CUsb();
public:
HANDLE m_hDevice;
public:
static BOOL USBEnumDevice(OUT PTCHAR pDeviceName, IN int instance);
BOOL UsbOpenDevice(PTCHAR pDeviceName);
VOID UsbClose();
BOOL SetMouseData(PVOID pData, ULONG nLen, PULONG pRtn);
BOOL SetKeyBoard(PVOID pData, ULONG nLen, PULONG pRtn);
BOOL PluginDevice();
BOOL UnPluginDevice();
};
可以看到,通过USBEnumDevice枚举出设备,然后调用UsbOpenDevice打开设备,这样就可以使用PluginDevice和UnPluginDevice在设备管理器中创建和销毁虚拟的USB键盘和USB鼠标设备了。
默认安装了驱动后,不创建虚拟键盘和鼠标。
当设备创建之后,可以分别调用对应的函数进行鼠标报告内容和键盘报告内容的写入给驱动,这样驱动给将该报告内容转成标准的USB事件上报给系统。
关于报告的格式可详见:
- 键盘的报表内容格式见:http://www.usbzh.com/article/detail-13.html
- 鼠标的报表内容格式见:http://www.usbzh.com/article/detail-327.html
这里本人写了一个简单的测试用列:
键盘的模拟:
void CVMouseDlg::OnBnClickedButtonKeyBoardTest()
{
ULONG rtn = 0;
UCHAR data[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
Sleep(1000);
for (int i = 0; i < 40; i++)
{
data[2] = 0x04 + i;
m_usb.SetKeyBoard(data, 8, &rtn);//按下
Sleep(100);
data[2] = 0;
m_usb.SetKeyBoard(data, 8, &rtn);//弹起
Sleep(200);
}
}
鼠标的模拟,这里没有写滚轮的:
void CVMouseDlg::MouseLeft()
{
ULONG rtn = 0;
UCHAR data[4] = { 0x00,0xFF,0x00,0x00 };
m_usb.SetMouseData(data, 4, &rtn);
}
void CVMouseDlg::MouseRight()
{
ULONG rtn = 0;
UCHAR data[4] = { 0x00,0x01,0x00,0x00 };
m_usb.SetMouseData(data, 4, &rtn);
}
void CVMouseDlg::MouseUp()
{
ULONG rtn = 0;
UCHAR data[4] = { 0x00,0x00,0xff,0x00 };
m_usb.SetMouseData(data, 4, &rtn);
}
void CVMouseDlg::MouseDown()
{
ULONG rtn = 0;
UCHAR data[4] = { 0x00,0x00,0x01,0x00 };
m_usb.SetMouseData(data, 4, &rtn);
}
void CVMouseDlg::MouseLeftClickDown()
{
ULONG rtn = 0;
UCHAR data[4] = { 0x01,0x00,0x000,0x00 };
m_usb.SetMouseData(data, 4, &rtn);
}
void CVMouseDlg::MouseLeftClickUp()
{
ULONG rtn = 0;
UCHAR data[4] = { 0x00,0x00,0x000,0x00 };
m_usb.SetMouseData(data, 4, &rtn);
}