写在前面
介绍一个验证过的热键注册工具类,使用系统类库user32.dll
中的RegisterHotkey
函数来实现全局热键的注册。
代码实现
[Flags]public enum KeyModifiers{Alt = 1,Control = 2,Shift = 4,Windows = 8,NoRepeat = 0x4000}public static class HotKeyHelper{[DllImport("user32", SetLastError = true)]private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);[DllImport("user32", SetLastError = true)]private static extern bool UnregisterHotKey(IntPtr hWnd, int id);private static int _id = 0;private static volatile MessageWindow _wnd;private static volatile IntPtr _hwnd;private static ManualResetEvent _windowReadyEvent = new ManualResetEvent(false);static HotKeyHelper(){Thread messageLoop = new Thread(delegate (){Application.Run(new MessageWindow());});messageLoop.Name = "MessageLoopThread";messageLoop.IsBackground = true;messageLoop.Start();}public static event EventHandler<HotKeyEventArgs> HotKeyPressed;public static int RegisterHotKey(Keys key, KeyModifiers modifiers){_windowReadyEvent.WaitOne();int id = System.Threading.Interlocked.Increment(ref _id);_wnd.Invoke(new RegisterHotKeyDelegate(RegisterHotKeyInternal), _hwnd, id, (uint)modifiers, (uint)key);return id;}public static void UnregisterHotKey(int id){_wnd.Invoke(new UnRegisterHotKeyDelegate(UnRegisterHotKeyInternal), _hwnd, id);}delegate void RegisterHotKeyDelegate(IntPtr hwnd, int id, uint modifiers, uint key);delegate void UnRegisterHotKeyDelegate(IntPtr hwnd, int id);private static void RegisterHotKeyInternal(IntPtr hwnd, int id, uint modifiers, uint key){RegisterHotKey(hwnd, id, modifiers, key);}private static void UnRegisterHotKeyInternal(IntPtr hwnd, int id){UnregisterHotKey(_hwnd, id);}private static void OnHotKeyPressed(HotKeyEventArgs e){if (HotKeyHelper.HotKeyPressed != null){HotKeyHelper.HotKeyPressed(null, e);}}private class MessageWindow : Form{public MessageWindow(){_wnd = this;_hwnd = this.Handle;_windowReadyEvent.Set();}protected override void WndProc(ref Message m){if (m.Msg == WM_HOTKEY){HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);HotKeyHelper.OnHotKeyPressed(e);}base.WndProc(ref m);}protected override void SetVisibleCore(bool value){// Ensure the window never becomes visiblebase.SetVisibleCore(false);}private const int WM_HOTKEY = 0x312;}}public class HotKeyEventArgs : EventArgs{public readonly Keys Key;public readonly KeyModifiers Modifiers;public HotKeyEventArgs(Keys key, KeyModifiers modifiers){this.Key = key;this.Modifiers = modifiers;}public HotKeyEventArgs(IntPtr hotKeyParam){uint param = (uint)hotKeyParam.ToInt64();Key = (Keys)((param & 0xffff0000) >> 16);Modifiers = (KeyModifiers)(param & 0x0000ffff);}}
调用示例
void RegisterHotKeyTest(){HotKeyHelper.RegisterHotKey(Keys.B, KeyModifiers.Alt);HotKeyHelper.HotKeyPressed += new EventHandler<HotKeyEventArgs>(OnHotKeyPressed);}void OnHotKeyPressed(object sender, HotKeyEventArgs e){MessageBox.Show("Alt + B");}
执行结果
如果需要注册成Windows服务在后台运行,需要开启Service的允许与桌面交互选项。