Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The trick is to use a set of user32.dll functions: <a href="http://msdn.microsoft.com/en-us/library/ms633522(VS.85).aspx" rel="noreferrer">GetWindowThreadProcessId</a>, <a href="http://msdn.microsoft.com/en-us/library/ms646296.aspx" rel="noreferrer">GetKeyboardLayout</a>, <a href="http://msdn.microsoft.com/en-us/library/ms646299(VS.85).aspx" rel="noreferrer">GetKeyboardState</a> and <a href="http://msdn.microsoft.com/en-us/library/ms646322(VS.85).aspx" rel="noreferrer">ToUnicodeEx</a>.</p> <ol> <li>Use the <a href="http://msdn.microsoft.com/en-us/library/ms633522(VS.85).aspx" rel="noreferrer">GetWindowThreadProcessId</a> function with your control handle to achieve the relevant native thread id.</li> <li>Pass that thread id to <a href="http://msdn.microsoft.com/en-us/library/ms646296.aspx" rel="noreferrer">GetKeyboardLayout</a> to get the current keyboard layout.</li> <li>Call <a href="http://msdn.microsoft.com/en-us/library/ms646299(VS.85).aspx" rel="noreferrer">GetKeyboardState</a> to get the current keyboard state. This helps the next method to decide which character to generate according to modifiers state.</li> <li>Finally, call the <a href="http://msdn.microsoft.com/en-us/library/ms646322(VS.85).aspx" rel="noreferrer">ToUnicodeEx</a> 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.</li> </ol> <p>If the result is not zero, just return the first returned character.</p> <pre><code> 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(); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload