1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Windows;
  8. using System.Windows.Forms;
  9. using System.Windows.Interop;
  10.  
  11. namespace WpfHotKey
  12. {
  13. public class HotKeyHelper
  14. {
  15.  
  16. /// <summary>
  17. /// 如果函数执行成功,返回值不为0。
  18. /// 如果函数执行失败,返回值为0。要得到扩展错误信息,调用GetLastError。.NET方法:Marshal.GetLastWin32Error()
  19. /// </summary>
  20. /// <param name="hWnd">要定义热键的窗口的句柄</param>
  21. /// <param name="id">定义热键ID(不能与其它ID重复) </param>
  22. /// <param name="fsModifiers">标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效</param>
  23. /// <param name="vk">定义热键的内容,WinForm中可以使用Keys枚举转换,
  24. /// WPF中Key枚举是不正确的,应该使用System.Windows.Forms.Keys枚举,或者自定义正确的枚举或int常量</param>
  25. /// <returns></returns>
  26. [DllImport("user32.dll", SetLastError = true)]
  27. static extern bool RegisterHotKey(
  28. IntPtr hWnd,
  29. int id,
  30. KeyModifiers fsModifiers,
  31. int vk
  32. );
  33.  
  34. /// <summary>
  35. /// 取消注册热键
  36. /// </summary>
  37. /// <param name="hWnd">要取消热键的窗口的句柄</param>
  38. /// <param name="id">要取消热键的ID</param>
  39. /// <returns></returns>
  40. [DllImport("user32.dll", SetLastError = true)]
  41. static extern bool UnregisterHotKey(
  42. IntPtr hWnd,
  43. int id
  44. );
  45.  
  46. /// <summary>
  47. /// 向全局原子表添加一个字符串,并返回这个字符串的唯一标识符,成功则返回值为新创建的原子ID,失败返回0
  48. /// </summary>
  49. /// <param name="lpString"></param>
  50. /// <returns></returns>
  51. [DllImport("kernel32", SetLastError = true)]
  52. static extern short GlobalAddAtom(string lpString);
  53.  
  54. [DllImport("kernel32", SetLastError = true)]
  55. static extern short GlobalDeleteAtom(short nAtom);
  56.  
  57. /// <summary>
  58. /// 定义了辅助键的名称(将数字转变为字符以便于记忆,也可去除此枚举而直接使用数值)
  59. /// </summary>
  60. [Flags()]
  61. public enum KeyModifiers
  62. {
  63. None = ,
  64. Alt = ,
  65. Ctrl = ,
  66. Shift = ,
  67. WindowsKey =
  68. }
  69. /// <summary>
  70. /// 热键的对应的消息ID
  71. /// </summary>
  72. public const int WM_HOTKEY = 0x312;
  73. static Dictionary<int, Action> keymap = new Dictionary<int, Action>(); //每一个key对于一个处理函数
  74.  
  75. /// <summary>
  76. /// 注册快捷键
  77. /// </summary>
  78. /// <param name="window">主体窗体</param>
  79. /// <param name="action">回调的方法</param>
  80. /// <returns>热键的标识</returns>
  81. public static void Regist(Window window, Action action)
  82. {
  83. HwndSource hWndSource;
  84. WindowInteropHelper wih = new WindowInteropHelper(window);
  85. hWndSource = HwndSource.FromHwnd(wih.Handle);
  86. //添加处理程序
  87. hWndSource.AddHook(MainWindowProc);
  88. int KeyCodes = -;
  89. if (!RegisterHotKey(wih.Handle, KeyCodes, HotKeyHelper.KeyModifiers.Ctrl, (int)Keys.S))
  90. {
  91. throw new Exception("注册失败");
  92. }
  93. else
  94. {
  95. if (keymap.Where(p => p.Key == KeyCodes).Count() > )
  96. throw new Exception("注册失败,应为这个组合键已经注册!!");
  97. else
  98. {
  99. keymap.Add(KeyCodes, action);
  100. }
  101. }
  102. }
  103. /// <summary>
  104. /// 卸载快捷键
  105. /// </summary>
  106. /// <param name="window">主体窗体</param>
  107. /// <param name="callBack">注册时回调的方法</param>
  108. public static void UnRegist(Window window, Action callBack)
  109. {
  110. foreach (KeyValuePair<int, Action> var in keymap)
  111. {
  112. WindowInteropHelper wih = new WindowInteropHelper(window);
  113. if (var.Value == callBack)
  114. {
  115. UnregisterHotKey(wih.Handle, var.Key);
  116. keymap.Remove(var.Key);
  117. return;
  118. }
  119. }
  120. }
  121.  
  122. private static IntPtr MainWindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
  123. {
  124. switch (msg)
  125. {
  126. case HotKeyHelper.WM_HOTKEY:
  127. {
  128. int sid = wParam.ToInt32();
  129. if (keymap.Where(p => p.Key == sid).Count() > )
  130. {
  131. keymap.Where(p => p.Key == sid).FirstOrDefault().Value.Invoke();
  132. }
  133. handled = true;
  134. break;
  135. }
  136. }
  137. return IntPtr.Zero;
  138. }
  139. }
  140. }

wpf程序热键的一个类的更多相关文章

  1. WPF程序只运行一个实例

    1.WPF程序在 启动窗口的构造函数执行InitializeComponent之前判断是否已经存在实例 不涉及服务器情况,可直接进行判断(不在mainwindow的构造函数中判断) // public ...

  2. 关于WPF程序只运行一个实例的方法

    找到的方法有两种: 1)http://www.cnblogs.com/liuyazhou/archive/2009/11/02/1594364.html 2)http://codereview.sta ...

  3. WPF 程序中启动和关闭外部.exe程序

    当需要在WPF程序启动时,启动另一外部程序(.exe程序)时,可以按照下面的例子来: C#后台代码如下: using System; using System.Collections.Generic; ...

  4. 如何在WPF程序中使用ArcGIS Engine的控件

    原文 http://www.gisall.com/html/47/122747-4038.html WPF(Windows Presentation Foundation)是美国微软公司推出.NET ...

  5. Oracle 远程访问配置 在 Windows Forms 和 WPF 应用中使用 FontAwesome 图标 C#反序列化XML异常:在 XML文档(0, 0)中有一个错误“缺少根元素” C#[Win32&WinCE&WM]应用程序只能运行一个实例:MutexHelper Decimal类型截取保留N位小数向上取, Decimal类型截取保留N位小数并且不进行四舍五入操作

    Oracle 远程访问配置   服务端配置 如果不想自己写,可以通过 Net Manager 来配置. 以下配置文件中的 localhost 改为 ip 地址,否则,远程不能访问. 1.网络监听配置 ...

  6. 35.按要求编写Java程序: (1)编写一个接口:InterfaceA,只含有一个方法int method(int n); (2)编写一个类:ClassA来实现接口InterfaceA,实现int method(int n)接口方 法时,要求计算1到n的和; (3)编写另一个类:ClassB来实现接口InterfaceA,实现int method(int n)接口 方法时,要求计算n的阶乘(n

      35.按要求编写Java程序: (1)编写一个接口:InterfaceA,只含有一个方法int method(int n): (2)编写一个类:ClassA来实现接口InterfaceA,实现in ...

  7. Java基础-继承-编写一个Java应用程序,设计一个汽车类Vehicle,包含的属性有车轮个数 wheels和车重weight。小车类Car是Vehicle的子类,其中包含的属性有载人数 loader。卡车类Truck是Car类的子类,其中包含的属性有载重量payload。每个 类都有构造方法和输出相关数据的方法。最后,写一个测试类来测试这些类的功 能。

    #29.编写一个Java应用程序,设计一个汽车类Vehicle,包含的属性有车轮个数 wheels和车重weight.小车类Car是Vehicle的子类,其中包含的属性有载人数 loader.卡车类T ...

  8. java基础,继承类题目:编写一个Java应用程序,该程序包括3个类:Monkey类、People类和主类 E

    21.编写一个Java应用程序,该程序包括3个类:Monkey类.People类和主类 E.要求: (1) Monkey类中有个构造方法:Monkey (String s),并且有个public vo ...

  9. 在VS中手工创建一个最简单的WPF程序

    如果不用VS的WPF项目模板,如何手工创建一个WPF程序呢?我们来模仿WPF模板,创建一个最简单的WPF程序. 第一步:文件——新建——项目——空项目,创建一个空项目. 第二步:添加引用,Presen ...

随机推荐

  1. [译] Closures in Lua - Lua中的闭包

    原文:(PDF) . 摘要 一等(first-class)函数是一种非常强大的语言结构,并且是函数式语言的基础特性.少数过程式语言由于其基于栈的实现,也支持一等函数.本文讨论了Lua 5.x用于实现一 ...

  2. emacs org mode 中的标签全参考

    把交叉的信息关联起来的最好的方式就是打标签. emacs 的 org 模式对标签的支持非常强大. 每一个标题都可以在最后包含标签列表.标签由字母.数字.'_' 和 '@' 组成.标签的前后必需有一个冒 ...

  3. 图的强连通分量-Kosaraju算法

    输入一个有向图,计算每个节点所在强连通分量的编号,输出强连通分量的个数 #include<iostream> #include<cstring> #include<vec ...

  4. phonegap android3.5.1 Crosswalk

    1. your phonegap platform for android update 3.5.1 cordova platform add android@3.5 2. download cros ...

  5. 【转】DDR3详解(以Micron MT41J128M8 1Gb DDR3 SDRAM为例)

    这两天正在学习FPGA如何控制DDR3的读写,找到一篇个人感觉比较有意义的文章,可以对DDR的内部结构有一个初步的了解.原文出处:http://blog.chinaunix.net/uid-28458 ...

  6. unity3d发布Android程序

    unity3d是一个跨平台的游戏开发引擎,可以使用c#开发各种平台上的游戏,如windows,Mac,Android,windows phone,IOS,Flash等.下面说下如何将开发好的unity ...

  7. fluentd正则表达式

    一: 匹配上则取否则不取 匹配规则为 \[sv=(?<sv>[^\]]*?)\].*?\[os=(?<os>[^\]]*?)\].*?\[net=(?<net>[^ ...

  8. abstract 和 interfaces 的用法注意事项

    abstract :  abstract class calssname{} 1.abstract也可也修饰普通的类,这样的目的是为了防止用这个类来创建对象: 2.abstract中的abstract ...

  9. java Literals

    Primitive Data Types The Java programming language is statically-typed, which means that all variabl ...

  10. jQuery通过jquery.form.js插件使用AJAX提交Form表单

    我简单使用了一下,jQuery Form插件有一下优点:  1.支持提交前验证. 2.支持提交后回调. 3.采用AJAX方式,有很好的用户体验 4.提交方式是灵活.只要指定要提交的form ID即可. ...