在WPF中使用全局快捷键

Posted TianFang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在WPF中使用全局快捷键相关的知识,希望对你有一定的参考价值。

今天写一个小程序中使用到了全局快捷键,找到了我之前写的文章在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     }
View Code

 

代码仍然差不多,使用的方式更加简单一点:

protected override void OnSourceInitialized(EventArgs e)
{
    Hotkey.Regist(thisHotkeyModifiers.MOD_ALTKey.T, () =>
    {
        MessageBox.Show("hello");
    });

    _context = new MainContext();
    this.DataContext = _context;
    _context.Process();
}

需要注意的是,调用Hotkey.Regist函数时,需要窗口是分配了句柄的,因此建议在OnLoad事件或OnSourceInitialized函数中进行。

 

以上是关于在WPF中使用全局快捷键的主要内容,如果未能解决你的问题,请参考以下文章

WPF 窗体快捷键(热键)

WPF 窗体快捷键(热键)

如何制作“全局”wpf 应用程序热键

VS code自定义用户代码片段snippet

使用 Git 来管理 Xcode 中的代码片段

vs code 自定义代码片段