WPFの三种方式实现快捷键
最近,对wpf添加快捷键的方式进行了整理。主要用到的三种方式如下:
一、wpf命令:
- 资源中添加命令
- <Window.Resources>
- <RoutedUICommand x:Key="ToolCapClick" Text="截屏快捷键" />
- </Window.Resources>
- 输入命令绑定
- <Window.InputBindings>
- <KeyBinding Gesture="Ctrl+Alt+Q" Command="{StaticResource ToolCapClick}"/>
- </Window.InputBindings>
- 命令执行方法绑定
- <Window.CommandBindings>
- <CommandBinding Command="{StaticResource ToolCapClick}"
- CanExecute="CommandBinding_ToolCapClick_CanExecute"
- Executed="CommandBinding_ToolCapClick_Executed"/>
- </Window.CommandBindings>
需要注意的是,绑定命令的时候,也可以<KeyBinding Modifiers="Ctrl+Alt" Key="Q" Command="{StaticResource ToolCapClick}"/>,建议用前者,以免造成混乱。
执行方法实现
- #region 截屏快捷键
- private void CommandBinding_ToolCapClick_CanExecute(object sender, CanExecuteRoutedEventArgs e)
- {
- e.CanExecute = true;
- }
- private void CommandBinding_ToolCapClick_Executed(object sender, ExecutedRoutedEventArgs e)
- {
- try
- {
- CaptureImageTool capture = new CaptureImageTool();
- capture.CapOverToHandWriting += Capture_CapOverToHandWriting;
- capture.CapOverToBlackboard += Capture_CapOverToBlackboard;
- string saveName = String.Empty;
- if (capture.ShowDialog() == System.Windows.Forms.DialogResult.OK)
- {
- //保存截取的内容
- System.Drawing.Image capImage = capture.Image;
- //上课存班级内部,不上课存外部
- string strSavePath = DataBusiness.GetCurrentTeachFilePath(SystemConstant.PATH_CAPS);
- if (!String.IsNullOrEmpty(strSavePath))
- {
- if (!Directory.Exists(strSavePath))
- {
- Directory.CreateDirectory(strSavePath);
- }
- saveName = strSavePath + DateTime.Now.ToString(SystemConstant.FORMAT_CAPS);
- }
- else
- {
- saveName = PathExecute.GetPathFile(SystemConstant.PATH_SAVE + Path.DirectorySeparatorChar + SystemConstant.PATH_CAPS, DateTime.Now.ToString(SystemConstant.FORMAT_CAPS));
- }
- capImage.Save(saveName + SystemConstant.EXTENSION_PNG, System.Drawing.Imaging.ImageFormat.Png);
- }
- }
- catch (Exception ex)
- {
- new Exception("capscreen module error:" + ex.Message);
- }
- }
二、利用windows钩子(hook)函数
第一步 引入到Winows API
- 1: [DllImport("user32.dll")]
- 2: public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
- 3: [DllImport("user32.dll")]
- 4: public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
这边可以参考两个MSDN的链接
第一个是关于RegisterHotKey函数的,里面有关于id,fsModifiers和vk 的具体说明
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646309%28v=vs.85%29.aspx
第二个是Virtual-Key 的表,即RegisterHotKey的最后一个参数
http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
第二步 注册全局按键
这里先介绍一个窗体的事件SourceInitialized,这个时间发生在WPF窗体的资源初始化完毕,并且可以通过WindowInteropHelper获得该窗体的句柄用来与Win32交互。
具体可以参考MSDN http://msdn.microsoft.com/en-us/library/system.windows.window.sourceinitialized.aspx
我们通过重载OnSourceInitialized来在SourceInitialized事件发生后获取窗体的句柄,并且注册全局快捷键
- private const Int32 MY_HOTKEYID = 0x9999;
- protected override void OnSourceInitialized(EventArgs e)
- {
- base.OnSourceInitialized(e);
- IntPtr handle = new WindowInteropHelper(this).Handle;
- RegisterHotKey(handle, MY_HOTKEYID, 0x0001, 0x72);
- }
关于几个常熟的解释
MY_HOTKEYID 是一个自定义的ID,取值范围在0x0000 到 0xBFFF。之后我们会根据这个值来判断事件的处理。
RegisterHotKey的第三或第四个参数可以参考第一步
第三步 添加接收所有窗口消息的事件处理程序
上面只是在系统中注册了快捷键,但是还要获取消息的事件,并筛选消息。
继续在OnSourceInitialized函数中操作
- protected override void OnSourceInitialized(EventArgs e)
- {
- base.OnSourceInitialized(e);
- IntPtr handle = new WindowInteropHelper(this).Handle;
- RegisterHotKey(handle, MY_HOTKEYID, 0x0001, 0x72);
- HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
- source.AddHook(WndProc);
- }
下面来完成WndProc函数
- IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handle)
- {
- //Debug.WriteLine("hwnd:{0},msg:{1},wParam:{2},lParam{3}:,handle:{4}"
- // ,hwnd,msg,wParam,lParam,handle);
- if(wParam.ToInt32() == MY_HOTKEYID)
- {
- //全局快捷键要执行的命令
- }
- return IntPtr.Zero;
- }
三、给button控件添加快捷键
- <UserControl.Resources>
- <RoutedUICommand x:Key="ClickCommand" Text="点击快捷键" />
- </UserControl.Resources>
- <UserControl.CommandBindings>
- <CommandBinding Command="{StaticResource ClickCommand}"
- Executed="ClickHandler" />
- </UserControl.CommandBindings>
- <UserControl.InputBindings>
- <KeyBinding Key="C" Modifiers="Ctrl" Command="{StaticResource ClickCommand}" />
- </UserControl.InputBindings>
- <Grid>
- <Button Content="button" Command="{StaticResource ClickCommand}"/>
- </Grid>
执行方法:
- private void ClickHandler(object sender, RoutedEventArgs e)
- {
- Message.Show("命令执行!");
- }
WPFの三种方式实现快捷键的更多相关文章
- WPF中实现PropertyGrid(用于展示对象的详细信息)的三种方式
原文:WPF中实现PropertyGrid(用于展示对象的详细信息)的三种方式 由于WPF中没有提供PropertyGrid控件,有些业务需要此类的控件.这篇文章介绍在WPF中实现PropertyGr ...
- 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件 内容简介:本文介绍 Spring Boot 的配置文件和配置管理,以及介绍了三种读取配置文 ...
- 监视EntityFramework中的sql流转你需要知道的三种方式Log,SqlServerProfile, EFProfile
大家在学习entityframework的时候,都知道那linq写的叫一个爽,再也不用区分不同RDMS的sql版本差异了,但是呢,高效率带来了差灵活性,我们 无法控制sql的生成策略,所以必须不要让自 ...
- iOS字体加载三种方式
静态加载 动态加载 动态下载苹果提供的多种字体 其他 打印出当前所有可用的字体 检查某字体是否已经下载 这是一篇很简短的文章,介绍了 iOS 自定义字体加载的三种方式. 静态加载 这个可以说是最简单最 ...
- 0036 Java学习笔记-多线程-创建线程的三种方式
创建线程 创建线程的三种方式: 继承java.lang.Thread 实现java.lang.Runnable接口 实现java.util.concurrent.Callable接口 所有的线程对象都 ...
- 【整理】Linux下中文检索引擎coreseek4安装,以及PHP使用sphinx的三种方式(sphinxapi,sphinx的php扩展,SphinxSe作为mysql存储引擎)
一,软件准备 coreseek4.1 (包含coreseek测试版和mmseg最新版本,以及测试数据包[内置中文分词与搜索.单字切分.mysql数据源.python数据源.RT实时索引等测 ...
- JDBC的批处理操作三种方式 pstmt.addBatch()
package lavasoft.jdbctest; import lavasoft.common.DBToolkit; import java.sql.Connection; import java ...
- 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】
一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...
- Java设置session超时(失效)的三种方式
1. 在web容器中设置(此处以tomcat为例) 在tomcat-6.0\conf\web.xml中设置,以下是tomcat 6.0中的默认配置: <!-- ================= ...
随机推荐
- 一篇很全面的freemarker教程
以下内容全部是网上收集: FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成:1,文本:直接输出的部分2,注释:<#-- ... --& ...
- GIT与SVN的区别
1.GIT是分布式的,SVN不是: 这是GIT和其它非分布式的版本控制系统,例如SVN,CVS等,最核心的区别.如果你能理解这个概念,那么你就已经上手一半了.需要做一点声明,GIT并不是目前第一个或唯 ...
- js 随机数 洗牌算法
function shuffle(arr){ var len = arr.length; for(var i = 0;i<len -1;i++) { var idx = Math.floor(M ...
- 解决Android调用https服务API时出错的问题
今天同事告诉我说他的应用调用我开发的API报异常了,原因跟SSL有关系,因为之前调试一直调用的是HTTP服务API,今天调试HTTPS服务API时报错了,并且找到了一篇文章让我看了一眼,文章中提到了W ...
- 将CachedRowSet中的数据转储到对象中
虽然还有很多bug,但凑合能用,就是将CachedRowSet中的数据转换成对象或List.省去了繁琐难看的一系列get/set方法. 先说调用: 注: cachedRowSet是查询的结果集 Stu ...
- java 正则表达式获取匹配和非获取匹配
package test1; import java.util.regex.Matcher; import java.util.regex.Pattern; public class TestExp ...
- 有效的PhoneGap CSS: WebKit Tap Highlight Color
原文链接:文章1:http://phonegap-tips.com/articles/essential-phonegap-css-webkit-tap-highlight-color.html(此文 ...
- 直观友好的单个memcache监控工具:phpmemcache.php
上传phpmemcache.php到指定文件 修改文件中的: define('ADMIN_USERNAME','user'); // Admin Usernamedefine('ADMIN_P ...
- Nodejs开发(2.连接MongoDB)
一.先配置MongoDB Win10下下载那个安装版,zip版的会报却各种DLL,安装在你希望的路径,实在安装错了,就剪切过来也行(本例E:\mongodb). 然后是配置启动脚本,就是写一个bat文 ...
- Wordpress 标题设置
使用标题格式:首页(网站标题 - 网站副标题),其他页面(页面标题 | 网站标题) 在后台找到头部文件head.php <?php wp_title('|', true, 'right'); e ...