场景

wpf窗体运行后,只能捕获当前Active窗体的按键事件,如果要监听windows全局事件,并对当前窗口事件响应.

第一步:导入Winows API

  1. public class Win32
  2. {
  3. [DllImport("User32.Dll")]
  4. public static extern void SetWindowText(int h, String s);
  5.  
  6. /// <summary>
  7. /// 如果函数执行成功,返回值不为0。
  8. /// 如果函数执行失败,返回值为0。要得到扩展错误信息,调用GetLastError。.NET方法:Marshal.GetLastWin32Error()
  9. /// </summary>
  10. /// <param name="hWnd">要定义热键的窗口的句柄</param>
  11. /// <param name="id">定义热键ID(不能与其它ID重复) </param>
  12. /// <param name="fsModifiers">标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效</param>
  13. /// <param name="vk">定义热键的内容,WinForm中可以使用Keys枚举转换,
  14. /// WPF中Key枚举是不正确的,应该使用System.Windows.Forms.Keys枚举,或者自定义正确的枚举或int常量</param>
  15. /// <returns></returns>
  16. [DllImport("user32.dll", SetLastError = true)]
  17. public static extern bool RegisterHotKey(
  18. IntPtr hWnd,
  19. int id,
  20. KeyModifiers fsModifiers,
  21. int vk
  22. );
  23.  
  24. /// <summary>
  25. /// 取消注册热键
  26. /// </summary>
  27. /// <param name="hWnd">要取消热键的窗口的句柄</param>
  28. /// <param name="id">要取消热键的ID</param>
  29. /// <returns></returns>
  30. [DllImport("user32.dll", SetLastError = true)]
  31. public static extern bool UnregisterHotKey(
  32. IntPtr hWnd,
  33. int id
  34. );
  35.  
  36. /// <summary>
  37. /// 向全局原子表添加一个字符串,并返回这个字符串的唯一标识符,成功则返回值为新创建的原子ID,失败返回0
  38. /// </summary>
  39. /// <param name="lpString"></param>
  40. /// <returns></returns>
  41. [DllImport("kernel32", SetLastError = true)]
  42. public static extern short GlobalAddAtom(string lpString);
  43.  
  44. [DllImport("kernel32", SetLastError = true)]
  45. public static extern short GlobalDeleteAtom(short nAtom);
  46.  
  47. /// <summary>
  48. /// 定义了辅助键的名称(将数字转变为字符以便于记忆,也可去除此枚举而直接使用数值)
  49. /// </summary>
  50. [Flags()]
  51. public enum KeyModifiers
  52. {
  53. None = ,
  54. Alt = ,
  55. Ctrl = ,
  56. Shift = ,
  57. WindowsKey =
  58. }
  59. /// <summary>
  60. /// 热键的对应的消息ID
  61. /// </summary>
  62. public const int WmHotkey = 0x312;
  63. }

第二步:注册快捷键

  1. /// <summary>
  2. /// 注册快捷集合
  3. /// </summary>
  4. readonly Dictionary<string, short> hotKeyDic = new Dictionary<string, short>();
  5.  
  6. public MainWindow()
  7. {
  8. InitializeComponent();
  9.  
  10. this.Loaded += (sender, e) =>
  11. {
  12. var wpfHwnd = new WindowInteropHelper(this).Handle;
  13.  
  14. var hWndSource = HwndSource.FromHwnd(wpfHwnd);
  15. //添加处理程序
  16. if (hWndSource != null) hWndSource.AddHook(MainWindowProc);
  17.  
  18. hotKeyDic.Add("Alt-S", Win32.GlobalAddAtom("Alt-S"));
  19. hotKeyDic.Add("Alt-D", Win32.GlobalAddAtom("Alt-D"));
  20. Win32.RegisterHotKey(wpfHwnd, hotKeyDic["Alt-S"], Win32.KeyModifiers.Alt, (int)System.Windows.Forms.Keys.S);
  21. Win32.RegisterHotKey(wpfHwnd, hotKeyDic["Alt-D"], Win32.KeyModifiers.Alt, (int)System.Windows.Forms.Keys.D);
  22. };
  23. }

第三步:响应快捷键事件

  1. /// <summary>
  2. /// 响应快捷键事件
  3. /// </summary>
  4. /// <param name="hwnd"></param>
  5. /// <param name="msg"></param>
  6. /// <param name="wParam"></param>
  7. /// <param name="lParam"></param>
  8. /// <param name="handled"></param>
  9. /// <returns></returns>
  10. private IntPtr MainWindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
  11. {
  12. switch (msg)
  13. {
  14. case Win32.WmHotkey:
  15. {
  16. int sid = wParam.ToInt32();
  17. if (sid == hotKeyDic["Alt-S"])
  18. {
  19. MessageBox.Show("按下Alt+S");
  20. }
  21. else if (sid == hotKeyDic["Alt-D"])
  22. {
  23. MessageBox.Show("按下Alt+D");
  24. }
  25. handled = true;
  26. break;
  27. }
  28. }
  29.  
  30. return IntPtr.Zero;
  31. }

WPF获得全局窗体句柄,并响应全局键盘事件的更多相关文章

  1. 【winform-窗体快捷键】定义功能窗体快捷键,非全局

    这里的快捷键并非系统全局快捷键.仅是普通的当窗体在焦点内发生.有很多种方法,这里列举几种项目中使用到的方法. Alt+*(一般控件快捷键) 这个比较简单,只需为该控件的Text属性声明时加上”(&am ...

  2. 获取当前进程(程序)主窗体句柄并设置wpf的父窗体为此句柄

    有时候在c++调用wpf控件的时候,wpf控件想自己显示窗体,但需要设置owner属性.迂回解决办法是设置wpf的window窗体的父窗体为进程的句柄. 1.获取当前进程id int id = Pro ...

  3. duilib底层机制剖析:窗体类与窗体句柄的关联

    转载请说明原出处,谢谢~~ 看到群里朋友有人讨论WTL中的thunk技术,让我联想到了duilib的类似技术.这些技术都是为了解决c++封装的窗体类与窗体句柄的关联问题. 这里是三篇关于thunk技术 ...

  4. VC中获取窗体句柄的各种方法

    AfxGetMainWnd AfxGetMainWnd获取自身窗体句柄 HWND hWnd = AfxGetMainWnd()->m_hWnd; GetTopWindow 函数功能:该函数检查与 ...

  5. WPF中不规则窗体与WindowsFormsHost控件的兼容问题完美解决方案

    首先先得瑟一下,有关WPF中不规则窗体与WindowsFormsHost控件不兼容的问题,网上给出的解决方案不能满足所有的情况,是有特定条件的,比如  WPF中不规则窗体与WebBrowser控件的兼 ...

  6. JCEF3——谷歌浏览器内核Java版实现(一):使用jawt获取窗体句柄

    前言 最近一段时间研究谷歌浏览器内核.谷歌浏览器内核一直开源,并维护更新,它的开源项目中内核更新速度和Chrome浏览器版本更新进度一样!而且它不同于WebKit(值得一题的是谷歌浏览器已不使用Web ...

  7. WPF 之 自定义窗体标题栏

    在WPF中自定义窗体标题栏,首先需要将窗体的WindowStyle属性设置为None,隐藏掉WPF窗体的自带标题栏.然后可以在窗体内部自定义一个标题栏. 例如,标题栏如下: <WrapPanel ...

  8. 在DLL中封装的VCL窗体Tab键响应的问题

    在DLL中的子窗体不会响应Tab按键的,这个时候就需要手动去指定Tab键的操作,但是前提是主窗体要向这个窗体发送一个消息,一个Tab键按下的消息.基本顺序是这样的: 1. 主窗体用Hook技术捕获Ta ...

  9. WPF中不规则窗体与WebBrowser控件的兼容问题解决办法

    原文:WPF中不规则窗体与WebBrowser控件的兼容问题解决办法 引言 这几天受委托开发一个网络电视项目,要求初步先使用内嵌网页形式实现视频播放和选单,以后再考虑将网页中的所有功能整合进桌面程序. ...

随机推荐

  1. lintcode 453 将二叉树拆成链表

    将二叉树拆成链表   描述 笔记 数据 评测 将一棵二叉树按照前序遍历拆解成为一个假链表.所谓的假链表是说,用二叉树的 right 指针,来表示链表中的 next 指针. 注意事项 不要忘记将左儿子标 ...

  2. 接口测试入门(3)--使用httpClient进行登录用例操作/set-cookies验证/ List<NameValuePair>设置post参数/json解析

    (最近学的都是很基础的接口测试,都是基于UI界面可见的接口,就是发请求,接收响应,分析返回的结果,校验,对共通模块进行封装,仅此而已,其实做自动化的思路基本都是如此,UI也是.) 现在开始用httpC ...

  3. Apache Spark 2.2.0 中文文档 - 快速入门 | ApacheCN

    快速入门 使用 Spark Shell 进行交互式分析 基础 Dataset 上的更多操作 缓存 独立的应用 快速跳转 本教程提供了如何使用 Spark 的快速入门介绍.首先通过运行 Spark 交互 ...

  4. 【漏洞公告】CVE-2017-12615/CVE-2017-12616:Tomcat信息泄漏和远程代码执行漏洞

    2017年9月19日,Apache Tomcat官方确认并修复了两个高危漏洞,漏洞CVE编号:CVE-2017-12615和CVE-2017-12616,该漏洞受影响版本为7.0-7.80之间,在一定 ...

  5. 一张图告诉你移动Web前端所有技术(工程化、预编译、自动化)

    你要的移动web前端都在这里! 大前端方向:移动Web前端.Native客户端.Node.js. 大前端框架:React.Vue.js.Koa 跨终端技术:HTML5.CSS 3.JavaScript ...

  6. 【个人笔记】《知了堂》mysql表连接

    为什么使用表连接 什么是表连接? 如果数据来自多个表,那么可以采用链接查询的方式来实现.因此表连接就是多个表连接合在一起实现查询效果 表连接的原理 表连接采用的是笛卡尔乘积,称之为横向连接. 笛卡尔乘 ...

  7. VS2015 + EF6连接MYSQL

    ADO.NET Entity Framework 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) 解决方案,不仅支持SQL Server,还支持MySQL.Ora ...

  8. Python扩展方法一二事

    前言 跟着一个有强迫症的老板干活是一件极其幸福的事情(你懂的).最近碰到一个问题,简单的说就是对一个对象做出部分修改后仍然返回此对象,于是我就写了一个方法,老板看了之后只有一句话:不雅观,改成直接对此 ...

  9. SqlHelper工具类

    public class SqlHlper { public static readonly string constr = ConfigurationManager.ConnectionString ...

  10. 洗礼灵魂,修炼python(7)--元组,集合,不可变集合

    前面已经把列表的基本用法讲解完 接着讲python的几大核心之--元组(tuple) 1.什么是元组? 类似列表,但为不可变对象,之前提到列表是可变对象,所谓可变对象就是支持原处修改,并且在修改前后对 ...