欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-12-12 20:11:46
快捷键辅助类 复制代码 代码如下: class hotkey { /// /// 如果函数执行成功,返回值不为0。 /// 如果函数执行失败...

快捷键辅助类

复制代码 代码如下:

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选项,一些安全软件会警报,可能因为这样就可以全局监听键盘而造成安全问题
代码下载

上一篇:

下一篇: