You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Hotkeys.cs 6.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using System.Windows.Forms;
  6. using System.Windows.Input;
  7. using GlobalHotKey;
  8. namespace Shadowsocks.Util
  9. {
  10. public static class HotKeys
  11. {
  12. private static HotKeyManager _hotKeyManager;
  13. public delegate void HotKeyCallBackHandler();
  14. // map key and corresponding handler function
  15. private static Dictionary<HotKey, HotKeyCallBackHandler> _keymap = new Dictionary<HotKey, HotKeyCallBackHandler>();
  16. public static void Init()
  17. {
  18. _hotKeyManager = new HotKeyManager();
  19. _hotKeyManager.KeyPressed += HotKeyManagerPressed;
  20. }
  21. public static void Destroy()
  22. {
  23. _hotKeyManager.KeyPressed -= HotKeyManagerPressed;
  24. _hotKeyManager.Dispose();
  25. }
  26. private static void HotKeyManagerPressed(object sender, KeyPressedEventArgs e)
  27. {
  28. var hotkey = e.HotKey;
  29. HotKeyCallBackHandler callback;
  30. if (_keymap.TryGetValue(hotkey, out callback))
  31. callback();
  32. }
  33. public static bool IsHotkeyExists( HotKey hotKey )
  34. {
  35. if (hotKey == null) throw new ArgumentNullException(nameof(hotKey));
  36. return _keymap.Any( v => v.Key.Equals( hotKey ) );
  37. }
  38. public static bool IsCallbackExists( HotKeyCallBackHandler cb, out HotKey hotkey)
  39. {
  40. if (cb == null) throw new ArgumentNullException(nameof(cb));
  41. try
  42. {
  43. var key = _keymap.First(x => x.Value == cb).Key;
  44. hotkey = key;
  45. return true;
  46. }
  47. catch (InvalidOperationException)
  48. {
  49. // not found
  50. hotkey = null;
  51. return false;
  52. }
  53. }
  54. public static string HotKey2Str( HotKey key )
  55. {
  56. if (key == null) throw new ArgumentNullException(nameof(key));
  57. return HotKey2Str( key.Key, key.Modifiers );
  58. }
  59. public static string HotKey2Str( Key key, ModifierKeys modifier )
  60. {
  61. if (!Enum.IsDefined(typeof(Key), key))
  62. throw new InvalidEnumArgumentException(nameof(key), (int) key, typeof(Key));
  63. try
  64. {
  65. ModifierKeysConverter mkc = new ModifierKeysConverter();
  66. var keyStr = Enum.GetName(typeof(Key), key);
  67. var modifierStr = mkc.ConvertToInvariantString(modifier);
  68. return $"{modifierStr}+{keyStr}";
  69. }
  70. catch (NotSupportedException)
  71. {
  72. // converter exception
  73. return null;
  74. }
  75. }
  76. public static HotKey Str2HotKey(string s)
  77. {
  78. try
  79. {
  80. if (s.IsNullOrEmpty()) return null;
  81. int offset = s.LastIndexOf("+", StringComparison.OrdinalIgnoreCase);
  82. if (offset <= 0) return null;
  83. string modifierStr = s.Substring(0, offset).Trim();
  84. string keyStr = s.Substring(offset + 1).Trim();
  85. KeyConverter kc = new KeyConverter();
  86. ModifierKeysConverter mkc = new ModifierKeysConverter();
  87. Key key = (Key) kc.ConvertFrom(keyStr.ToUpper());
  88. ModifierKeys modifier = (ModifierKeys) mkc.ConvertFrom(modifierStr.ToUpper());
  89. return new HotKey(key, modifier);
  90. }
  91. catch (NotSupportedException)
  92. {
  93. // converter exception
  94. return null;
  95. }
  96. catch (NullReferenceException)
  97. {
  98. return null;
  99. }
  100. }
  101. public static bool Regist( HotKey key, HotKeyCallBackHandler callBack )
  102. {
  103. if (key == null)
  104. throw new ArgumentNullException(nameof(key));
  105. if (callBack == null)
  106. throw new ArgumentNullException(nameof(callBack));
  107. try
  108. {
  109. _hotKeyManager.Register(key);
  110. _keymap[key] = callBack;
  111. return true;
  112. }
  113. catch (ArgumentException)
  114. {
  115. // already called this method with the specific hotkey
  116. // return success silently
  117. return true;
  118. }
  119. catch (Win32Exception)
  120. {
  121. // this hotkey already registered by other programs
  122. // notify user to change key
  123. return false;
  124. }
  125. }
  126. public static bool Regist(Key key, ModifierKeys modifiers, HotKeyCallBackHandler callBack)
  127. {
  128. if (!Enum.IsDefined(typeof(Key), key))
  129. throw new InvalidEnumArgumentException(nameof(key), (int) key, typeof(Key));
  130. try
  131. {
  132. var hotkey = _hotKeyManager.Register(key, modifiers);
  133. _keymap[hotkey] = callBack;
  134. return true;
  135. }
  136. catch (ArgumentException)
  137. {
  138. // already called this method with the specific hotkey
  139. // return success silently
  140. return true;
  141. }
  142. catch (Win32Exception)
  143. {
  144. // already registered by other programs
  145. // notify user to change key
  146. return false;
  147. }
  148. }
  149. public static void UnRegist(HotKey key)
  150. {
  151. if (key == null)
  152. throw new ArgumentNullException(nameof(key));
  153. _hotKeyManager.Unregister(key);
  154. if(_keymap.ContainsKey(key))
  155. _keymap.Remove(key);
  156. }
  157. public static IEnumerable<TControl> GetChildControls<TControl>(this Control control) where TControl : Control
  158. {
  159. var children = control.Controls.Count > 0 ? control.Controls.OfType<TControl>() : Enumerable.Empty<TControl>();
  160. return children.SelectMany(c => GetChildControls<TControl>(c)).Concat(children);
  161. }
  162. }
  163. }