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.2 kB

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