【前言】
最近在写一个软件的时候需要用到全局热键的方法,Qt的keyPressEvent()函数只能在窗口获得焦点的时候起作用,如果想要设置全局热键应该怎么做呢。
花很多时间在网上查了不少资料,确实找到了一些方法,但当我自己试验的时候要么是程序崩溃了,要么是没有效果,不知道是什么地方出了问题。最后我将各种方法整合了一下,查了一个Qt的帮助文档,终于成功实现了,纯属误打误撞。以下的想法和代码仅仅是我个人在本次查阅资料之后的思考,而在此之前并没有接触此类知识,难免会有一些错误,请大家批评指正。
【代码分析】
-
#include <Windows.h>头文件
并且,在.pro文件中加上 LIBS +=User32.LIB,否则无效。 -
在系统中注册一个热键。
用BOOL RegisterHotKey(HWND hWnd,int id,UINT fsModifiers,UINT vk)函数,成功注册返回true,失败返回false。
第一个参数是窗口句柄,可用this->winId()函数获得。
第二个参数是热键的唯一标识符,系统通过标识符判断是哪个热键,新注册的标识符不可以与之前热键的标识一样。我们用ATOM GlobalAddAtom(In LPCTSTR lpString)函数可以获得一个基于string参数的唯一标识符。另外,在程序结束之前,务必记得再用ATOM GlobalDeleteAtom( ATOM nAtom);函数将获得的ATOM删去。
第三个参数是修饰按键,第四个键是键值。例如想设置热键ctrl+Q,第三个参数填MOD_CONTROL,第四个参数填‘Q’,或者VK_Q。Alt键为MOD_ALT。这两个参数对应的热键可自行查表。
我这儿以ctrl+Q为例:
RegisterHotKey(HWND(this->winId()),id,MOD_CONTROL,‘Q’);
第三个参数:
第四个参数:VK键值 -
热键注册后,在程序结束前,务必记得注销,否则该热键会一直被占用。
BOOL UnregisterHotKey(HWND hWnd, int id);使用此函数,注销成功返回true,否则返回false。hWnd还是this->winId(),id就是之前获取的ATOM。 -
热键注册、注销都已经有了,现在需要判断热键是否按下。
使用bool nativeEvent(const QByteArray &eventType, void *message, long *result)函数来接收系统消息,这个函数需要自己实现。这一段直接放代码吧。
if(eventType == "windows_generic_MSG")
{
MSG* pMsg = reinterpret_cast<MSG*>(message);
if(pMsg->message == WM_HOTKEY)
{
if(pMsg->wParam == id)
ui->messageLabel->setText("已按下ctrl+Q");
}
}
return QWidget::nativeEvent(eventType,message,result);
MSG是windows中的一个结构体,大家可以百度一下。
成员message存储了消息类型,WM_HOTKEY代表热键类型。成员wParam存储了附加消息,这里是我们的热键标识符。
这样全局热键的注册、注销和使用就已经完成了,亲测可用。
【PS】
哇写这个花了我挺长时间的,本来这些时间能用来写代码的, 希望能帮助到大家。
如果大家有什么疑问或者想与我交流,可以加我的QQ634622697联系我。