在Winform和WPF中注册全局快捷键实现思路及代码
- 作者: 亖呉?盀
- 来源: 51数据库
- 2021-08-13
快捷键辅助类
复制代码 代码如下:
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选项,一些安全软件会警报,可能因为这样就可以全局监听键盘而造成安全问题
代码下载
推荐阅读
- C#通过fleck实现wss协议的WebSocket多人Web实时聊天(附源码)
- 团队城市未满足要求:MSBuildTools12.0_x86_Path 存在
- 使用 MSBuild.exe 在发布模式下构建 C# 解决方案
- 当我发布 Web 应用程序时,AfterPublish 脚本不运行
- 构建时 T4 转换的产品仅在下一个构建中使用
- ASP.NET Core Application (.NET Framework) for Windows x64 only error in project.assets.json
- 新的 .csproj 格式 - 如何将整个目录指定为“链接文件"到子目录?
- 如何将条件编译符号(DefineConstants)传递给 msbuild
- MSBuild 支持 Visual Studio 2017 RTM 中的 T4 模板
- NuGet 包还原找不到包,没有源
热点文章
团队城市未满足要求:MSBuildTools12.0_x86_Path 存在
0
使用 MSBuild.exe 在发布模式下构建 C# 解决方案
0
当我发布 Web 应用程序时,AfterPublish 脚本不运行
0
构建时 T4 转换的产品仅在下一个构建中使用
0
ASP.NET Core Application (.NET Framework) for Windows x64 only error in project.assets.json
0
新的 .csproj 格式 - 如何将整个目录指定为“链接文件"到子目录?
0
如何将条件编译符号(DefineConstants)传递给 msbuild
0
MSBuild 支持 Visual Studio 2017 RTM 中的 T4 模板
0
NuGet 包还原找不到包,没有源
0
使用 C# 6.0 功能运行 TFS 构建
0
