Skip to content

Commit

Permalink
重新实现热键钩子
Browse files Browse the repository at this point in the history
  • Loading branch information
JiuLing-zhang committed Jan 22, 2025
1 parent 81f10d3 commit 9a3176a
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 117 deletions.
13 changes: 13 additions & 0 deletions src/ComputerLock/Enums/HotKeyModifiers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace ComputerLock.Enums;

/// <summary>
/// 热键修饰键
/// </summary>
[Flags]
public enum HotKeyModifiers : uint
{
Alt = 1,
Control = 2,
Shift = 4,
Win = 8
}
178 changes: 68 additions & 110 deletions src/ComputerLock/Hooks/HotKeyHook.cs
Original file line number Diff line number Diff line change
@@ -1,148 +1,106 @@
using System.Runtime.InteropServices;

namespace ComputerLock.Hooks
namespace ComputerLock.Hooks;

/// <summary>
/// 快捷键钩子
/// </summary>
public class HotKeyHook : IDisposable
{
//引用:https://stackoverflow.com/questions/2450373/set-global-hotkeys-using-c-sharp
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);

[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

private const int HotkeyId = 90;
private bool _isRegistered;

public sealed class HotKeyHook : IDisposable
public event Action? HotKeyPressed;

private sealed class HotKeyNativeWindow : NativeWindow
{
// Registers a hot key with Windows.
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
// Unregisters the hot key with Windows.
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

/// <summary>
/// Represents the window that is used internally to get the messages.
/// </summary>
private class Window : NativeWindow, IDisposable
{
private static int WM_HOTKEY = 0x0312;
public event Action? OnHotKeyPressed;

public Window()
{
// create the handle for the window.
this.CreateHandle(new CreateParams());
}
public HotKeyNativeWindow()
{
this.CreateHandle(new CreateParams());
}

/// <summary>
/// Overridden to get the notifications.
/// </summary>
/// <param name="m"></param>
protected override void WndProc(ref Message m)
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0312) // WM_HOTKEY
{
base.WndProc(ref m);

// check if we got a hot key pressed.
if (m.Msg == WM_HOTKEY)
if (m.WParam.ToInt32() == HotkeyId)
{
// get the keys.
Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF);
ModifierKeys modifier = (ModifierKeys)((int)m.LParam & 0xFFFF);

// invoke the event to notify the parent.
if (KeyPressed != null)
KeyPressed(this, new KeyPressedEventArgs(modifier, key));
OnHotKeyPressed?.Invoke();
}
}

public event EventHandler<KeyPressedEventArgs> KeyPressed;

#region IDisposable Members

public void Dispose()
else
{
this.DestroyHandle();
base.WndProc(ref m);
}

#endregion
}
}

private Window _window = new Window();
const int _currentId = 1;

public HotKeyHook()
{
// register the event of the inner native window.
_window.KeyPressed += delegate (object sender, KeyPressedEventArgs args)
{
if (KeyPressed != null)
KeyPressed(this, args);
};
}
private readonly HotKeyNativeWindow _nativeWindow;

/// <summary>
/// Registers a hot key in the system.
/// </summary>
/// <param name="modifier">The modifiers that are associated with the hot key.</param>
/// <param name="key">The key itself that is associated with the hot key.</param>
public void RegisterHotKey(ModifierKeys modifier, Keys key)
{
// register the hot key.
if (!RegisterHotKey(_window.Handle, _currentId, (uint)modifier, (uint)key))
throw new InvalidOperationException("Couldn’t register the hot key.");
}
public HotKeyHook()
{
_nativeWindow = new HotKeyNativeWindow();
_nativeWindow.OnHotKeyPressed += () => HotKeyPressed?.Invoke();
}

public void UnregisterHotKey()
/// <summary>
/// 注册快捷键
/// </summary>
public void Register(HotKey hotKey)
{
if (_isRegistered)
{
// register the hot key.
if (!UnregisterHotKey(_window.Handle, _currentId))
throw new InvalidOperationException("Couldn’t cancel register the hot key.");
Unregister();
}

/// <summary>
/// A hot key has been pressed.
/// </summary>
public event EventHandler<KeyPressedEventArgs> KeyPressed;

#region IDisposable Members

public void Dispose()
var success = RegisterHotKey(_nativeWindow.Handle, HotkeyId, (uint)hotKey.Modifiers, (uint)hotKey.Key);
if (!success)
{
UnregisterHotKey(_window.Handle, _currentId);

// dispose the inner native window.
_window.Dispose();
throw new Exception("注册快捷键失败");
}

#endregion
_isRegistered = success;
}

/// <summary>
/// Event Args for the event that is fired after the hot key has been pressed.
/// 注销快捷键
/// </summary>
public class KeyPressedEventArgs : EventArgs
public void Unregister()
{
private ModifierKeys _modifier;
private Keys _key;

internal KeyPressedEventArgs(ModifierKeys modifier, Keys key)
if (!_isRegistered)
{
_modifier = modifier;
_key = key;
return;
}
UnregisterHotKey(_nativeWindow.Handle, HotkeyId);
_isRegistered = false;
}

public ModifierKeys Modifier
{
get { return _modifier; }
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

public Keys Key
protected virtual void Dispose(bool disposing)
{
if (!disposing)
{
get { return _key; }
return;
}

Unregister();
_nativeWindow.DestroyHandle();
}

/// <summary>
/// The enumeration of possible modifiers.
/// </summary>
[Flags]
public enum ModifierKeys : uint
~HotKeyHook()
{
Alt = 1,
Control = 2,
Shift = 4,
Win = 8
Dispose(false);
}
}
7 changes: 7 additions & 0 deletions src/ComputerLock/Models/HotKey.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ComputerLock.Models;

public class HotKey(HotKeyModifiers modifiers, Keys key)
{
public HotKeyModifiers Modifiers { get; set; } = modifiers;
public Keys Key { get; set; } = key;
}
14 changes: 7 additions & 7 deletions src/ComputerLock/Pages/Index.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ protected override async Task OnInitializedAsync()
RegisterHotKey();
}

HotKeyHook.KeyPressed += (_, _) =>
HotKeyHook.HotKeyPressed += () =>
{
Logger.Write("快捷键解锁");
Locker.Lock();
Expand Down Expand Up @@ -184,18 +184,18 @@ public void RegisterHotKey()
{
try
{
ModifierKeys keys = 0;
HotKeyModifiers modifiers = 0;
if (AppSettings.ShortcutKeyForLock.IndexOf("Ctrl") >= 0)
{
keys |= ModifierKeys.Control;
modifiers |= HotKeyModifiers.Control;
}
if (AppSettings.ShortcutKeyForLock.IndexOf("Shift") >= 0)
{
keys |= ModifierKeys.Shift;
modifiers |= HotKeyModifiers.Shift;
}
if (AppSettings.ShortcutKeyForLock.IndexOf("Alt") >= 0)
{
keys |= ModifierKeys.Alt;
modifiers |= HotKeyModifiers.Alt;
}

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

_shortcutKeyText = AppSettings.ShortcutKeyDisplayForLock;
}
Expand All @@ -221,7 +221,7 @@ public void UnregisterHotKey()
try
{
Logger.Write("释放锁屏热键");
HotKeyHook.UnregisterHotKey();
HotKeyHook.Unregister();
}
catch (Exception ex)
{
Expand Down

0 comments on commit 9a3176a

Please sign in to comment.