WPF监听快捷键的几种方式

  • WPF监听快捷键的几种方式已关闭评论
  • 162 次浏览
  • A+
所属分类:.NET技术
摘要

那么,假如我要在一个WPF程序监听CTRL+5按键,首先在主窗口程序添加以下代码:


调用Win32 API(优先级最高,全局监听, 支持最小化失焦等情况)

那么,假如我要在一个WPF程序监听CTRL+5按键,首先在主窗口程序添加以下代码:

         /// <summary>         /// CTRL+5事件Id         /// </summary>         private const int Ctrl5KeyEventId = 9000;           [DllImport("user32.dll")]         public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);          [DllImport("user32.dll")]         public static extern bool UnregisterHotKey(IntPtr hWnd, int id);           protected override void OnSourceInitialized(EventArgs e)         {             base.OnSourceInitialized(e);              var handle = new WindowInteropHelper(this).Handle;             var source = HwndSource.FromHwnd(handle);             source?.AddHook(HwndHook);             //真正注册快捷键监听处理: 同时注册数字键和小键盘的CTRL+5             RegisterHotKey(handle, Ctrl5KeyEventId, (uint)ModifierKeys.Control, (uint)KeyInterop.VirtualKeyFromKey(Key.D5));             RegisterHotKey(handle, Ctrl5KeyEventId, (uint)ModifierKeys.Control, (uint)KeyInterop.VirtualKeyFromKey(Key.NumPad5));         }           private IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)         {             const int wmHotkey = 0x0312;              switch (msg)             {                 case wmHotkey:                     switch (wParam.ToInt32())                     {                         case Ctrl5KeyEventId:                             Debug.WriteLine("Win32监听CTRL+5成功");                             break;                     }                     break;             }              return IntPtr.Zero;         }           protected override void OnClosing(CancelEventArgs e)         {             base.OnClosing(e);              var handle = new WindowInteropHelper(this).Handle;             //关闭窗口后取消注册             UnregisterHotKey(handle, Ctrl5KeyEventId);         }  

监听WPF的KeyDown事件(不够清真,可选择,最小化失焦等情况监听失效)

         public MainWindow()         {             InitializeComponent();             KeyDown += MainWindow_KeyDown;         }           private void MainWindow_KeyDown(object sender, KeyEventArgs e)         {             if (Keyboard.Modifiers == ModifierKeys.Control && (e.Key == Key.D5 || e.Key == Key.NumPad5))             {                 Debug.WriteLine("WPF的KeyDown事件监听CTRL+5成功"); ;                 e.Handled = true;             }         }   

XAML绑定命令方式(WPF当然优先选中命令绑定啦,清真,最小化失焦等情况监听失效)

以下为Window主窗体的XAML代码

     <Window.CommandBindings>         <CommandBinding Command="{x:Static local:Commands.Ctrl5Command}" Executed="Ctrl5Command_OnExecuted"/>     </Window.CommandBindings>     <Window.InputBindings>         <KeyBinding Modifiers="Control" Key="D5"  Command="{x:Static  local:Commands.Ctrl5Command}" />         <KeyBinding Modifiers="Control" Key="NumPad5"  Command="{x:Static  local:Commands.Ctrl5Command}" />     </Window.InputBindings>   

在Window主窗体后台代码创建命令对应的Executed方法

         private void Ctrl5Command_OnExecuted(object sender, ExecutedRoutedEventArgs e)         {             Debug.WriteLine("WPF的XAML绑定命令监听CTRL+5成功");         }  

新增命令相关的静态类:

     public static class Commands     {         public static ICommand Ctrl5Command { get; } = new RoutedCommand();     }  

细节

三个监听方案的优先级

其中Win32 > XAML绑定命令 = KeyDown事件,假如同时监听的话,其中会只处理高优先级的,以上面的例子,假如
我同时监听三个,只会处理win32的

 Win32监听CTRL+5成功  
全局监听问题

其中win32支持全局监听键盘,也就是窗口在失焦情况下,例如最小化,也能监听得到,其中XAML绑定命令KeyDown事件不支持失焦情况,最小化等情况也就监听不到了,因此,要按业务选择方案

DEMO

DEMO链接