2

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.

2 Answers 2

3

Pax's answer did not work out, but it lead me to the correct solution. In short: do not use KEYEVENTF_UNICODE for individual keypresses, rather, convert the character to a virtual key code, and send it that way. Here's the relevant code:

SHORT virtKey = VkKeyScan((TCHAR) chr); input[nInput].ki.wVk = LOBYTE(virtKey); input[nInput].ki.dwFlags = 0; nInput++; input[nInput].ki.wVk = LOBYTE(virtKey); input[nInput].ki.dwFlags = KEYEVENTF_KEYUP; nInput++; 

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.

Sign up to request clarification or add additional context in comments.

2 Comments

@David, you should probably accept this answer otherwise SO will continue to bother you with "have you thought of accepting an answer to this question".
@Pax: sure, I'll do that, but first I wanted to give others a chance to improve my answer or to point out my mistakes.
2

The only piece of code I've found which may indicate your problem sets the scan code in the ki structure as well.

Try changing your modifier sections to be:

if (control) { input[nInput].ki.wVk = VK_CONTROL; input[nInput].ki.dwFlags = 0; input[nInput].ki.wScan = MapVirtualKey(VK_CONTROL, 0); nInput++; } if (alt) { input[nInput].ki.wVk = VK_MENU; input[nInput].ki.dwFlags = 0; input[nInput].ki.wScan = MapVirtualKey(VK_MENU, 0); nInput++; } if (shift) { input[nInput].ki.wVk = VK_SHIFT; input[nInput].ki.dwFlags = 0; input[nInput].ki.wScan = MapVirtualKey(VK_SHIFT, 0); nInput++; } 

and see if that helps.

If that still doesn't work, try setting the dwFlags to KEYEVENTF_SCANCODE instead of 0 (only for the modifier keys).

Also do it for the key-up events as well and I'm assuming that you're setting input[nInput].type to INPUT_KEYBOARD, yes? Your code doesn't indicate this.

For reference, it was found on this page.

4 Comments

"you're setting input[nInput].type to INPUT_KEYBOARD" - yes, of course.
Not "of course", I never assume anything that's not plainly stated (and sometimes I even doubt those :-). Anyhow, did you try the scan codes?
Fair enough :-) Anyway, the scan codes did not help, but the page you referenced lead me to the solution. I'll post it as an answer. +1, and thanks!
No probs, glad I could help, if only a little. I'm off to bed, it's late here in Oz.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.