在Winform和WPF中注册全局快捷键实现思路及代码

 更新时间:2020年6月25日 11:43  点击:2274

快捷键辅助类

复制代码 代码如下:

class HotKey
{
/// <summary>
/// 如果函数执行成功,返回值不为0。
/// 如果函数执行失败,返回值为0。要得到扩展错误信息,调用GetLastError。.NET方法:Marshal.GetLastWin32Error()
/// </summary>
/// <param name="hWnd">要定义热键的窗口的句柄</param>
/// <param name="id">定义热键ID(不能与其它ID重复) </param>
/// <param name="fsModifiers">标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效</param>
/// <param name="vk">定义热键的内容,WinForm中可以使用Keys枚举转换,
/// WPF中Key枚举是不正确的,应该使用System.Windows.Forms.Keys枚举,或者自定义正确的枚举或int常量</param>
/// <returns></returns>
[DllImport("user32.dll", SetLastError = true)]
public static extern bool RegisterHotKey(
IntPtr hWnd,
int id,
KeyModifiers fsModifiers,
int vk
);
/// <summary>
/// 取消注册热键
/// </summary>
/// <param name="hWnd">要取消热键的窗口的句柄</param>
/// <param name="id">要取消热键的ID</param>
/// <returns></returns>
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnregisterHotKey(
IntPtr hWnd,
int id
);
/// <summary>
/// 向全局原子表添加一个字符串,并返回这个字符串的唯一标识符,成功则返回值为新创建的原子ID,失败返回0
/// </summary>
/// <param name="lpString"></param>
/// <returns></returns>
[DllImport("kernel32", SetLastError = true)]
public static extern short GlobalAddAtom(string lpString);
[DllImport("kernel32", SetLastError = true)]
public static extern short GlobalDeleteAtom(short nAtom);
/// <summary>
/// 定义了辅助键的名称(将数字转变为字符以便于记忆,也可去除此枚举而直接使用数值)
/// </summary>
[Flags()]
public enum KeyModifiers
{
None = 0,
Alt = 1,
Ctrl = 2,
Shift = 4,
WindowsKey = 8
}
/// <summary>
/// 热键的对应的消息ID
/// </summary>
public const int WM_HOTKEY = 0x312;
}

WinForm方法
在中在onload中注册事件,然后重载WndProc,对返回的消息进行处理
复制代码 代码如下:

int alts,altd;
protected override void OnLoad(EventArgs e)
{
alts= HotKey.GlobalAddAtom("Alt-S");
altd= HotKey.GlobalAddAtom("Alt-D");
HotKey.RegisterHotKey(this.Handle, alts, HotKey.KeyModifiers.Alt, (int)Keys.S);
HotKey.RegisterHotKey(this.Handle, altd, HotKey.KeyModifiers.Alt, (int)Keys.D);
}
protected override void WndProc(ref Message m)// 监视Windows消息
{
switch (m.Msg)
{
case HotKey.WM_HOTKEY:
ProcessHotkey(m);//按下热键时调用ProcessHotkey()函数
break;
}
base.WndProc(ref m); //将系统消息传递自父类的WndProc
}
private void ProcessHotkey(Message m) //按下设定的键时调用该函数
{
IntPtr id = m.WParam;//IntPtr用于表示指针或句柄的平台特定类型
int sid=id.ToInt32();
if(sid==alts)
{
MessageBox.Show("按下Alt+S");
}
else if(sid==altd)
{
MessageBox.Show("按下Alt+D");
}
}

也可以在Application使用AddMessageFilter添加处理来代替重载WndProc,可以使form自身实现IMessageFilter接口,
注册方法
复制代码 代码如下:

[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var form = new Form1();
Application.AddMessageFilter(form);
Application.Run(form);
}

实现接口
复制代码 代码如下:

bool IMessageFilter.PreFilterMessage(ref Message m)
{
const int WM_HOTKEY = 0x0312;//如果m.Msg的值为0x0312那么表示用户按下了热键
switch (m.Msg)
{
case WM_HOTKEY:
ProcessHotkey(m);//按下热键时调用ProcessHotkey()函数
break;
}
//如果筛选消息并禁止消息被调度,则为 true;如果允许消息继续到达下一个筛选器或控件,则为 false
return false ;
}

如果同时在AddMessageFilter和WndProc处理消息,顺序是先IMessageFilter,然后调用WndProc
WPF方法
WPF中的注册方法和Winform一样,只是WPF的Key枚举的值不能正确监听,要引用System.Windows.Forms.Keys或者自己定义才可以正确注册,窗口句柄也需要借助WindowInteropHelper来得到,处理函数的加入也和Winform不同,需要HwndSource来添加处理函数。
注册及处理方法
复制代码 代码如下:

int alts, altd;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
HwndSource hWndSource;
WindowInteropHelper wih = new WindowInteropHelper(this);
hWndSource = HwndSource.FromHwnd(wih.Handle);
//添加处理程序
hWndSource.AddHook(MainWindowProc);
alts = HotKey.GlobalAddAtom("Alt-S");
altd = HotKey.GlobalAddAtom("Alt-D");
HotKey.RegisterHotKey(wih.Handle, alts, HotKey.KeyModifiers.Alt, (int)System.Windows.Forms.Keys.S);
HotKey.RegisterHotKey(wih.Handle, altd, HotKey.KeyModifiers.Alt, (int)System.Windows.Forms.Keys.D);
}
private IntPtr MainWindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case HotKey.WM_HOTKEY:
{
int sid = wParam.ToInt32();
if (sid == alts)
{
MessageBox.Show("按下Alt+S");
}
else if (sid == altd)
{
MessageBox.Show("按下Alt+D");
}
handled = true;
break;
}
}
return IntPtr.Zero;
}

注意
如果注册快捷键,RegisterHotKey中的fsModifiers参数为0,即None选项,一些安全软件会警报,可能因为这样就可以全局监听键盘而造成安全问题
代码下载

[!--infotagslink--]

相关文章

  • intelliJ IDEA 多行选中相同内容的快捷键分享

    这篇文章主要介绍了intelliJ IDEA 多行选中相同内容的快捷键分享,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-06
  • c# WPF中通过双击编辑DataGrid中Cell的示例(附源码)

    这篇文章主要介绍了c# WPF中通过双击编辑DataGrid中Cell的示例(附源码),帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下...2021-03-03
  • C#实现快捷键的几种常用方法汇总

    这篇文章主要介绍了C#实现快捷键的几种常用方法,非常实用,需要的朋友可以参考下...2020-06-25
  • C# WinForm快捷键设置技巧

    这篇文章主要给大家介绍C# winform快捷键设置技巧,涉及到C winform快捷键相关知识,对C winform知识感兴趣的朋友可以参考下本篇文章...2020-06-25
  • WPF实现类似360安全卫士界面的程序源码分享

    最近在网上看到了新版的360安全卫士,感觉界面还不错,于是用WPF制作了一个,时间有限,一些具体的控件没有制作,用图片代替了。感兴趣的朋友一起跟着小编学习WPF实现类似360安全卫士界面的程序源码分享...2020-06-25
  • vue+axios全局添加请求头和参数操作

    这篇文章主要介绍了vue+axios全局添加请求头和参数操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-24
  • vue设置全局访问接口API地址操作

    这篇文章主要介绍了vue设置全局访问接口API地址操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-14
  • R语言-使用快捷键快速注释的实现

    这篇文章主要介绍了R语言-使用快捷键快速注释的实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-05-06
  • 配置vue全局方法的两种方式实例

    vue项目中有一些方法需要在多个页面调用,但为了避免在每个页面都import进来,可以把方法加到原型上去,这样在每个组件中都能使用了,下面这篇文章主要给大家介绍了关于配置vue全局方法的两种方式,需要的朋友可以参考下...2021-09-13
  • WPF仿三星手机充电界面实现代码

    这篇文章主要为大家详细介绍了WPF仿三星手机充电界面实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • C# WPF 通过委托实现多窗口间的传值的方法

    这篇文章主要介绍了C# WPF 通过委托实现多窗口间的传值的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • pycharm 多行批量缩进和反向缩进快捷键介绍

    这篇文章主要介绍了pycharm 多行批量缩进和反向缩进快捷键介绍,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-16
  • JS中正则表达式全局匹配模式 /g用法详解

    本文章通过实例代码给大家详细介绍js中正则表达式的全局匹配模式 g的用法,需要的朋友参考下...2017-04-03
  • Delphi编程常用快捷键大全

    这篇文章主要介绍了Delphi编程常用快捷键,对于提高Delphi编程的效率很有帮助,需要的朋友可以参考下...2020-06-30
  • VS2019使用快捷键将代码对齐的方法

    这篇文章主要介绍了VS2019使用快捷键将代码对齐的相关资料,非常不错对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • WPF TextBox实现按字节长度限制输入功能

    这篇文章主要为大家详细介绍了WPF TextBox实现按字节长度限制输入功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • C#中WPF使用多线程调用窗体组件的方法

    这篇文章主要介绍了C#中WPF使用多线程调用窗体组件的方法,涉及C#中多线程的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • 深入分析为Visual Assist设置快捷键的方法

    本篇文章是对为Visual Assist设置快捷键的方法进行了详细的分析介绍,需要的朋友参考下...2020-04-25
  • WPF InkCanvas绘制矩形和椭圆

    这篇文章主要为大家详细介绍了WPF InkCanvas绘制矩形和椭圆,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Postman环境变量全局变量使用方法详解

    这篇文章主要介绍了Postman环境变量全局变量使用方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-08-13