PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/MajosaUtilities/KeyboardManager.cs

https://bitbucket.org/majosa/transparent-chat
C# | 145 lines | 136 code | 6 blank | 3 comment | 27 complexity | 8b6048647dfd541a70e59ae4e5e1338c MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Runtime.InteropServices;
  7. using System.Windows;
  8. using System.Windows.Input;
  9. using System.Windows.Interop;
  10. using Majosa;
  11. namespace Majosa.Keyboard
  12. {
  13. public enum KeyboardMessageType
  14. {
  15. WM_KEYDOWN = 0x100,
  16. WM_KEYUP
  17. }
  18. public class GlobalKeyEventArgs : KeyboardEventArgs
  19. {
  20. private Key key;
  21. private bool isUp;
  22. private bool isHandled = false;
  23. private List<Key> pressedKeys = new List<Key>();
  24. private string printableKey;
  25. public GlobalKeyEventArgs(Key key, int timestamp,bool isUp,List<Key> keys,String printable) : base(System.Windows.Input.Keyboard.PrimaryDevice,timestamp)
  26. {
  27. this.key = key;
  28. this.isUp = isUp;
  29. this.pressedKeys=new List<Key>(keys);
  30. this.printableKey=printable;
  31. }
  32. public Key Key { get { return key; } }
  33. public bool IsUp { get { return isUp; } }
  34. public bool IsHandled { get { return isHandled; } set { isHandled = value; } }
  35. public List<Key> PressedKeys { get { return new List<Key>(pressedKeys); } }
  36. public string PrintableKey { get { return printableKey; } }
  37. }
  38. public class KeyboardManager
  39. {
  40. private IntPtr idHook;
  41. public delegate void GlobalKeyEventHandler(object sender,GlobalKeyEventArgs ev);
  42. public event GlobalKeyEventHandler KeyPressed;
  43. public event GlobalKeyEventHandler KeyUp;
  44. private static KeyboardManager instance;
  45. private HookManager hookM;
  46. private List<Key> pressedKeys;
  47. private KeyboardManager()
  48. {
  49. hookM = HookManager.Instance();
  50. idHook=hookM.AddHook(HookManager.HookType.WH_KEYBOARD_LL, HookKeyboardHandle);
  51. pressedKeys = new List<Key>();
  52. }
  53. public static KeyboardManager Instance()
  54. {
  55. if (instance == null)
  56. {
  57. instance = new KeyboardManager();
  58. }
  59. return instance;
  60. }
  61. private IntPtr HookKeyboardHandle(int nCode, IntPtr wParam, IntPtr lParam)
  62. {
  63. if (nCode > 0)
  64. {
  65. //Pass call
  66. return CallNextHookEx(idHook, nCode, wParam, lParam);
  67. }
  68. //Parse lParam
  69. uint vkCode = (uint)Marshal.ReadInt32(lParam, 0);
  70. uint scanCode = (uint)Marshal.ReadInt32(lParam, 32 + 1);
  71. uint flags = (uint)Marshal.ReadInt32(lParam, 32 * 2);
  72. uint time = (uint)Marshal.ReadInt32(lParam, 32 * 3);
  73. IntPtr extraPtr = Marshal.ReadIntPtr(lParam, 32 * 4);
  74. bool isExtended = (flags & 0x1) != 0;
  75. bool isInjected = (flags & 0x10) != 0;
  76. bool isContextCode = (flags & 0x20) != 0;
  77. bool isPressedBefore = (flags & 0x80) != 0;
  78. //Parse wParam
  79. GlobalKeyEventArgs evArgs;
  80. Key key=KeyInterop.KeyFromVirtualKey((int)vkCode);
  81. String printable = getPrintableCharFromKey(vkCode, scanCode);
  82. switch ((KeyboardMessageType)wParam)
  83. {
  84. case KeyboardMessageType.WM_KEYDOWN:
  85. if (!pressedKeys.Contains(key)) pressedKeys.Add(key);
  86. evArgs = new GlobalKeyEventArgs(KeyInterop.KeyFromVirtualKey((int)vkCode), (int)time, false, pressedKeys, printable);
  87. if (KeyPressed != null) KeyPressed(null, evArgs);
  88. break;
  89. case KeyboardMessageType.WM_KEYUP:
  90. if (pressedKeys.Contains(key)) pressedKeys.Remove(key);
  91. evArgs = new GlobalKeyEventArgs(KeyInterop.KeyFromVirtualKey((int)vkCode), (int)time, true, pressedKeys, printable);
  92. if (KeyUp != null) KeyUp(null, evArgs);
  93. break;
  94. default:
  95. evArgs = new GlobalKeyEventArgs(KeyInterop.KeyFromVirtualKey((int)vkCode), (int)time, false, pressedKeys,"");
  96. break;
  97. }
  98. if (evArgs.IsHandled)
  99. {
  100. return (IntPtr)0;
  101. }
  102. else
  103. {
  104. return CallNextHookEx(idHook, nCode, wParam, lParam);
  105. }
  106. }
  107. private string getPrintableCharFromKey(uint virtualKeyCode, uint scanCode)
  108. {
  109. var buffer = new StringBuilder(256);
  110. var keyboardState = new byte[256];
  111. foreach (var key in pressedKeys)
  112. {
  113. keyboardState[KeyInterop.VirtualKeyFromKey(key)] = 0xFF;
  114. if (key == Key.LeftShift || key == Key.RightShift)
  115. {
  116. keyboardState[0x10] = 0xFF;
  117. }
  118. if (key == Key.LeftCtrl || key == Key.RightCtrl)
  119. {
  120. keyboardState[0x11] = 0xFF;
  121. }
  122. if (key == Key.LeftAlt || key == Key.RightAlt)
  123. {
  124. keyboardState[0x12] = 0xFF;
  125. }
  126. }
  127. ToUnicode(virtualKeyCode, scanCode, keyboardState, buffer, 256, 0);
  128. return buffer.ToString();
  129. }
  130. ~KeyboardManager()
  131. {
  132. HookManager.Instance().RemoveHook(idHook);
  133. }
  134. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  135. private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
  136. [DllImport("user32.dll")]
  137. public static extern int ToUnicode(uint virtualKeyCode, uint scanCode, byte[] keyboardState, [Out, MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)]StringBuilder receivingBuffer, int bufferSize, uint flags);
  138. }
  139. }