WPF监听快捷键的几种方式
调用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
WPF监听快捷键的几种方式的更多相关文章
- ASP.NET Core中配置监听URLs的五种方式
原文: 5 ways to set the URLs for an ASP.NET Core app 作者: Andrew Lock 译者: Lamond Lu 默认情况下,ASP. NET Core ...
- springboot 中事件监听模型的一种实现
目录 定义事件本身 定义事件源 定义监听者 一.需要实现 ApplicationListener 二.使用 @EventListener 注解 测试 项目结构 前言: 事件监听模型是一种常用的设计模式 ...
- bootstrap课程12 滚动监听如何实现(bootstrap方式和自定义方式)
bootstrap课程12 滚动监听如何实现(bootstrap方式和自定义方式) 一.总结 一句话总结:通过监听滚动的高,判断滚动的高是否大于元素距离顶端的距离 1.如何知道屏幕滚动的高? st=$ ...
- JS003. 事件监听和监听滚动条的三种参数( addEventListener( ) )
全局 1 window.addEventListener('scroll', () => { 2 console.log('------') 3 console.log(document.doc ...
- Second Day: 关于Button监听事件的三种方法(匿名类、外部类、继承接口)
第一种:通过匿名类实现对Button事件的监听 首先在XML文件中拖入一个Button按钮,并设好ID,其次在主文件.java中进行控件初始化(Private声明),随后通过SetOnClickLis ...
- WPF - 监听判断键盘组合键的按下
对于键盘事件PreviewKeyDown.PreviewKeyUp.KeyDown.KeyUp,在其中检查当次事件是哪个按键触发的很简单,只需要判断KeyEventArgs类型的事件参数e的Key属性 ...
- miniui 给表格行添加监听事件的几种方法以及点击某列列名数据不能排序的问题
最近在使用miniui框架做开发,在做表格行的点击监听事件中发现了几个属性,都可以起到监听效果但是执行的结果却大有不同.好了废话不多说,直接上代码. <div id="pageGrid ...
- 009-Spring Boot 事件监听、监听器配置与方式、spring、Spring boot内置事件
一.概念 1.事件监听的流程 步骤一.自定义事件,一般是继承ApplicationEvent抽象类 步骤二.定义事件监听器,一般是实现ApplicationListener接口 步骤三.启动时,需要将 ...
- 解决Oracle监听错误的一种办法
1:事出有因 安装oracle数据库,默认安装的是orcl数据库,安装完成后查看了一下字符集是gbk的,由于业务需要al32utf8的字符集,所以需要修改字符集,但是修改却无效.于是就删除了默认的or ...
- UIScrollView监听静止的数种情况
1.直接通过block -(void)testInBlock { //通过block监听 [UIView animateWithDuration:1.0 animations:^{ self.scro ...
随机推荐
- springboot自动装配静态成员变量
首先要说的是,springboot并不能装配静态类,但可以通过以下骚操作来实现: @Component public class StatisticLogger { private static Da ...
- 【七侠传】冲刺阶段--Day6
[七侠传]冲刺阶段--Day6 团队成员 20181221曾宇涛 20181202李祎铭 20181209沙桐 20181215薛胜瀚 20181216杨越麒 20181223何家豪 20181232 ...
- python 项目启动
批量执行requirements.txt文件: pip install -r requirements.txt 清华镜像源安装: pip install -i https://pypi.tuna.ts ...
- js-label
js中的label就像一个对已有语句块的命名,函数有了函数名我们可以随时调用它,语句块有了语句名我们也可以随时调用它,将他运用到循环中可快速跳出 循环. var num = 0;for (var i ...
- puts()与scanf(“%s”)
使用gets()即使字符串中含有空格,依然可以接收,而scanf()不会. Example: /* 输入一个字符串到字符数组s1中,将s1中的字符串复制到字符数组s2中并输出s2中的字符串. 不用st ...
- 使用React脚手架初始化项目
1.npx create-react-app my-app------>是项目名 2.cd my-app 3.npm start
- Oracle学习-----基本SQL select语句
一.基本select语句 SELECT 标识 选择那些列 FROM 标识从哪个表中选择 select * 标识 全部选择 select department_id, location_id ...
- 龙中华著《Spring Boot实战派》读书笔记之入门篇
第一章 进入Spring Boot的世界 理念:默认大于配置.有很多集成好的方案,开箱即用.针对痛点:环境配置耗时. 1.1 Spring Boot 的特色: 使用简单 注解方式实现类的定义和功能开发 ...
- MySQL分库分表原理
转自https://www.jianshu.com/p/7aec260ca1a2 前言 在互联网还未崛起的时代,我们的传统应用都有这样一个特点:访问量.数据量都比较小,单库单表都完全可以支撑整个业务. ...
- jmeter的三种参数化方式
一.通过添加前置处理器(用户参数) 1. 在http层级下添加--前置处理器--用户参数 2.可以修改名称,每次迭代更新一次(一定要勾选上),这样才会每次迭代变量值也更新 ,点击下面添加用户(多次测试 ...