WPFの三种方式实现快捷键

原文: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("命令执行!");
 }

原文地址:https://www.cnblogs.com/lonelyxmas/p/9941791.html

时间: 2024-10-10 01:32:13

WPFの三种方式实现快捷键的相关文章

AngularJs学习——实现数据绑定的三种方式

三种方式: 方式一:<h5>{{msg}}</h5>  此方式在页面刷新的时候会闪现{{}} 方式二:<h5 ng-bind="msg"></h5> 方式三:<h5 ng-clock class="ng-clock">{{msg}}</h5> 示例代码: <!DOCTYPE html> <html lang="en" ng-app="myapp&q

小蚂蚁学习页面静态化(2)——更新生成纯静态化页面的三种方式

更新生成纯静态化页面的三种方式:1.按照时间间隔更新.2.手动更新.3.定时更新(需要系统配合). 1. 按照时间间隔更新. 当用户第一次访问这个页面的时候,程序自动判断,该静态文件是否存在,并且该文件是否还在有效时间内,如果该文件未超出了有效时间,用户访问的是已经生成的静态文件.如果超出了有效时间,用户得到的是动态输出的内容,同时重新生成静态文件.稍微修改一下昨天的代码为例: <?php //首先判断是否有静态文件,并且文件的最新修改时间到现在是否大于20秒 if(is_file('./tex

Linux中设置服务自启动的三种方式

有时候我们需要Linux系统在开机的时候自动加载某些脚本或系统服务 主要用三种方式进行这一操作: ln -s                       在/etc/rc.d/rc*.d目录中建立/etc/init.d/服务的软链接(*代表0-6七个运行级别之一) chkonfig                命令行运行级别设置 ntsysv                   伪图形运行级别设置 注意:1.这三种方式主要用于以redhat为基础的发行版 2.如果还不知道运行级别是什么,那么最

Linux识别ntfs及挂载的三种方式

NTFS-3G是一个开源软件,支持在Linux操作系统下读写NTFS格式的分区.它能快速且安全的操作Windows XP,Windows Server 2003, Windows 2000 以及WindowsVista文件系统. 1 .环境准备 安装该软件需要依赖于fuse, Centos6.*中应该默认安装过fuse: [[email protected] yum.repos.d]# rpm -q fuse fuse-2.8.3-4.el6.i686 已经安装 如果没有安装可以yum安装或者编

Tomcat热部署的三种方式

热部署是指在你修改项目BUG的时候对JSP或JAVA类进行了修改在不重启WEB服务器前提下能让修改生效.但是对配置文件的修改除外! 1.直接把项目web文件夹放在webapps里. 2.在tomcat\conf\server.xml中的<host></host>内部添加<context/>标签: <Context debug="0" docBase="D:\demo1\web" path="/demo1"

【Struts2】Struts2获取session的三种方式

1.Map<String,Object> map =  ActionContext.getContext().getSession(); 2.HttpSession session = ServletActionContext.getRequest().getSession(); 3.让Action实现SessionAware接口,并实现public void setSession(Map<String, Object> session) {} 方法,Struts2会在实例化Act

虚拟机NetworkAdapter三种方式的区别

虚拟机在安装时默认的有三块网卡,VMnet1和VMnet8,另外还有VMnet0 Vmware 还提供了三种网络连接模式: 分别为: A 桥接bridge  B NAT 网络地址转换 C  主机模式 下面来简单说一下 三种方式的区别  : 1) bridge : 默认使用VMnet0,不提供DHCP服务 在桥接模式下,虚拟机和宿主计算机处于同等地位,虚拟机就像是一台真实主机一样存在于局域网中.因此在桥接模式下,我们就要像对待其他真实计算机一样为其配置IP.网关.子网掩码等等.当我们可以自由分配局

【整理】Linux下中文检索引擎coreseek4安装,以及PHP使用sphinx的三种方式(sphinxapi,sphinx的php扩展,SphinxSe作为mysql存储引擎)

一,软件准备 coreseek4.1 (包含coreseek测试版和mmseg最新版本,以及测试数据包[内置中文分词与搜索.单字切分.mysql数据源.python数据源.RT实时索引等测试配置]) Mysql源码包 (必须选择与你已安装mysql的版本一致) 为了避免安装中出现依赖包缺失,你需要打一句鸡血: yum install make gcc g++ gcc-c++ libtool autoconf automake imake mysql-devel libxml2-devel exp

Java Class类以及获取Class实例的三种方式

T - 由此 Class 对象建模的类的类型.例如,String.class 的类型是Class<String>.如果将被建模的类未知,则使用Class<?>. [java] view plain copy print? public final class Class<T> extends Object  implements java.io.Serializable, java.lang.reflect.GenericDeclaration, java.lang.r