今天写一个小程序中使用到了全局快捷键,找到了我之前写的文章在c#中使用全局快捷键翻了一下,发现它是WinForm版本的,而我现在大部分写WPF程序了,便将其翻译了为WPF版本的了。
1 static class Hotkey 2 { 3 #region 系统api 4 [DllImport("user32.dll")] 5 [return: MarshalAs(UnmanagedType.Bool)] 6 static extern bool RegisterHotKey(IntPtr hWnd, int id, HotkeyModifiers fsModifiers, uint vk); 7 8 [DllImport("user32.dll")] 9 static extern bool UnregisterHotKey(IntPtr hWnd, int id); 10 #endregion 11 12 /// <summary> 13 /// 注册快捷键 14 /// </summary> 15 /// <param name="window">持有快捷键窗口</param> 16 /// <param name="fsModifiers">组合键</param> 17 /// <param name="key">快捷键</param> 18 /// <param name="callBack">回调函数</param> 19 public static void Regist(Window window, HotkeyModifiers fsModifiers, Key key, HotKeyCallBackHanlder callBack) 20 { 21 var hwnd = new WindowInteropHelper(window).Handle; 22 var _hwndSource = HwndSource.FromHwnd(hwnd); 23 _hwndSource.AddHook(WndProc); 24 25 int id = keyid++; 26 27 var vk = KeyInterop.VirtualKeyFromKey(key); 28 if (!RegisterHotKey(hwnd, id, fsModifiers, (uint)vk)) 29 throw new Exception("regist hotkey fail."); 30 keymap[id] = callBack; 31 } 32 33 /// <summary> 34 /// 快捷键消息处理 35 /// </summary> 36 static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 37 { 38 if (msg == WM_HOTKEY) 39 { 40 int id = wParam.ToInt32(); 41 if (keymap.TryGetValue(id, out var callback)) 42 { 43 callback(); 44 } 45 } 46 return IntPtr.Zero; 47 } 48 49 /// <summary> 50 /// 注销快捷键 51 /// </summary> 52 /// <param name="hWnd">持有快捷键窗口的句柄</param> 53 /// <param name="callBack">回调函数</param> 54 public static void UnRegist(IntPtr hWnd, HotKeyCallBackHanlder callBack) 55 { 56 foreach (KeyValuePair<int, HotKeyCallBackHanlder> var in keymap) 57 { 58 if (var.Value == callBack) 59 UnregisterHotKey(hWnd, var.Key); 60 } 61 } 62 63 64 const int WM_HOTKEY = 0x312; 65 static int keyid = 10; 66 static Dictionary<int, HotKeyCallBackHanlder> keymap = new Dictionary<int, HotKeyCallBackHanlder>(); 67 68 public delegate void HotKeyCallBackHanlder(); 69 } 70 71 enum HotkeyModifiers 72 { 73 MOD_ALT = 0x1, 74 MOD_CONTROL = 0x2, 75 MOD_SHIFT = 0x4, 76 MOD_WIN = 0x8 77 }
代码仍然差不多,使用的方式更加简单一点:
protected override void OnSourceInitialized(EventArgs e)
{
Hotkey.Regist(this, HotkeyModifiers.MOD_ALT, Key.T, () =>
{
MessageBox.Show("hello");
});
_context = new MainContext();
this.DataContext = _context;
_context.Process();
}
需要注意的是,调用Hotkey.Regist函数时,需要窗口是分配了句柄的,因此建议在OnLoad事件或OnSourceInitialized函数中进行。