|
1 | 1 | using System.Runtime.InteropServices;
|
2 | 2 |
|
3 |
| -namespace ComputerLock.Hooks |
| 3 | +namespace ComputerLock.Hooks; |
| 4 | + |
| 5 | +/// <summary> |
| 6 | +/// 快捷键钩子 |
| 7 | +/// </summary> |
| 8 | +public class HotKeyHook : IDisposable |
4 | 9 | {
|
5 |
| - //引用:https://stackoverflow.com/questions/2450373/set-global-hotkeys-using-c-sharp |
| 10 | + [DllImport("user32.dll")] |
| 11 | + private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); |
| 12 | + |
| 13 | + [DllImport("user32.dll")] |
| 14 | + private static extern bool UnregisterHotKey(IntPtr hWnd, int id); |
| 15 | + |
| 16 | + private const int HotkeyId = 90; |
| 17 | + private bool _isRegistered; |
6 | 18 |
|
7 |
| - public sealed class HotKeyHook : IDisposable |
| 19 | + public event Action? HotKeyPressed; |
| 20 | + |
| 21 | + private sealed class HotKeyNativeWindow : NativeWindow |
8 | 22 | {
|
9 |
| - // Registers a hot key with Windows. |
10 |
| - [DllImport("user32.dll")] |
11 |
| - private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); |
12 |
| - // Unregisters the hot key with Windows. |
13 |
| - [DllImport("user32.dll")] |
14 |
| - private static extern bool UnregisterHotKey(IntPtr hWnd, int id); |
15 |
| - |
16 |
| - /// <summary> |
17 |
| - /// Represents the window that is used internally to get the messages. |
18 |
| - /// </summary> |
19 |
| - private class Window : NativeWindow, IDisposable |
20 |
| - { |
21 |
| - private static int WM_HOTKEY = 0x0312; |
| 23 | + public event Action? OnHotKeyPressed; |
22 | 24 |
|
23 |
| - public Window() |
24 |
| - { |
25 |
| - // create the handle for the window. |
26 |
| - this.CreateHandle(new CreateParams()); |
27 |
| - } |
| 25 | + public HotKeyNativeWindow() |
| 26 | + { |
| 27 | + this.CreateHandle(new CreateParams()); |
| 28 | + } |
28 | 29 |
|
29 |
| - /// <summary> |
30 |
| - /// Overridden to get the notifications. |
31 |
| - /// </summary> |
32 |
| - /// <param name="m"></param> |
33 |
| - protected override void WndProc(ref Message m) |
| 30 | + protected override void WndProc(ref Message m) |
| 31 | + { |
| 32 | + if (m.Msg == 0x0312) // WM_HOTKEY |
34 | 33 | {
|
35 |
| - base.WndProc(ref m); |
36 |
| - |
37 |
| - // check if we got a hot key pressed. |
38 |
| - if (m.Msg == WM_HOTKEY) |
| 34 | + if (m.WParam.ToInt32() == HotkeyId) |
39 | 35 | {
|
40 |
| - // get the keys. |
41 |
| - Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF); |
42 |
| - ModifierKeys modifier = (ModifierKeys)((int)m.LParam & 0xFFFF); |
43 |
| - |
44 |
| - // invoke the event to notify the parent. |
45 |
| - if (KeyPressed != null) |
46 |
| - KeyPressed(this, new KeyPressedEventArgs(modifier, key)); |
| 36 | + OnHotKeyPressed?.Invoke(); |
47 | 37 | }
|
48 | 38 | }
|
49 |
| - |
50 |
| - public event EventHandler<KeyPressedEventArgs> KeyPressed; |
51 |
| - |
52 |
| - #region IDisposable Members |
53 |
| - |
54 |
| - public void Dispose() |
| 39 | + else |
55 | 40 | {
|
56 |
| - this.DestroyHandle(); |
| 41 | + base.WndProc(ref m); |
57 | 42 | }
|
58 |
| - |
59 |
| - #endregion |
60 | 43 | }
|
| 44 | + } |
61 | 45 |
|
62 |
| - private Window _window = new Window(); |
63 |
| - const int _currentId = 1; |
64 |
| - |
65 |
| - public HotKeyHook() |
66 |
| - { |
67 |
| - // register the event of the inner native window. |
68 |
| - _window.KeyPressed += delegate (object sender, KeyPressedEventArgs args) |
69 |
| - { |
70 |
| - if (KeyPressed != null) |
71 |
| - KeyPressed(this, args); |
72 |
| - }; |
73 |
| - } |
| 46 | + private readonly HotKeyNativeWindow _nativeWindow; |
74 | 47 |
|
75 |
| - /// <summary> |
76 |
| - /// Registers a hot key in the system. |
77 |
| - /// </summary> |
78 |
| - /// <param name="modifier">The modifiers that are associated with the hot key.</param> |
79 |
| - /// <param name="key">The key itself that is associated with the hot key.</param> |
80 |
| - public void RegisterHotKey(ModifierKeys modifier, Keys key) |
81 |
| - { |
82 |
| - // register the hot key. |
83 |
| - if (!RegisterHotKey(_window.Handle, _currentId, (uint)modifier, (uint)key)) |
84 |
| - throw new InvalidOperationException("Couldn’t register the hot key."); |
85 |
| - } |
| 48 | + public HotKeyHook() |
| 49 | + { |
| 50 | + _nativeWindow = new HotKeyNativeWindow(); |
| 51 | + _nativeWindow.OnHotKeyPressed += () => HotKeyPressed?.Invoke(); |
| 52 | + } |
86 | 53 |
|
87 |
| - public void UnregisterHotKey() |
| 54 | + /// <summary> |
| 55 | + /// 注册快捷键 |
| 56 | + /// </summary> |
| 57 | + public void Register(HotKey hotKey) |
| 58 | + { |
| 59 | + if (_isRegistered) |
88 | 60 | {
|
89 |
| - // register the hot key. |
90 |
| - if (!UnregisterHotKey(_window.Handle, _currentId)) |
91 |
| - throw new InvalidOperationException("Couldn’t cancel register the hot key."); |
| 61 | + Unregister(); |
92 | 62 | }
|
93 | 63 |
|
94 |
| - /// <summary> |
95 |
| - /// A hot key has been pressed. |
96 |
| - /// </summary> |
97 |
| - public event EventHandler<KeyPressedEventArgs> KeyPressed; |
98 |
| - |
99 |
| - #region IDisposable Members |
100 |
| - |
101 |
| - public void Dispose() |
| 64 | + var success = RegisterHotKey(_nativeWindow.Handle, HotkeyId, (uint)hotKey.Modifiers, (uint)hotKey.Key); |
| 65 | + if (!success) |
102 | 66 | {
|
103 |
| - UnregisterHotKey(_window.Handle, _currentId); |
104 |
| - |
105 |
| - // dispose the inner native window. |
106 |
| - _window.Dispose(); |
| 67 | + throw new Exception("注册快捷键失败"); |
107 | 68 | }
|
108 |
| - |
109 |
| - #endregion |
| 69 | + _isRegistered = success; |
110 | 70 | }
|
111 | 71 |
|
112 | 72 | /// <summary>
|
113 |
| - /// Event Args for the event that is fired after the hot key has been pressed. |
| 73 | + /// 注销快捷键 |
114 | 74 | /// </summary>
|
115 |
| - public class KeyPressedEventArgs : EventArgs |
| 75 | + public void Unregister() |
116 | 76 | {
|
117 |
| - private ModifierKeys _modifier; |
118 |
| - private Keys _key; |
119 |
| - |
120 |
| - internal KeyPressedEventArgs(ModifierKeys modifier, Keys key) |
| 77 | + if (!_isRegistered) |
121 | 78 | {
|
122 |
| - _modifier = modifier; |
123 |
| - _key = key; |
| 79 | + return; |
124 | 80 | }
|
| 81 | + UnregisterHotKey(_nativeWindow.Handle, HotkeyId); |
| 82 | + _isRegistered = false; |
| 83 | + } |
125 | 84 |
|
126 |
| - public ModifierKeys Modifier |
127 |
| - { |
128 |
| - get { return _modifier; } |
129 |
| - } |
| 85 | + public void Dispose() |
| 86 | + { |
| 87 | + Dispose(true); |
| 88 | + GC.SuppressFinalize(this); |
| 89 | + } |
130 | 90 |
|
131 |
| - public Keys Key |
| 91 | + protected virtual void Dispose(bool disposing) |
| 92 | + { |
| 93 | + if (!disposing) |
132 | 94 | {
|
133 |
| - get { return _key; } |
| 95 | + return; |
134 | 96 | }
|
| 97 | + |
| 98 | + Unregister(); |
| 99 | + _nativeWindow.DestroyHandle(); |
135 | 100 | }
|
136 | 101 |
|
137 |
| - /// <summary> |
138 |
| - /// The enumeration of possible modifiers. |
139 |
| - /// </summary> |
140 |
| - [Flags] |
141 |
| - public enum ModifierKeys : uint |
| 102 | + ~HotKeyHook() |
142 | 103 | {
|
143 |
| - Alt = 1, |
144 |
| - Control = 2, |
145 |
| - Shift = 4, |
146 |
| - Win = 8 |
| 104 | + Dispose(false); |
147 | 105 | }
|
148 | 106 | }
|
0 commit comments