Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

convert a keycode to the relevant display character

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.?

like image 892
Asher Avatar asked Dec 16 '08 08:12

Asher


People also ask

How do I find the KeyCode of a character?

charCodeAt() method returns returns keycode for an character.

What does charCode mean?

Definition and Usage The charCode property returns the Unicode character code of the key that triggered the onkeypress event. The Unicode character code is the number of a character (e.g. the number "97" represents the letter "a").


1 Answers

The trick is to use a set of user32.dll functions: GetWindowThreadProcessId, GetKeyboardLayout, GetKeyboardState and ToUnicodeEx.

  1. Use the GetWindowThreadProcessId function with your control handle to achieve the relevant native thread id.
  2. Pass that thread id to GetKeyboardLayout to get the current keyboard layout.
  3. Call GetKeyboardState to get the current keyboard state. This helps the next method to decide which character to generate according to modifiers state.
  4. Finally, call the ToUnicodeEx function with the wanted virtual key code and scan code (those two can be the same), the current keyboard state, a string builder as a string holder (to hold the result), no flags (0), and the current keyboard layout pointer.

If the result is not zero, just return the first returned character.

  public class KeyboardHelper
    {
        [DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern int ToUnicodeEx(
            uint wVirtKey,
            uint wScanCode,
            Keys[] lpKeyState,
            StringBuilder pwszBuff,
            int cchBuff,
            uint wFlags,
            IntPtr dwhkl);

        [DllImport("user32.dll", ExactSpelling = true)]
        internal static extern IntPtr GetKeyboardLayout(uint threadId);

        [DllImport("user32.dll", ExactSpelling = true)]
        internal static extern bool GetKeyboardState(Keys[] keyStates);

        [DllImport("user32.dll", ExactSpelling = true)]
        internal static extern uint GetWindowThreadProcessId(IntPtr hwindow, out uint processId);

        public static string CodeToString(int scanCode)
        {
            uint procId;
            uint thread = GetWindowThreadProcessId(Process.GetCurrentProcess().MainWindowHandle, out procId);
            IntPtr hkl = GetKeyboardLayout(thread);

            if (hkl == IntPtr.Zero)
            {
                Console.WriteLine("Sorry, that keyboard does not seem to be valid.");
                return string.Empty;
            }

            Keys[] keyStates = new Keys[256];
            if (!GetKeyboardState(keyStates))
                return string.Empty;

            StringBuilder sb = new StringBuilder(10);
            int rc = ToUnicodeEx((uint)scanCode, (uint)scanCode, keyStates, sb, sb.Capacity, 0, hkl);
            return sb.ToString();
        }
    }
like image 69
Itai Bar-Haim Avatar answered Nov 01 '22 12:11

Itai Bar-Haim