In a C# Windows.Forms project I have a control that does not supply the KeyPressed event (It’s a COM control – ESRI map).
It only supplies the KeyUp and KeyDown events, containing the KeyEventArgs structure.
How can I convert the information in KeyEventArgs to a displayable Unicode character, taking the current active keyboard layout into account, etc.?
Itai Bar-Haim's solution is nice but has a problem with dead keys.
The first time you call CodeToString(int scanCode) with the scan code of a dead key, the return code of ToUnicodeEx() is -1 and your method returns the right value.
But on the next call, ToUnicodeEx() will return 2. The result string will contain the dead key before the expected result, followed by memory junk data.
For instance, I call your method with ^ (dead key) and then with $. The first call returns ^ (nice), but the second call returns ^$azertyui.
You must do two things to fix that :
1) You must use the ToUnicodeEx() return code absolute value to set the length of your StringBuilder. So you avoid getting junk data after the characters.
2) When ToUnicodeEx() return code is -1, you must take the first char of your StringBuilder as a result for your method. And then you must remove the dead key from the keyboard state : recall ToUnicodeEx() with the scancode of the Space key.
Another problem you could have : if the keyboard state has been modified by a user who hit a dead key before you call ToUnicodeEx(), the returned string will contains the dead key character before the expected value. A workaround I found is to call ToUnicodeEx() with the scancode of the Space key before the actual call.
Hope this help!
Look at KeysConverter and its ConvertToString method. Remember that not all KeyDown map to a KeyPress.
The trick is to use a set of user32.dll functions: GetWindowThreadProcessId, GetKeyboardLayout, GetKeyboardState and ToUnicodeEx.
If the result is not zero, just return the first returned character.