InputKeyHelpers.cs 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. using System.Globalization;
  2. using System.Runtime.InteropServices;
  3. using System.Text;
  4. using System.Windows.Input;
  5. namespace PixiEditor.Helpers
  6. {
  7. public static class InputKeyHelpers
  8. {
  9. /// <summary>
  10. /// Returns the charcter of the <paramref name="key"/> mapped to the users keyboard layout
  11. /// </summary>
  12. public static string GetKeyboardKey(Key key) => GetKeyboardKey(key, CultureInfo.CurrentCulture);
  13. public static string GetKeyboardKey(Key key, CultureInfo culture) => key switch
  14. {
  15. >= Key.NumPad0 and <= Key.Divide => $"Num {GetMappedKey(key, culture)}",
  16. Key.Space => nameof(Key.Space),
  17. Key.Tab => nameof(Key.Tab),
  18. Key.Back => "Backspace",
  19. Key.Escape => "Esc",
  20. _ => GetMappedKey(key, culture),
  21. };
  22. private static string GetMappedKey(Key key, CultureInfo culture)
  23. {
  24. int virtualKey = KeyInterop.VirtualKeyFromKey(key);
  25. byte[] keyboardState = new byte[256];
  26. uint scanCode = MapVirtualKeyExW((uint)virtualKey, MapType.MAPVK_VK_TO_VSC, culture.KeyboardLayoutId);
  27. StringBuilder stringBuilder = new(3);
  28. int result = ToUnicode((uint)virtualKey, scanCode, keyboardState, stringBuilder, stringBuilder.Capacity, 0);
  29. string stringResult;
  30. stringResult = result switch
  31. {
  32. 0 => key.ToString(),
  33. -1 => stringBuilder.ToString().ToUpper(),
  34. _ => stringBuilder[result - 1].ToString().ToUpper()
  35. };
  36. return stringResult;
  37. }
  38. private enum MapType : uint
  39. {
  40. /// <summary>
  41. /// The uCode parameter is a virtual-key code and is translated into a scan code. If it is a virtual-key code that does not distinguish between left- and right-hand keys, the left-hand scan code is returned. If there is no translation, the function returns 0.
  42. /// </summary>
  43. MAPVK_VK_TO_VSC = 0x0,
  44. /// <summary>
  45. /// The uCode parameter is a scan code and is translated into a virtual-key code that does not distinguish between left- and right-hand keys. If there is no translation, the function returns 0.
  46. /// </summary>
  47. MAPVK_VSC_TO_VK = 0x1,
  48. /// <summary>
  49. /// The uCode parameter is a virtual-key code and is translated into an unshifted character value in the low order word of the return value. Dead keys (diacritics) are indicated by setting the top bit of the return value. If there is no translation, the function returns 0.
  50. /// </summary>
  51. MAPVK_VK_TO_CHAR = 0x2,
  52. /// <summary>
  53. /// The uCode parameter is a scan code and is translated into a virtual-key code that distinguishes between left- and right-hand keys. If there is no translation, the function returns 0.
  54. /// </summary>
  55. MAPVK_VSC_TO_VK_EX = 0x3,
  56. }
  57. [DllImport("user32.dll")]
  58. private static extern int ToUnicode(
  59. uint wVirtKey,
  60. uint wScanCode,
  61. byte[] lpKeyState,
  62. [Out, MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 4)]
  63. StringBuilder pwszBuff,
  64. int cchBuff,
  65. uint wFlags);
  66. [DllImport("user32.dll")]
  67. private static extern bool GetKeyboardState(byte[] lpKeyState);
  68. [DllImport("user32.dll")]
  69. private static extern uint MapVirtualKeyExW(uint uCode, MapType uMapType, int hkl);
  70. }
  71. }