Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SendInput() isn't "sending" the correct shifted characters?

void WriteChar(char c)
{
    INPUT input = {0};
    input.type = INPUT_KEYBOARD;
    input.ki.wVk= VkKeyScanEx(c, GetKeyboardLayout(0) ) ;   
    SendInput(1,&input, sizeof(INPUT));
}

VkKeyScanEx returns different key codes for '/' and '?'(same key), however if you try using this method to write a message containing '?', it will only write '/'. I don't know what's going on. Same thing occurs with ';' and ':'.

I partly don't understand key codes and scan codes. Most characters have a virtual key code, however I can't find something similar for question marks. They must exist, but aren't listed?

like image 893
Alex Gramatikov Avatar asked Jan 30 '10 07:01

Alex Gramatikov


1 Answers

Scan codes are the raw key ids returned from the keyboard. So a 101 key keyboard will (in theory) have 101 unique scan codes that it can return. (see footnote 1)

Virtual key codes are a separate set of codes that represent an key on an idealized keyboard. No matter where on a real keyboard the TAB key is, and what scancode is used for it, the virtual key code is always VK_TAB. windows.h defines VK_xxx codes for non-printable virtual keys, for the printable ones, the virtual key code is the same as the ASCII value.

But virtual key codes are still key codes. 'A' and 'a' have the same virtual key code, so if you want to send an 'A' then you have to send a VK_SHIFT down, then 'a' down, then 'a' up, then VK_SHIFT up.

VkKeyScanEx() converts a character into a scan key and shift state See the quote below from this page http://msdn.microsoft.com/en-us/library/ms646332(VS.85).aspx

If the function succeeds, the low-order byte of the return value contains the virtual-key code and the high-order byte contains the shift state, which can be a combination of the following flag bits.

So you can't just take the return from VkKeyScanEx(), you need to check to see if it has a shift key flagged. and send the shift key as a separate keystroke

SHORT vk = VkKeyScanEx(c, ...);
if (vk & 0x100) // check upper byte for shift flag
{
   // send a shift key down
}
if (vk & 0x200) // check for ctrl flag
{
   // send a ctrl key down
}
input.ki.wVk = vk & 0xFF;

// send keyup for each of the keydown

You also have to send a keyup for every keydown.

Footnotes:

1 This is in theory only, in practice standard PC keyboards emulate a old IBM keyboard that you can't even get anymore, so some keys can return 2 different scan codes based on another key, while other in other cases two keys can return the same scan code.

like image 74
John Knoeller Avatar answered Oct 26 '22 06:10

John Knoeller