|
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