1.查找windows API 手册,调用GetRawInputData函数,可以获得按下的键值VKey以及唯一的句柄hDevice,但是hDevice并不能直观的对应不同键盘而且每当拔下键盘,重新插入的时候hDevice会发生变化。
2.继续查找发现可以通过GetRawInputDeviceInfo函数,找到按键所对应的具体来源。函数第一个参数是设备句柄,第二个参数根据想要获得的内容填写,一开始我在第二个参数填写的是RIDI_DEVICEINFO,发现获得数值无法区分不同设备。
3.后来经过测试,填写RIDI_DEVICENAME,即读取设备名,能找出不同设备的区别,后经过对应,得到的是设备管理器对应出的设备实例路径,由此确定了唯一,并且拔下键盘后再插上,deviceName没有发生改变。
附上代码
(获取按键同时得到的信息)
::GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &rawinputData, &uiSize, sizeof(RAWINPUTHEADER));
if (RIM_TYPEKEYBOARD == rawinputData.header.dwType)
{
// WM_KEYDOWN --> 普通按键 WM_SYSKEYDOWN --> 系统按键(指的是ALT)
if ((WM_KEYDOWN == rawinputData.data.keyboard.Message) ||
(WM_SYSKEYDOWN == rawinputData.data.keyboard.Message))
{
qDebug() << "keyboard.VKey ==" << (QChar)rawinputData.data.keyboard.VKey;
qDebug() << "header.hDevice" << rawinputData.header.hDevice;
UINT bufferSize;//为键盘设备名准备缓冲区大小
::GetRawInputDeviceInfo(rawinputData.header.hDevice, RIDI_DEVICENAME, NULL, &bufferSize);
WCHAR* RawDevName = new WCHAR[bufferSize];
::GetRawInputDeviceInfo(rawinputData.header.hDevice, RIDI_DEVICENAME, RawDevName, &bufferSize);//将设备名读入缓冲区RawDevName
QString devName = QString::fromWCharArray(RawDevName);
qDebug() << "dev ===" << devName;
delete[] RawDevName;
// RID_DEVICE_INFO device_info;
// UINT info_size (sizeof (RID_DEVICE_INFO));
// if (GetRawInputDeviceInfo (rawinputData.header.hDevice,
// RIDI_DEVICEINFO, (LPVOID)&device_info, &info_size) == info_size)
// {
// DWORD errorCode1 = GetLastError();
// qDebug()<<"errorCode1 = "<
// if (device_info.dwType == RIM_TYPEKEYBOARD)
// {
// qDebug()<<"device_info dwType= "<
// }
// }
}
}
(获取所有设备详情)
int MainWindow::GetUSBDeviceInfos(QList<USB_INFO> &infos)
{
infos.clear();
bool ok;
QString str;
USB_INFO info;
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
WCHAR buffer[INTERFACE_DETAIL_SIZE] = { 0 };
if ((hDevInfo = SetupDiGetClassDevs(NULL, L"USB", 0, DIGCF_PRESENT | DIGCF_ALLCLASSES)) == INVALID_HANDLE_VALUE){
// Insert error handling here.
return 0;
}
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
// 设备序号=0,1,2... 逐一测试设备接口,到失败为止
for (int i = 0; SetupDiEnumDeviceInfo(hDevInfo, i,
&DeviceInfoData); i++)
{
DWORD DataT;
DWORD buffersize = 0;
if(!SetupDiGetDeviceRegistryProperty(
hDevInfo,
&DeviceInfoData,
SPDRP_HARDWAREID,
&DataT,
(PBYTE)buffer,
INTERFACE_DETAIL_SIZE,
&buffersize))
{
continue;
}
str = QString::fromWCharArray(buffer, wcslen(buffer));
info.vid = str.mid(str.indexOf("VID") + 4, 4).toULong(&ok, 16);
info.pid = str.mid(str.indexOf("PID") + 4, 4).toULong(&ok, 16);
memset(buffer, 0, INTERFACE_DETAIL_SIZE);
if (!SetupDiGetDeviceRegistryProperty(
hDevInfo,
&DeviceInfoData,
SPDRP_DEVICEDESC, // 设备描述信息
&DataT,
(PBYTE)buffer,
INTERFACE_DETAIL_SIZE,
&buffersize))
{
continue;
}
info.desc = QString::fromWCharArray(buffer);
memset(buffer, 0, INTERFACE_DETAIL_SIZE);
if (!SetupDiGetDeviceRegistryProperty(
hDevInfo,
&DeviceInfoData,
SPDRP_LOCATION_INFORMATION, // LocationInformation (R/W)
&DataT,
(PBYTE)buffer,
INTERFACE_DETAIL_SIZE,
&buffersize))
{
continue;
}
info.locationInfo = QString::fromWCharArray(buffer);
memset(buffer, 0, INTERFACE_DETAIL_SIZE);
if (!SetupDiGetDeviceRegistryProperty(
hDevInfo,
&DeviceInfoData,
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, // PhysicalDeviceObjectName (R)
&DataT,
(PBYTE)buffer,
INTERFACE_DETAIL_SIZE,
&buffersize))
{
continue;
}
info.devName = QString::fromWCharArray(buffer);
memset(buffer, 0, INTERFACE_DETAIL_SIZE);
if (!SetupDiGetDeviceRegistryProperty(
hDevInfo,
&DeviceInfoData,
SPDRP_CLASSGUID, // ClassGUID (R/W)
&DataT,
(PBYTE)buffer,
INTERFACE_DETAIL_SIZE,
&buffersize))
{
continue;
}
info.guid = QString::fromWCharArray(buffer);
ULONG pulStatus;
ULONG pulProblemNumber;
CM_Get_DevNode_Status(&pulStatus, &pulProblemNumber, DeviceInfoData.DevInst, 0);
if((pulStatus & DN_HAS_PROBLEM) && !(pulStatus & DN_DRIVER_LOADED))
{
info.enable = false;
}else
{
info.enable = true;
}
qDebug() << "设备启用标志 ===="<< info.enable;
qDebug() << "产品ID ===="<< info.vid;
qDebug() << "厂商ID ===="<< info.pid;
qDebug() << "设备描述信息 ===="<< info.desc;
qDebug() << "LocationInformation ===="<< info.locationInfo;
qDebug() << "PhysicalDeviceObjectName ==" << info.devName;
qDebug() << "ClassGUID (R/W) ==" << info.guid;
infos.append(info);
}
// Cleanup
SetupDiDestroyDeviceInfoList(hDevInfo);
return 0;
}
将两段代码整合,通过设备实例ID部分内容对应
BOOL GetDeviceInstanceId(HDEVINFO hDevInfo, SP_DEVINFO_DATA* DeviceInfoData,PWSTR strID)
{
DWORD iRequiredSize = 0;
int iSize = 0;
BOOL b = SetupDiGetDeviceInstanceId(hDevInfo, DeviceInfoData, strID, iSize, &iRequiredSize);
iSize = iRequiredSize;
b = SetupDiGetDeviceInstanceId(hDevInfo, DeviceInfoData, strID, iSize, &iRequiredSize);
if (true == b)
{
return TRUE;
}
return FALSE;
}