一、前言
一般来说,在使用键盘事件的时候,如果qt界面隐藏最小化或者不在顶层不是聚焦状态了,在按键盘就没有反应了,但是有的时候想在任何情况都要能通过键盘控制程序,所以本文的宗旨就是分享如何全局接收键盘事件。
二、环境
qt5.7 win8
三、正文
话不多说,先上程序,在pro目录下添加一个keypad文件夹,这个位置具体要放在哪里,还是根据个人习惯来定,反正这里加的代码后期也不需要整改。
文件夹内有capturer.h capturer.cpp keymonitor.h keymonitor.cpp
capturer.h
#ifndef CAPTURER_H
#define CAPTURER_H
#include <QObject>
/*捕获器*/
class KeyCapturer: public QObject
{
Q_OBJECT
public:
virtual ~KeyCapturer();
static KeyCapturer*& instance()
{
static KeyCapturer *s = nullptr;
if (s == nullptr)
{
s = new KeyCapturer();
}
return s;
}
public:
void setkeyValue(int key);
protected:
KeyCapturer();
signals:
void getKey(int);
private:
};
#endif // CAPTURER_H
capturer.cpp
#include "keypad/capturer.h"
KeyCapturer::KeyCapturer()
{
}
KeyCapturer::~KeyCapturer()
{
}
void KeyCapturer::setkeyValue(int key)
{
emit getKey(key);
}
keymonitor.h
#ifndef KEYMONITOR_H
#define KEYMONITOR_H
#include <Windows.h>
#include <DbgHelp.h>
int startHook();
bool stopHook();
#endif // KEYMONITOR_H
keymonitor.cpp
#include "keypad/keymonitor.h"
#include "keypad/capturer.h"
#include <QtDebug>
LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam);
HMODULE WINAPI ModuleFromAddress(PVOID pv);
static HHOOK hHook;
LRESULT KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
KBDLLHOOKSTRUCT *Key_Info = (KBDLLHOOKSTRUCT*)lParam;
if (HC_ACTION == nCode)
{
if (WM_KEYDOWN == wParam || WM_SYSKEYDOWN == wParam) //如果按键为按下状态
{
if (Key_Info->vkCode <= 107 && Key_Info->vkCode >= 65)
{
qDebug() << Key_Info->vkCode;
if (KeyCapturer::instance())
{
KeyCapturer::instance()->setkeyValue(Key_Info->vkCode);
}
}
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
HMODULE ModuleFromAddress(PVOID pv)
{
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery(pv, &mbi, sizeof(mbi)) != 0) {
return (HMODULE)mbi.AllocationBase;
} else {
return NULL;
}
}
int startHook()
{
hHook = SetWindowsHookExW(WH_KEYBOARD_LL, KeyboardHookProc, ModuleFromAddress((PVOID)KeyboardHookProc), 0);
int error = GetLastError();
return error;
}
bool stopHook()
{
return UnhookWindowsHookEx(hHook);
}
然后在mainwindow.h中加入
#include "keypad/keymonitor.h"
#include "keypad/capturer.h"
在mainwindow.cpp中加入
connect( KeyCapturer::instance(), &KeyCapturer::getKey, [=](int key){
qDebug()<<QString::number(key);
});
startHook();
当然这个键盘监听事件也是可以关闭的
通过stopHook()这个函数即可。
2020年3月13日11:19:03更新
上面程序只是获取字母和小键盘的按键回调,如果想获取更多,如大键盘的数字和F1-F12等,将keymonitor.cpp内的107换成大一些即可。
方式二:使用qhotkey类
将开源代码放入到程序路径,并引入程序调用
调用方法,有两种方式传入检测的热键参数
QHotkey *hotkey=new QHotkey(QKeySequence("Ctrl+Shift+A"),true);
//QHotkey *hotkey=new QHotkey(Qt::Key_L,Qt::ControlModifier,true);
//连接热键被按下的信号与槽
QObject::connect(hotkey,&QHotkey::activated,[=](){
//热键被按下的处理代码段
ui->btn_menu_1->click();//执行截图功能
});
四、结语
qt监听全局键盘事件