翼度科技»论坛 编程开发 .net 查看内容

WPF监听快捷键的几种方式

7

主题

7

帖子

21

积分

新手上路

Rank: 1

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

那么,假如我要在一个WPF程序监听CTRL+5按键,首先在主窗口程序添加以下代码:
  1.         /// <summary>
  2.         /// CTRL+5事件Id
  3.         /// </summary>
  4.         private const int Ctrl5KeyEventId = 9000;
  5.         [DllImport("user32.dll")]
  6.         public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
  7.         [DllImport("user32.dll")]
  8.         public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
  9.         protected override void OnSourceInitialized(EventArgs e)
  10.         {
  11.             base.OnSourceInitialized(e);
  12.             var handle = new WindowInteropHelper(this).Handle;
  13.             var source = HwndSource.FromHwnd(handle);
  14.             source?.AddHook(HwndHook);
  15.             //真正注册快捷键监听处理: 同时注册数字键和小键盘的CTRL+5
  16.             RegisterHotKey(handle, Ctrl5KeyEventId, (uint)ModifierKeys.Control, (uint)KeyInterop.VirtualKeyFromKey(Key.D5));
  17.             RegisterHotKey(handle, Ctrl5KeyEventId, (uint)ModifierKeys.Control, (uint)KeyInterop.VirtualKeyFromKey(Key.NumPad5));
  18.         }
  19.         private IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
  20.         {
  21.             const int wmHotkey = 0x0312;
  22.             switch (msg)
  23.             {
  24.                 case wmHotkey:
  25.                     switch (wParam.ToInt32())
  26.                     {
  27.                         case Ctrl5KeyEventId:
  28.                             Debug.WriteLine("Win32监听CTRL+5成功");
  29.                             break;
  30.                     }
  31.                     break;
  32.             }
  33.             return IntPtr.Zero;
  34.         }
  35.         protected override void OnClosing(CancelEventArgs e)
  36.         {
  37.             base.OnClosing(e);
  38.             var handle = new WindowInteropHelper(this).Handle;
  39.             //关闭窗口后取消注册
  40.             UnregisterHotKey(handle, Ctrl5KeyEventId);
  41.         }
复制代码
监听WPF的KeyDown事件(不够清真,可选择,最小化失焦等情况监听失效)
  1.         public MainWindow()
  2.         {
  3.             InitializeComponent();
  4.             KeyDown += MainWindow_KeyDown;
  5.         }
  6.         private void MainWindow_KeyDown(object sender, KeyEventArgs e)
  7.         {
  8.             if (Keyboard.Modifiers == ModifierKeys.Control && (e.Key == Key.D5 || e.Key == Key.NumPad5))
  9.             {
  10.                 Debug.WriteLine("WPF的KeyDown事件监听CTRL+5成功"); ;
  11.                 e.Handled = true;
  12.             }
  13.         }
复制代码
XAML绑定命令方式(WPF当然优先选中命令绑定啦,清真,最小化失焦等情况监听失效)

以下为Window主窗体的XAML代码
  1.     <Window.CommandBindings>
  2.         <CommandBinding Command="{x:Static local:Commands.Ctrl5Command}" Executed="Ctrl5Command_OnExecuted"/>
  3.     </Window.CommandBindings>
  4.     <Window.InputBindings>
  5.         <KeyBinding Modifiers="Control" Key="D5"  Command="{x:Static  local:Commands.Ctrl5Command}" />
  6.         <KeyBinding Modifiers="Control" Key="NumPad5"  Command="{x:Static  local:Commands.Ctrl5Command}" />
  7.     </Window.InputBindings>
复制代码
在Window主窗体后台代码创建命令对应的Executed方法
  1.         private void Ctrl5Command_OnExecuted(object sender, ExecutedRoutedEventArgs e)
  2.         {
  3.             Debug.WriteLine("WPF的XAML绑定命令监听CTRL+5成功");
  4.         }
复制代码
新增命令相关的静态类:
  1.     public static class Commands
  2.     {
  3.         public static ICommand Ctrl5Command { get; } = new RoutedCommand();
  4.     }
复制代码
细节

三个监听方案的优先级

其中Win32 > XAML绑定命令 = KeyDown事件,假如同时监听的话,其中会只处理高优先级的,以上面的例子,假如
我同时监听三个,只会处理win32的
  1. Win32监听CTRL+5成功
复制代码
全局监听问题

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

DEMO链接

来源:https://www.cnblogs.com/ryzen/archive/2023/03/20/17235188.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具