I am trying to synthesize keystrokes via PostMessage()
and I need to generate the corresponding lParam
.
I am familiar with the KeyStrokeMessage
struct.
Here's the code:
///-------------------------------------------------------------------------------------------
/// KeystrokeMessage/KeyLParam struct
///-------------------------------------------------------------------------------------------
typedef struct KeystrokeMessage
{
unsigned RepeatCount : 16;
unsigned ScanCode : 8;
unsigned ExtendedFlag : 1;
unsigned Reserved : 4;
unsigned ContextCode : 1;
unsigned PreviousKeyState : 1;
unsigned TransitionState : 1;
} KeyLParam;
///-------------------------------------------------------------------------------------------
/// GetKeyMessageLPARAM:
/// Creates an LPARAM for key messages.
///-------------------------------------------------------------------------------------------
LPARAM GetKeyMessageLPARAM(unsigned aVKey, bool aIsDown, bool aIsSystem)
{
KeyLParam lp;
UINT sc = MapVirtualKeyA(aVKey, MAPVK_VK_TO_VSC_EX);
lp.RepeatCount = 1;
lp.ScanCode = LOBYTE(sc);
lp.ExtendedFlag = (HIBYTE(sc) == 0xE0 || HIBYTE(sc) == 0xE1) ? 1 : 0;
lp.Reserved = 0;
lp.ContextCode = aIsSystem ? 1 : 0;
lp.PreviousKeyState = aIsDown ? 0 : 1;
lp.TransitionState = aIsDown ? 0 : 1;
return *(LPARAM*)&lp;
}
I also intercepted genuine keystrokes to understand what I'm doing wrong.
Specifically, I'm trying to synthesize an "up arrow" keystroke, which is VK_UP
.
A genuine message for the "up arrow" has the wParam
set to VK_UP
and the lParam
has the scancode 0x48
with the extended flag set.
Genuine keystroke for reference:
The scancode should be 0xE048
(with the extended flag).
However, MapVirtualKey()
returns 72 (0x48
) and therefore it is not setting the ExtendedFlag
.
The documentation on MSDN states that it would return the extended flag.
I have tried MapVirtualKey()
and MapVirtualKeyEx()
.
In the Ex
versions, I've tried both the actual keyboard layout, as well as leaving it as 0.
I am using the correct map type MAPVK_VK_TO_VSC_EX
, but I also tried MAPVK_VK_TO_VSC
to see if the result is any different.
I even tried going the reverse route, starting with the actual scancode and converting it into a virtual key and then back into a scancode.
I get the correct VK_UP
but once again trying to get the scancode from that returns the wrong key.
No matter the input, I never get an extended flag returned, even though it's supposed to have one. I also cross-referenced my keyboard layout via https://kbdlayout.info and it is supposed to be 0xE048
.
How do I receive the extended flag from MapVirtualKeyA()
?
Answering my own question in case anyone else stumbles onto this behaviour:
The return value is technically correct, as MapVirtualKey
defaults to the non-extended version and VK_UP
is shared by both the "arrow up" (0xE048
) key and Numpad 8 (0x48
). Some other keys are also sharing the same Virtual KeyCode, such as VK_RETURN
.
For reference, VK_NUMPAD8
exists and some other layouts may be using it, but not in this case.