调用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. holiday08

    第八天 管道 linux允许将 一个命令的输出 可以 通过管道 作为 另一个命令的输入 ls -lh | more 可以理解现实生活中的管子,管子一头塞东西进去,另一头取出来,这里 | 的左右分为两端 ...

  2. 删除Windows10资源管理器多余的入口

    ///// 删除3D对象 定位到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\Nam ...

  3. git和coding的使用

    1.注册 coding ::::::https://coding.net/ 2.个人设置中添加上邮箱账号和密码 3.下载git 4.在coding中新建项目,并对项目初始化---生成分支,会生成url ...

  4. postman收藏 -大佬玩法。

    请求顺序:    https://www.cnblogs.com/superhin/p/11454832.html 在Postman脚本中发送请求(pm.sendRequest) : https:// ...

  5. react 获取文件流导出功能

    记录一下: 根据后台接口返回的文件流,前端实现导出下载,使用(react+ts) 1.请求方法 (这里写法绕开拦截器) // 导出日志 export async function exportLog( ...

  6. PLC入门笔记11

    1.开关? 输入 拨杆开关.点动开关.常开.常闭开关 霍尔接近开关(磁场 N极导通 3线+-DC24V ).电容接近开关(非金属).电感接近开关(金属) 2.输入接线? NPN型,不需要外接电源,直接 ...

  7. centos7.2 64位安装php7.2.12

    1 安装php所需要的扩展 yum -y install libxml2 libxml2-devel openssl openssl-devel bzip2 bzip2-devel curl curl ...

  8. Spring Boot统一日志框架

    一.日志框架的选择 市面上常见的日志框架有很多,它们可以被分为两类:日志门面(日志抽象层)和日志实现,如下表.  日志分类 描述 举例 日志门面(日志抽象层) 为 Java 日志访问提供一套标准和规范 ...

  9. ASP.NET Core 读取配置文件信息

    一:读取配置文件 先来看一下appsettings.json文件的内容,如下图: { "ConnectionStrings": { "ServerConnection&q ...

  10. Java的由来

    Java 发展史 1.1.起源 20 世纪 90 年代,单片式计算机系统诞生,单片式计算机系统不仅廉价,而且功能强大,使用它 可以大幅度提升消费性电子产品的智能化程度. SUN 公司为了抢占市场先机, ...