Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SendInput() and non-English characters and keyboard layouts

I'm having trouble simulating character keypresses when a non-English input keyboard language is being used in Windows.

I tried calling SendInput() with KEYEVENTF_UNICODE:

KEYBDINPUT ki;
INPUT input;
int character = 0;

ki.wVk = 0;
ki.wScan = character;
ki.dwFlags = KEYEVENTF_UNICODE;
ki.time = 0;
ki.dwExtraInfo = 0;   
input.type = INPUT_KEYBOARD;
input.ki = ki;
SendInput(1, &input, sizeof(INPUT));

And this actually works (of course, in my code, I also do a KEYUP after the key down)... except in GTK+ apps (there may be other instances where it doesn't work either).

According to MSDN, If KEYEVENTF_UNICODE is specified, SendInput sends a WM_KEYDOWN or WM_KEYUP message to the foreground thread's message queue with wParam equal to VK_PACKET. Once GetMessage or PeekMessage obtains this message, passing the message to TranslateMessage posts a WM_CHAR message with the Unicode character originally specified by wScan. This Unicode character will automatically be converted to the appropriate ANSI value if it is posted to an ANSI window.

So I believe that when KEYEVENTF_UNICODE is passed, the functionality of SendInput() is different... not as low-level as it usually is.

For the life of me, I can't figure out any other way to get SendInput() to print out characters properly for the user's keyboard language. For example, if the keyboard input language is "Swedish", I can't get it to output '@' (instead, it prints out a quotation mark), and I can't get it to output non-ASCII characters properly, either (accented letters, etc).

Thanks in advance.

like image 807
00010000 Avatar asked Dec 28 '09 18:12

00010000


2 Answers

I discovered that the proper way to do this is to get the virtual-key code of the character by calling VkKeyScanEx() with the character. The high-order bytes of the return value will tell you which modifier keys you need to "press": Control, Alt, and/or Shift; the low-order bytes are the actual virtual-key code.

To get the scan code of the VK, call MapVirtualKeyEx(vkCode, 0);

Then it's just a matter of doing the keypress simulation with the information just obtained.

like image 167
00010000 Avatar answered Oct 19 '22 07:10

00010000


As I understand it SendInput() is just a wrapper around calls to mouse_event() and keybd_event() that gurantees that your input doesn't get interspersed with input from the user or other callers.

So I guess the question I have is, have you tried using keybd_event()?

like image 32
John Knoeller Avatar answered Oct 19 '22 06:10

John Knoeller