I’m using the Windows API SendInput() call to simulate keyboard events. The following snippet (irrelevant details omitted) works perfectly for sending a sequence of characters:
wchar_t txt = ...; INPUT *input = ...; size_t nInput = 0; for (unsigned int j = 0; j < length; j++) { input[nInput].ki.wVk = 0; input[nInput].ki.wScan = txt[j]; input[nInput].ki.dwFlags = KEYEVENTF_UNICODE; nInput++; input[nInput].ki.wVk = 0; input[nInput].ki.wScan = txt[j]; input[nInput].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP; nInput++; } SendInput(nInput, input, sizeoF(INPUT));
Now I’m trying to send single keypresses, with modifiers. I tried the following code:
bool control, alt shift; wchar_t chr; if (control) { input[nInput].ki.wVk = VK_CONTROL; input[nInput].ki.dwFlags = 0; nInput++; } if (alt) { input[nInput].ki.wVk = VK_MENU; input[nInput].ki.dwFlags = 0; nInput++; } if (shift) { input[nInput].ki.wVk = VK_SHIFT; input[nInput].ki.dwFlags = 0; nInput++; } input[nInput].ki.wVk = 0; input[nInput].ki.wScan = chr; input[nInput].ki.dwFlags = KEYEVENTF_UNICODE; nInput++; input[nInput].ki.wVk = 0; input[nInput].ki.wScan = chr; input[nInput].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP; nInput++; if (shift) { input[nInput].ki.wVk = VK_SHIFT; input[nInput].ki.dwFlags = KEYEVENTF_KEYUP; nInput++; } if (alt) { input[nInput].ki.wVk = VK_MENU; input[nInput].ki.dwFlags = KEYEVENTF_KEYUP; nInput++; } if (control) { input[nInput].ki.wVk = VK_CONTROL; input[nInput].ki.dwFlags = KEYEVENTF_KEYUP; nInput++; } SendInput(nInput, input, sizeof(INPUT));
However, modifiers don’t seem to get through, i.e., even though, say control is set to true, the event sequence is received as a plain keypress.
Pax’s answer did not work out, but it lead me to the correct solution. In short: do not use
KEYEVENTF_UNICODEfor individual keypresses, rather, convert the character to a virtual key code, and send it that way. Here’s the relevant code:I have not tested how this works for non-ASCII unicode characters, that are mapped to non-English keyboard layouts, and what happens when the layout set for my app is different from the layout set for the application in the front.