Skip to content

Commit 9a3176a

Browse files
committed
重新实现热键钩子
1 parent 81f10d3 commit 9a3176a

File tree

4 files changed

+95
-117
lines changed

4 files changed

+95
-117
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace ComputerLock.Enums;
2+
3+
/// <summary>
4+
/// 热键修饰键
5+
/// </summary>
6+
[Flags]
7+
public enum HotKeyModifiers : uint
8+
{
9+
Alt = 1,
10+
Control = 2,
11+
Shift = 4,
12+
Win = 8
13+
}

src/ComputerLock/Hooks/HotKeyHook.cs

Lines changed: 68 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,106 @@
11
using System.Runtime.InteropServices;
22

3-
namespace ComputerLock.Hooks
3+
namespace ComputerLock.Hooks;
4+
5+
/// <summary>
6+
/// 快捷键钩子
7+
/// </summary>
8+
public class HotKeyHook : IDisposable
49
{
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;
618

7-
public sealed class HotKeyHook : IDisposable
19+
public event Action? HotKeyPressed;
20+
21+
private sealed class HotKeyNativeWindow : NativeWindow
822
{
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;
2224

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+
}
2829

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
3433
{
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)
3935
{
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();
4737
}
4838
}
49-
50-
public event EventHandler<KeyPressedEventArgs> KeyPressed;
51-
52-
#region IDisposable Members
53-
54-
public void Dispose()
39+
else
5540
{
56-
this.DestroyHandle();
41+
base.WndProc(ref m);
5742
}
58-
59-
#endregion
6043
}
44+
}
6145

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;
7447

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+
}
8653

87-
public void UnregisterHotKey()
54+
/// <summary>
55+
/// 注册快捷键
56+
/// </summary>
57+
public void Register(HotKey hotKey)
58+
{
59+
if (_isRegistered)
8860
{
89-
// register the hot key.
90-
if (!UnregisterHotKey(_window.Handle, _currentId))
91-
throw new InvalidOperationException("Couldn’t cancel register the hot key.");
61+
Unregister();
9262
}
9363

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)
10266
{
103-
UnregisterHotKey(_window.Handle, _currentId);
104-
105-
// dispose the inner native window.
106-
_window.Dispose();
67+
throw new Exception("注册快捷键失败");
10768
}
108-
109-
#endregion
69+
_isRegistered = success;
11070
}
11171

11272
/// <summary>
113-
/// Event Args for the event that is fired after the hot key has been pressed.
73+
/// 注销快捷键
11474
/// </summary>
115-
public class KeyPressedEventArgs : EventArgs
75+
public void Unregister()
11676
{
117-
private ModifierKeys _modifier;
118-
private Keys _key;
119-
120-
internal KeyPressedEventArgs(ModifierKeys modifier, Keys key)
77+
if (!_isRegistered)
12178
{
122-
_modifier = modifier;
123-
_key = key;
79+
return;
12480
}
81+
UnregisterHotKey(_nativeWindow.Handle, HotkeyId);
82+
_isRegistered = false;
83+
}
12584

126-
public ModifierKeys Modifier
127-
{
128-
get { return _modifier; }
129-
}
85+
public void Dispose()
86+
{
87+
Dispose(true);
88+
GC.SuppressFinalize(this);
89+
}
13090

131-
public Keys Key
91+
protected virtual void Dispose(bool disposing)
92+
{
93+
if (!disposing)
13294
{
133-
get { return _key; }
95+
return;
13496
}
97+
98+
Unregister();
99+
_nativeWindow.DestroyHandle();
135100
}
136101

137-
/// <summary>
138-
/// The enumeration of possible modifiers.
139-
/// </summary>
140-
[Flags]
141-
public enum ModifierKeys : uint
102+
~HotKeyHook()
142103
{
143-
Alt = 1,
144-
Control = 2,
145-
Shift = 4,
146-
Win = 8
104+
Dispose(false);
147105
}
148106
}

src/ComputerLock/Models/HotKey.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace ComputerLock.Models;
2+
3+
public class HotKey(HotKeyModifiers modifiers, Keys key)
4+
{
5+
public HotKeyModifiers Modifiers { get; set; } = modifiers;
6+
public Keys Key { get; set; } = key;
7+
}

src/ComputerLock/Pages/Index.razor.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ protected override async Task OnInitializedAsync()
4747
RegisterHotKey();
4848
}
4949

50-
HotKeyHook.KeyPressed += (_, _) =>
50+
HotKeyHook.HotKeyPressed += () =>
5151
{
5252
Logger.Write("快捷键解锁");
5353
Locker.Lock();
@@ -184,18 +184,18 @@ public void RegisterHotKey()
184184
{
185185
try
186186
{
187-
ModifierKeys keys = 0;
187+
HotKeyModifiers modifiers = 0;
188188
if (AppSettings.ShortcutKeyForLock.IndexOf("Ctrl") >= 0)
189189
{
190-
keys |= ModifierKeys.Control;
190+
modifiers |= HotKeyModifiers.Control;
191191
}
192192
if (AppSettings.ShortcutKeyForLock.IndexOf("Shift") >= 0)
193193
{
194-
keys |= ModifierKeys.Shift;
194+
modifiers |= HotKeyModifiers.Shift;
195195
}
196196
if (AppSettings.ShortcutKeyForLock.IndexOf("Alt") >= 0)
197197
{
198-
keys |= ModifierKeys.Alt;
198+
modifiers |= HotKeyModifiers.Alt;
199199
}
200200

201201
var result = RegexUtils.GetFirst(AppSettings.ShortcutKeyForLock, @"\d+");
@@ -205,7 +205,7 @@ public void RegisterHotKey()
205205
}
206206
Logger.Write("注册锁屏热键");
207207
Keys key = (Keys)Convert.ToInt32(result.result);
208-
HotKeyHook.RegisterHotKey(keys, key);
208+
HotKeyHook.Register(new HotKey(modifiers, key));
209209

210210
_shortcutKeyText = AppSettings.ShortcutKeyDisplayForLock;
211211
}
@@ -221,7 +221,7 @@ public void UnregisterHotKey()
221221
try
222222
{
223223
Logger.Write("释放锁屏热键");
224-
HotKeyHook.UnregisterHotKey();
224+
HotKeyHook.Unregister();
225225
}
226226
catch (Exception ex)
227227
{

0 commit comments

Comments
 (0)