調研一臺電腦連接兩個鍵盤如何區分遇到的問題及解決方法

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 = "<<errorCode1;
            //                if (device_info.dwType == RIM_TYPEKEYBOARD)
            //                {
            //                    qDebug()<<"device_info dwType= "<<device_info.keyboard.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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章