/// <summary> /// Converts Key to Char (considering keyboard layout defined in the given culture) /// </summary> /// <param name="key">Key</param> /// <param name="cultureInfo">Culture</param> /// <returns>Char</returns> public static char?KeyToChar(Key key, CultureInfo cultureInfo) { // Get layouts existed in the system if (existingLayouts == null) { int keyboardsCount = NativeMethods.GetKeyboardLayoutList(0, null); existingLayouts = new IntPtr[keyboardsCount]; NativeMethods.GetKeyboardLayoutList(keyboardsCount, existingLayouts); } int virtualKey = KeyInterop.VirtualKeyFromKey(key); // Try to find keyboard layout in cache IntPtr keyboardlayout; if (!keyboardLayoutHandlers.TryGetValue(cultureInfo.LCID, out keyboardlayout)) { keyboardlayout = NativeMethods.LoadKeyboardLayout(cultureInfo.LCID.ToString("x8", CultureInfo.InvariantCulture), 0x00000080); keyboardLayoutHandlers.Add(cultureInfo.LCID, keyboardlayout); } // Get keyboard status bool bKeyStateStatus = NativeMethods.GetKeyboardState(keyboardState); if (!bKeyStateStatus) { return(null); } uint scanCode = NativeMethods.MapVirtualKeyEx((uint)virtualKey, 2, keyboardlayout); StringBuilder result = new StringBuilder(10); int count = NativeMethods.ToUnicodeEx((uint)virtualKey, scanCode, keyboardState, result, 10, 0, keyboardlayout); if (!existingLayouts.Contains(keyboardlayout)) { // We must unload the layout to be sure // that previously non-existed layout remains in the system NativeMethods.UnloadKeyboardLayout(keyboardlayout); keyboardLayoutHandlers.Remove(cultureInfo.LCID); } return((result.Length >= 1 && count >= 1) ? new char?(result[0]) : null); }