windowsdirectxraw-inputdirectinput

How do I convert a RawInput RAWKEYBOARD structure to a DirectInput DIK_ constant?


I am converting an application that currently uses DirectInput to use RawInput instead. (DirectInput is a largely deprecated API.)

Unfortunately, despite RawInput being the recommended successor to DirectInput, it doesn't appear to provide keyboard data in quite the same way as DirectInput.

DirectInput uses DIK_* constants (such as DIK_A, DIK_RETURN, etc...) to define specific physical keys on the keyboard. These keys are consistent across keyboard hardware but do not change depending on keyboard layout. (For example, DIK_Q refers to whatever key is in the physical location that the Q key is at on a standard US-English QWERTY keyboard.) In my case, this is the desired behavior.

RawInput's RAWKEYBOARD structure provides both a MakeCode and a VKey. I can't use VKey because that changes depending on keyboard layout.

But the MakeCode doesn't correspond 1:1 with the DIK_* constants. In particular, it doesn't differentiate between left and right ctrl and alt keys, or most of the number pad keys from their other keys.

So my question is: Is it possible to use the contents of a RAWKEYBOARD structure to figure out the equivalent DIK_* constant? And assuming that the MakeCode is part of figuring that out, can I rely on MakeCode being constant across keyboard hardware, in the same way that the DIK_* constants are?


Solution

  • I'm not 100% sure this is reliable across all keyboard hardware, but it appears that I can use the MakeCode and Flags (specifically the RI_KEY_E0 and RI_KEY_E1 flags) fields of RAWKEYBOARD to determine the actual physical key that was pressed or released, and map this to a DIK_ constant. I used this table to determine most of the make/scan codes for individual keys, and then experimentation to figure out the scan/make codes and flags for the remaining keys.

    I have tested this on four different keyboards, and all produce identical make codes / flags: 2 USB keyboards, a PS/2 keyboard, and the built-in keyboard on a Macbook running bootcamp.

    I'd love to have some documented confirmation that I can rely on the make code and flags to be consistent across all keyboards, but so far this seems to be working fine.

    Update: It's now ~5 years later and my software has had tens of thousands of real-world users and I have not received a single report of incorrect key mapping. At this point I'm 99.999% confident this approach works consistently across all keyboards, with the caveat that I cannot be sure things won't change in the future.