基于Qt/C++全局键盘和鼠标事件监控工具
创作时间:
作者:
@小白创作中心
基于Qt/C++全局键盘和鼠标事件监控工具
引用
CSDN
1.
https://blog.csdn.net/chenai886/article/details/143642146
项目介绍:
该项目实现了一个基于 Qt 框架的全局键盘和鼠标事件监控工具,主要功能包括:
- 实时监控全局键盘事件 :捕获并显示所有键盘按键,并将按键的虚拟键码转为键名显示。
- 实时监控全局鼠标事件 :捕获并显示鼠标左键、右键和中键点击事件及其位置。
- 系统托盘功能 :主窗口可以最小化到系统托盘,提供了“显示”和“退出”功能。
- 事件显示 :所有捕获的事件信息都会实时显示在主窗口的
plainTextEdit中。
主要文件
mainwindow.h和mainwindow.cpp:定义和实现主窗口类MainWindow,用于显示捕获的事件信息和控制程序的主界面。mhook.h和mhook.cpp:定义和实现全局键盘和鼠标钩子类MyHook,实现事件的捕获、区分、翻译和信号传递。
功能分解
- 全局钩子捕获事件 :利用 Windows API 实现键盘和鼠标钩子,通过
MyHook类进行封装,捕获系统中的键盘和鼠标事件。 - 信号槽机制 :键盘和鼠标事件捕获后,通过 Qt 信号槽机制传递到
MainWindow,从而在plainTextEdit中显示。 - 托盘图标管理 :托盘图标和菜单使得程序可以在系统托盘中最小化和恢复显示。
- 键码翻译 :使用键码转换函数
translateKey将虚拟键码转换为键名,方便用户阅读。
文件和代码讲解
mhook.h:钩子类定义
此头文件定义了 MyHook 类,它负责全局键盘和鼠标事件的捕获。
#ifndef MHOOK_H
#define MHOOK_H
#include <Windows.h>
#include <QObject>
#include <QMessageBox>
#include <QDebug>
// 用于中文字符显示的宏定义
#define tc(a) QString::fromLocal8Bit(a)
// 钩子类 MyHook 定义
class MyHook : public QObject
{
Q_OBJECT
public:
// 定义捕获模式的枚举
enum Model
{
eNull = 0, // 空模式,不捕获
eKey = 1, // 键盘钩子模式
eMouse = 2, // 鼠标钩子模式
eMouseKey = 3 // 键盘和鼠标钩子模式
} mModel;
// 单例模式:获得唯一实例
static MyHook* instance();
// 安装和卸载钩子函数
void installHook(Model model);
void unInstallHook(Model model);
private:
MyHook(); // 私有构造函数
void showError(const QString& message); // 异常提示方法
signals:
void keyEventReceived(int vkCode); // 键盘事件信号
void mouseEventReceived(int x, int y, QString button); // 鼠标事件信号,增加按钮信息
};
#endif // MHOOK_H
mhook.cpp:钩子类实现
MyHook 的实现中包含键盘和鼠标钩子的安装、卸载、事件捕获及信号发送逻辑。
关键代码解释
- 单例模式 :
instance方法创建并返回唯一的MyHook实例。 - 钩子安装和卸载 :
installHook和unInstallHook方法调用 Windows APISetWindowsHookEx和UnhookWindowsHookEx实现钩子的安装和卸载。 - 键盘和鼠标事件捕获 :定义
keyProc和mouseProc回调函数,通过WPARAM区分不同的按键和鼠标键。
#include "mhook.h"
// 静态变量定义
static HHOOK keyHook = nullptr, mouseHook = nullptr;
static MyHook* hookClass = nullptr;
// 键盘钩子处理函数
LRESULT CALLBACK keyProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (!hookClass)
return CallNextHookEx(keyHook, nCode, wParam, lParam);
if (wParam == WM_KEYDOWN) // 键盘按下事件
{
KBDLLHOOKSTRUCT* pkbhs = (KBDLLHOOKSTRUCT*)lParam;
// 触发信号传递键码
emit hookClass->keyEventReceived(pkbhs->vkCode);
}
return CallNextHookEx(keyHook, nCode, wParam, lParam); // 继续传递事件队列
}
// 鼠标钩子处理函数
LRESULT CALLBACK mouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (!hookClass)
return CallNextHookEx(mouseHook, nCode, wParam, lParam);
MOUSEHOOKSTRUCT* mhookstruct = (MOUSEHOOKSTRUCT*)lParam;
POINT pt = mhookstruct->pt; // 获取鼠标坐标
// 根据 WPARAM 区分鼠标键类型
if (wParam == WM_LBUTTONDOWN)
emit hookClass->mouseEventReceived(pt.x, pt.y, tc("左键"));
else if (wParam == WM_RBUTTONDOWN)
emit hookClass->mouseEventReceived(pt.x, pt.y, tc("右键"));
else if (wParam == WM_MBUTTONDOWN)
emit hookClass->mouseEventReceived(pt.x, pt.y, tc("中键"));
return CallNextHookEx(mouseHook, nCode, wParam, lParam); // 继续传递事件队列
}
mainwindow.h:主窗口类定义
定义 MainWindow 类,主要负责接收事件信号并显示。
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSystemTrayIcon>
#include "mhook.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
void closeEvent(QCloseEvent *event) override; // 重写关闭事件
private slots:
void onKeyEventReceived(int vkCode); // 键盘事件处理槽
void onMouseEventReceived(int x, int y, QString button); // 鼠标事件处理槽
void showMainWindow(); // 显示主窗口
void exitApplication(); // 退出应用程序
private:
QSystemTrayIcon *trayIcon;
QMenu *trayMenu;
QString translateKey(int vkCode); // 键码翻译函数
void initTrayIcon(); // 初始化系统托盘
};
#endif // MAINWINDOW_H
mainwindow.cpp:主窗口类实现
MainWindow 的实现包括系统托盘、事件显示和键码翻译逻辑。
关键代码解释
- 系统托盘 :
initTrayIcon方法初始化系统托盘图标和菜单。 - 键盘事件槽 :
onKeyEventReceived将键码翻译并显示到plainTextEdit。 - 鼠标事件槽 :
onMouseEventReceived显示鼠标按键和位置。 - 键码翻译 :
translateKey将键码转换为易读的按键名称。
#include "mainwindow.h"
#include <QCloseEvent>
#include <QMenu>
// 构造函数
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), trayIcon(new QSystemTrayIcon(this)), trayMenu(new QMenu(this))
{
ui->setupUi(this);
// 初始化系统托盘
initTrayIcon();
// 连接钩子类的信号到槽函数
MyHook *hook = MyHook::instance();
connect(hook, &MyHook::keyEventReceived, this, &MainWindow::onKeyEventReceived);
connect(hook, &MyHook::mouseEventReceived, this, &MainWindow::onMouseEventReceived);
// 安装键盘和鼠标钩子
hook->installHook(MyHook::eMouseKey);
}
// 键盘事件槽函数
void MainWindow::onKeyEventReceived(int vkCode)
{
QString keyName = translateKey(vkCode);
ui->plainTextEdit->appendPlainText(tc("键盘事件: 按键 - ") + keyName);
}
// 鼠标事件槽函数
void MainWindow::onMouseEventReceived(int x, int y, QString button)
{
ui->plainTextEdit->appendPlainText(tc("鼠标事件: ") + button + tc("点击位置 (") + QString::number(x) + ", " + QString::number(y) + ")");
}
// 键码翻译函数
QString MainWindow::translateKey(int vkCode)
{
switch (vkCode)
{
case 0x41: return "A";
case 0x42: return "B";
case VK_RETURN: return tc("回车");
case VK_SPACE: return tc("空格");
// 完整键码翻译略
default: return QString("0x%1").arg(vkCode, 0, 16);
}
}
项目运行
- 运行后,主窗口会捕获并显示键盘和鼠标事件,支持托盘最小化,并且能够通过系统托盘图标显示或退出。
- 应用场景 :适用于事件监控、快捷键监控等场景。
热门推荐
跨越半个世纪的守望:村上春树与阳子的爱情故事
25元畅游世界最大玛珥湖!湛江湖光岩周末游全攻略
秋冬换季,南京人如何预防过敏性结膜炎?
浙二眼科中心教你防过敏性结膜炎
过敏性结膜炎患者的饮食禁忌:远离辣酒肉!
重庆冬季自驾游必备用车知识
张大大风波牵连杨幂!为难打工人被群嘲,身边好友都塌房了
贾瑞病情背后,《红楼》隐藏的秘密
贾瑞之死:《红楼梦》中的古代医疗困境
贾瑞之死:《红楼梦》中的欲望与道德之殇
中山五院刘洋主任:过敏性结膜炎的预防与治疗全攻略
秋冬护眼有妙招:合理膳食预防过敏性结膜炎
武汉普瑞眼科提醒:过敏性结膜炎高发季,这些预防措施请收好
家庭聚会上一起做茶叶蛋有多好玩?
秋冬养生新宠:茶叶蛋的隐藏好处
直行道右拐扣几分
宋晓峰蒋诗萌:一对让观众笑到肚子疼的喜剧搭档
辽视春晚《天地寒 人心暖》:宋晓峰杨树林文松演绎寒冬暖心故事
2025辽视春晚节目单出炉:宋小宝压轴,德云社跨界小品成亮点
贾冰小品爆笑全场:辽视春晚再创收视高峰
英文论文写作中常犯的标点符号错误及正确使用规范介绍
深入探讨句号的功能与使用技巧,提升中文写作表达
掌握分号使用技巧,提升写作表达与逻辑清晰度
约克夏梗萌宠养成记:从喂养到训练全攻略
吃蘑菇真的能抗抑郁吗?宾夕法尼亚州立大学研究揭示惊人真相
最新研究:香菇多糖或成对抗阿尔茨海默病和帕金森病的新希望
秋冬食用菌保鲜小妙招
冬季养生新宠:白参菌与银耳大比拼
家庭用春联:选好尺寸迎新年
北京中医药大学东直门医院专家推荐:便秘患者饮食指南