调用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链接

WPF监听快捷键的几种方式的更多相关文章

  1. ASP.NET Core中配置监听URLs的五种方式

    原文: 5 ways to set the URLs for an ASP.NET Core app 作者: Andrew Lock 译者: Lamond Lu 默认情况下,ASP. NET Core ...

  2. springboot 中事件监听模型的一种实现

    目录 定义事件本身 定义事件源 定义监听者 一.需要实现 ApplicationListener 二.使用 @EventListener 注解 测试 项目结构 前言: 事件监听模型是一种常用的设计模式 ...

  3. bootstrap课程12 滚动监听如何实现(bootstrap方式和自定义方式)

    bootstrap课程12 滚动监听如何实现(bootstrap方式和自定义方式) 一.总结 一句话总结:通过监听滚动的高,判断滚动的高是否大于元素距离顶端的距离 1.如何知道屏幕滚动的高? st=$ ...

  4. JS003. 事件监听和监听滚动条的三种参数( addEventListener( ) )

    全局 1 window.addEventListener('scroll', () => { 2 console.log('------') 3 console.log(document.doc ...

  5. Second Day: 关于Button监听事件的三种方法(匿名类、外部类、继承接口)

    第一种:通过匿名类实现对Button事件的监听 首先在XML文件中拖入一个Button按钮,并设好ID,其次在主文件.java中进行控件初始化(Private声明),随后通过SetOnClickLis ...

  6. WPF - 监听判断键盘组合键的按下

    对于键盘事件PreviewKeyDown.PreviewKeyUp.KeyDown.KeyUp,在其中检查当次事件是哪个按键触发的很简单,只需要判断KeyEventArgs类型的事件参数e的Key属性 ...

  7. miniui 给表格行添加监听事件的几种方法以及点击某列列名数据不能排序的问题

    最近在使用miniui框架做开发,在做表格行的点击监听事件中发现了几个属性,都可以起到监听效果但是执行的结果却大有不同.好了废话不多说,直接上代码. <div id="pageGrid ...

  8. 009-Spring Boot 事件监听、监听器配置与方式、spring、Spring boot内置事件

    一.概念 1.事件监听的流程 步骤一.自定义事件,一般是继承ApplicationEvent抽象类 步骤二.定义事件监听器,一般是实现ApplicationListener接口 步骤三.启动时,需要将 ...

  9. 解决Oracle监听错误的一种办法

    1:事出有因 安装oracle数据库,默认安装的是orcl数据库,安装完成后查看了一下字符集是gbk的,由于业务需要al32utf8的字符集,所以需要修改字符集,但是修改却无效.于是就删除了默认的or ...

  10. UIScrollView监听静止的数种情况

    1.直接通过block -(void)testInBlock { //通过block监听 [UIView animateWithDuration:1.0 animations:^{ self.scro ...

随机推荐

  1. 招新题流程简介(WS2812)

    22物电科协软件招新题学习流程 有错误或者不当的地方请在评论区指出 题目简介 使用stm32驱动单一ws2812b灯珠实现呼吸灯效果,驱动及实现方法不限 演示效果 快速入门,在stm32核心板上点灯 ...

  2. JAVA第四五次大作业及期中考试总结

         21201411-李英涵            继承与多态blog2 前言: 期中考试的题目还可以,因为给了类图,但是难度也逐渐升高. pta中的四的第一题和第三题较为简单,因为第一题的正则 ...

  3. PostgreSQL 存储过程 通过设定条件,返回指定的数据表记录

    PL/pgSQL是 PostgreSQL 数据库系统的一个可装载的过程语言. PL/pgSQL的设计目标是创建一种可装载的过程语言,可以可用于创建函数和触发器过程, 在SQL语言中添加控制结构功能, ...

  4. go两种数据类型的区别、数据类型和操作符、常量、变量声明

    值类型和引用类型 1.值类型:变量直接存储值,内存通常在栈中分配. 基本数据类型int.float.bool.string以及数组和struct. 2.引用类型:变量存储的是一个地址,这个地址存储最终 ...

  5. python 创建虚拟环境python –m venv方式

    1.环境准备 1.1.刷新包清单 sudo yum update 1.2.安装SCL实用程序 sudo yum install centos-release-scl 1.3.安装Python 3.6 ...

  6. 【peewee】Python使用peewee时where中不同类型比较的问题

    问题 以学生表为例,TableStudents表中age字段是TextField类型,想要筛选出18岁以上的学生 TableStudents.select().where(TableStudents. ...

  7. IP协议数据包

    Header Length:头部长度固定20字节,永远为5(4bit为单位) Total Length:头部+包, 抓包结果 Identification.Fragment Flags.Fragmen ...

  8. redies概述

    1.redis下载路径 Windows:https://github.com/tporadowski/redis/releases Linux:http://redis.io/download 2.安 ...

  9. uni-app中调用高德地图去设置点和轨迹

    盒子部分 <view style="width: 100%; height: 100%" id="busContainer"> </view& ...

  10. springMVC的定时器

    大家好,本人从事软件行业已有8年,大部分时间从事软件开发编写工作.好了废话少说了哈哈哈,直接干货. 在Java开发过程中有很多业务需求里面需要我们实时处理一些动态的业务比如库存的数据动态更新,实时数据 ...