1

I am trying to determine which keyboard a key was pressed on in C++. For example, if I press the 'a' key on one keyboard, it prints 1 and if the 'a' key was pressed on a different keyboard then it prints 2. I really only need it for Windows.

Also, I only want to use standard libraries. I have used GetInputDeviceInfo/list to get all keyboards, however, I am unsure how to continue from here. I have tried looking online which has got me so far but I can not find anything to help with getting the current input device in order to compare it to the list.

If it is just not possible with Windows to do this, is there any other way to differentiate between the keyboards?

Any help would be appreciated. This is my first question on here so I apologise if I have not given enough detail, I will try to add more if asked. I'll also add the relevant code soon, it's messy so I need to clean it up before I post it.

Edit

Here it is:

int find_devices()
{

    vector <int> keyboard_index;



       // Get Number Of Devices
    UINT nDevices = 0;
    GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST));

    // Got Any?
    if (nDevices < 1)
    {
        // Exit
        cout << "ERR: 0 Devices?";
        cin.get();
        return 0;
    }

    // Allocate Memory For Device List
    PRAWINPUTDEVICELIST pRawInputDeviceList;
    pRawInputDeviceList = new RAWINPUTDEVICELIST[sizeof(RAWINPUTDEVICELIST) * nDevices];

    // Got Memory?
    if (pRawInputDeviceList == NULL)
    {
        // Error
        cout << "ERR: Could not allocate memory for Device List.";
        cin.get();
        return 0;
    }

    // Fill Device List Buffer
    int nResult;
    nResult = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST));

    // Got Device List?
    if (nResult < 0)
    {
        // Clean Up
        delete[] pRawInputDeviceList;

        // Error
        cout << "ERR: Could not get device list.";
        cin.get();
        return 0;
    }

    // Loop Through Device List
    for (UINT i = 0; i < nDevices; i++)
    {
        // Get Character Count For Device Name
        UINT nBufferSize = 0;
        nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device
            RIDI_DEVICENAME,                // Get Device Name
            NULL,                           // NO Buff, Want Count!
            &nBufferSize);                 // Char Count Here!

                                           // Got Device Name?
        if (nResult < 0)
        {
            // Error
            cout << "ERR: Unable to get Device Name character count.. Moving to next device." << endl << endl;

            // Next
            continue;
        }

        // Allocate Memory For Device Name
        WCHAR* wcDeviceName = new WCHAR[nBufferSize + 1];

        // Got Memory
        if (wcDeviceName == NULL)
        {
            // Error
            cout << "ERR: Unable to allocate memory for Device Name.. Moving to next device." << endl << endl;

            // Next
            continue;
        }

        // Get Name
        nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device
            RIDI_DEVICENAME,                // Get Device Name
            wcDeviceName,                   // Get Name!
            &nBufferSize);                 // Char Count

                                           // Got Device Name?
        if (nResult < 0)
        {
            // Error
            cout << "ERR: Unable to get Device Name.. Moving to next device." << endl << endl;

            // Clean Up
            delete[] wcDeviceName;

            // Next
            continue;
        }

        // Set Device Info & Buffer Size
        RID_DEVICE_INFO rdiDeviceInfo;
        rdiDeviceInfo.cbSize = sizeof(RID_DEVICE_INFO);
        nBufferSize = rdiDeviceInfo.cbSize;

        // Get Device Info
        nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice,
            RIDI_DEVICEINFO,
            &rdiDeviceInfo,
            &nBufferSize);

        // Got All Buffer?
        if (nResult < 0)
        {
            // Error
            cout << "ERR: Unable to read Device Info.. Moving to next device." << endl << endl;

            // Next
            continue;
        }



        // Keyboard
        else if (rdiDeviceInfo.dwType == RIM_TYPEKEYBOARD)
        {
            // Current Device
            cout << endl << "Displaying device " << i + 1 << " information. (KEYBOARD)" << endl;
            wcout << L"Device Name: " << wcDeviceName << endl;
            cout << "Keyboard mode: " << rdiDeviceInfo.keyboard.dwKeyboardMode << endl;
            cout << "Number of function keys: " << rdiDeviceInfo.keyboard.dwNumberOfFunctionKeys << endl;
            cout << "Number of indicators: " << rdiDeviceInfo.keyboard.dwNumberOfIndicators << endl;
            cout << "Number of keys total: " << rdiDeviceInfo.keyboard.dwNumberOfKeysTotal << endl;
            cout << "Type of the keyboard: " << rdiDeviceInfo.keyboard.dwType << endl;
            cout << "Subtype of the keyboard: " << rdiDeviceInfo.keyboard.dwSubType << endl;

            keyboard_index.push_back(i);
        }


        // Delete Name Memory!
        delete[] wcDeviceName;
    }

    // Clean Up - Free Memory
    //delete[] pRawInputDeviceList;

    // Exit


    for(int t = 0; t < abs(keyboard_index.size()); t++)
    {

        cout << keyboard_index[t] << endl << pRawInputDeviceList[keyboard_index[t]].hDevice;

    }




for(int r = 0; r == 0;)
{
    if(GetKeyState('A') & 0x8000/*Check if high-order bit is set (1 << 15)*/)
    {
            // Do stuff

    }

    else if(GetKeyState('B') & 0x8000/*Check if high-order bit is set (1 << 15)*/)
    {
            // Do stuff

        cout << "b\n";

        r = 1;


    }


return 1;

}

Edit

I've changed up the code so it uses WM_INPUT instead. It is still using all the keyboards however:

void InitRawInput(HWND hWnd)
{

    RAWINPUTDEVICE Rid[1];
    Rid[0].usUsagePage = 0x01;
    Rid[0].usUsage = 0x06;
    Rid[0].dwFlags = RIDEV_INPUTSINK;
    Rid[0].hwndTarget = hWnd;
    if (RegisterRawInputDevices(Rid,1,sizeof(Rid[0])) == false)
        {
        cout << "Registration failed" << endl;
        return;
        }
    cout << "Registration updated" << endl;
}
  • I have heard, some time ago, that it's possible in lua. Not sure about C++, though. – Algirdas Preidžius Sep 30 '19 at 13:39
  • have you tried Raw Input API? https://learn.microsoft.com/en-us/windows/win32/inputdev/raw-input?redirectedfrom=MSDN – Alex Pappas Sep 30 '19 at 13:56
  • 1
    @ColdCerberus I have tried Raw Input however I couldn't make it do anything useful. I could have been using it wrong though so some help with it would be appreciated. – the_anti_graviton Sep 30 '19 at 14:07
  • Possible duplicate of [How to distinguish Multiple Keyboards in Delphi?](https://stackoverflow.com/questions/3060512/how-to-distinguish-multiple-keyboards-in-delphi) – Botje Sep 30 '19 at 14:45
  • @Botje Possibly? I don't know enough to use it if it is. I have tried to go about it that way but it wasn't successful. However, from my understanding (I'm probably wrong) it's window has to be active for it to work whereas it would be better if it could work with, lets say, note pad open instead. – the_anti_graviton Sep 30 '19 at 16:44
  • @the_anti_graviton standard libraries do not have the functionality you are looking for. On Windows, the RAW Input API is the *only* way to differentiate which hardware is sending which events. If you are having trouble using the API, you need to ask about that. It is not enough to just query the available devices, you need to actually [register interest](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerrawinputdevices) for the devices you want to monitor, and then you need a window and message loop to receive `WM_INPUT` messages describing the hardware events – Remy Lebeau Sep 30 '19 at 17:05
  • @RemyLebeau Thanks, I have actually tried a RegisterRawInputDevices but I don't have enough information to use it properly I don't think. I'll add what I've done later, if you don't mind checking it, I would be grateful. – the_anti_graviton Sep 30 '19 at 17:50
  • @RemyLebeau The main reason I didn't carry on with that way was because the information I had read on it made me believe that it was window specific i.e would only work on one window when I wanted it to work on all. Please tell me if I am wrong so I can correct myself. – the_anti_graviton Sep 30 '19 at 18:04
  • @the_anti_graviton `RegisterRawInputDevices()` lets you specify a window to receive events to, but it does not monitor events for one specific window, it monitors globally and reports events before they are delivered to any particular target window. – Remy Lebeau Sep 30 '19 at 18:45
  • @RemyLebeau, Ahh thank you for clarifying, I would be grateful if you could give example code or a link to a tutorial or something to help me use it properly as many I have tried do not specify. You have helped me understand what I need to do now, thank you. I'll try it out and tell you if it works. – the_anti_graviton Sep 30 '19 at 19:21
  • @RemyLebeau, never mind I've made progress. The code it a bit long so I won't upload it unless needed but I've got the inputs from WM_INPUT. The only thing I need to do now is to make it only use one keyboard. At the moment it is using all of them. – the_anti_graviton Sep 30 '19 at 19:58
  • 1
    You WANT it to use all of the keyboards, so that you get `WM_INPUT` events from each keyboard. That is what you asked for, after all: "*I am trying to determine which keyboard a key was pressed on*". In the `WM_INPUT` message, the `lParam` will be a pointer to a `RAWINPUT` struct that identifies the specific keyboard in the `header.hDevice` field and the key press info in the `keyboard` field. – Remy Lebeau Sep 30 '19 at 21:06
  • @RemyLebeau Thank you so much for your comments, they have helped clarify things for me, not only on this topic but others as well. You also pointed me in the right direction in terms of research (Better than Google anyways). I have now successfully completed my project thanks to you. – the_anti_graviton Oct 01 '19 at 11:22

0 Answers0