基于Qt/C++全局键盘和鼠标事件监控工具

项目介绍:

该项目实现了一个基于 Qt 框架的全局键盘和鼠标事件监控工具,主要功能包括:

  1. 实时监控全局键盘事件:捕获并显示所有键盘按键,并将按键的虚拟键码转为键名显示。
  2. 实时监控全局鼠标事件:捕获并显示鼠标左键、右键和中键点击事件及其位置。
  3. 系统托盘功能:主窗口可以最小化到系统托盘,提供了“显示”和“退出”功能。
  4. 事件显示:所有捕获的事件信息都会实时显示在主窗口的 plainTextEdit 中。

在这里插入图片描述
在这里插入图片描述

主要文件

  • mainwindow.hmainwindow.cpp:定义和实现主窗口类 MainWindow,用于显示捕获的事件信息和控制程序的主界面。
  • mhook.hmhook.cpp:定义和实现全局键盘和鼠标钩子类 MyHook,实现事件的捕获、区分、翻译和信号传递。

功能分解

  1. 全局钩子捕获事件:利用 Windows API 实现键盘和鼠标钩子,通过 MyHook 类进行封装,捕获系统中的键盘和鼠标事件。
  2. 信号槽机制:键盘和鼠标事件捕获后,通过 Qt 信号槽机制传递到 MainWindow,从而在 plainTextEdit 中显示。
  3. 托盘图标管理:托盘图标和菜单使得程序可以在系统托盘中最小化和恢复显示。
  4. 键码翻译:使用键码转换函数 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 的实现中包含键盘和鼠标钩子的安装、卸载、事件捕获及信号发送逻辑。

关键代码解释
  1. 单例模式instance 方法创建并返回唯一的 MyHook 实例。
  2. 钩子安装和卸载installHookunInstallHook 方法调用 Windows API SetWindowsHookExUnhookWindowsHookEx 实现钩子的安装和卸载。
  3. 键盘和鼠标事件捕获:定义 keyProcmouseProc 回调函数,通过 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_OBJECTpublic: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 的实现包括系统托盘、事件显示和键码翻译逻辑。

关键代码解释
  1. 系统托盘initTrayIcon 方法初始化系统托盘图标和菜单。
  2. 键盘事件槽onKeyEventReceived 将键码翻译并显示到 plainTextEdit
  3. 鼠标事件槽onMouseEventReceived 显示鼠标按键和位置。
  4. 键码翻译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);}
}

项目运行

  • 运行后,主窗口会捕获并显示键盘和鼠标事件,支持托盘最小化,并且能够通过系统托盘图标显示或退出。
  • 应用场景:适用于事件监控、快捷键监控等场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/470189.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为数通HCIA系列第5次考试-【2024-46周-周一】

文章目录 1、子网掩码有什么作用&#xff0c;和IP地址是什么关系&#xff0c;利用子网掩码可以获取哪些信息&#xff1f;2、已知一个IP地址是192.168.1.1&#xff0c;子网掩码是255.255.255.0&#xff0c;求其网络地址3、已知某主机的IP地址是192.168.100.200&#xff0c;子网掩…

arkUI:遍历数据数组动态渲染(forEach)

arkUI&#xff1a;遍历数据数组动态渲染&#xff08;forEach&#xff09; 1 主要内容说明2 相关内容2.1 ForEach 的基本语法2.2 简单遍历数组2.2 多维数组遍历2.4 使用唯一键2.5 源码1的相关说明2.5.1 源码1 &#xff08;遍历数据数组动态渲染&#xff09;2.5.2 源码1运行效果 …

Ue5 umg学习(一)

学习视频资料链接 2、UI编辑界面_哔哩哔哩_bilibili 打开ue5虚幻引擎 创建新的文件夹UI&#xff0c;在这个文件夹里写东西 点击停靠在布局中 双击点进UI文件夹 右键用户界面&#xff0c;选择控件蓝图 创建控件蓝图&#xff0c;重命名&#xff0c;在名称后面加一个_BP1代表是…

PYNQ 框架 - 中断(INTR)驱动

目录 1. 简介 2. 分析 2.1 Block Design 2.2 AXI Timer 2.2.1 IP 基本信息 2.2.2 IP 地址空间 2.2.3 级联模式 2.2.4 生成/捕获模式 2.3 AXI Interrupt 2.3.1 IP 基本信息 2.3.2 IP 地址空间 2.3.3 相关概念 2.3.4 参数配置 2.3.5 中断确认寄存器 3. PYNQ 代码 …

RAG综述:《A Comprehensive Survey of Retrieval-Augmented Generation (RAG)》

来源于《A Comprehensive Survey of Retrieval-Augmented Generation (RAG): Evolution, Current Landscape and Future Directions》 一、RAG所解决的问题 如何有效地从外部知识源检索相关信息&#xff0c;如何将这些信息无缝地融入到生成文本中&#xff0c;以及如何在保证生…

GitLab 如何跨版本升级?

本分分享 GitLab 跨版本升级的一些注意事项。 众所周知&#xff0c;GitLab 的升级必须要严格遵循升级路径&#xff0c;否则就会出现问题&#xff0c;导致升级失败。因此&#xff0c;在 GitLab 升级之前需要做好两件事情&#xff1a; 当前版本的确认升级路径的确认 极狐GitLa…

aws(学习笔记第十二课) 使用AWS的RDS-MySQL

aws(学习笔记第十二课) 使用AWS的RDS 学习内容&#xff1a; AWS的RDS-MySQL 1. 使用AWS的RDS 什么是RDS RDS就是Relation Database Service的缩写&#xff0c;是AWS提供的托管关系型数据库系统。让用户能够在 AWS Cloud 云中更轻松地设置、操作和扩展关系数据库。 数据库和we…

云原生-docker安装与基础操作

一、云原生 Docker 介绍 Docker 在云原生中的优势 二、docker的安装 三、docker的基础命令 1. docker pull&#xff08;拉取镜像&#xff09; 2. docker images&#xff08;查看本地镜像&#xff09; 3. docker run&#xff08;创建并启动容器&#xff09; 4. docker ps…

Spark 核心概念与宽窄依赖的详细解析

Spark 的介绍与搭建&#xff1a;从理论到实践_spark环境搭建-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交&#xff1a;本地与集群模式全解析-CSDN博客 Spark on YARN&#xff1a;Spark集群模式…

【css】html里面的图片宽度设为百分比,高度要与宽度一样

场景&#xff1a;展示图片列表的时候&#xff0c;原始图片宽高不一致。 外层div的宽度自适应&#xff0c;图片宽度不能固定数值&#xff0c;只能设置百分比。图片高度也不能设置固定数值。 如何让图片的高度与图片的宽度一样呢&#xff1f; html代码 &#xff1a; <div cl…

c#使用COM接口设置excel单元格宽高匹配图片,如何计算?

c#使用COM接口设置excel单元格宽高如何换算 在实际工作中&#xff0c;经常需要在excel中插入图片。并设置单元格与图片对齐。但是excel单元格的宽度和高度使用不同的单位。单元格的宽度以字符宽度为单位&#xff0c;而高度以点为单位。如果按照实际值来设置&#xff0c;例如设…

RHCE web解析、dns配置、firewalld配置实验

RHCE web解析、dns配置、firewalld配置实验 实验一1.清理软件包2.安装软件包3.配置web服务查看默认测试页面报错讲解12 4.安装DNS解析需要的bind软件包5.修改网络配置&#xff0c;查错&#xff0c;修改权限 实验二配置文件haha.confnamed.confnamed.haha 实验一 1、学习方法 重…

JavaEE进阶----SpringMVC(三)---响应的获取

文章目录 1.cookie和session获取1.1servlet写法获取1.2spring获取cookie1.3传统方法获取session1.4sring获取session内容 2.访问静态页面3.一个项目部署多个服务4.responsebody的介绍5.返回html的片段6.不同相应content-type类型6.1text/html类型6.2application-json类型6.3 js…

Chromium 中MemoryMappedFile使用例子c++

文件映射基础介绍参考微软官网&#xff1a; 使用文件映射 - Win32 apps | Microsoft Learn 在文件中创建视图 - Win32 apps | Microsoft Learn 创建命名的共享内存 - Win32 apps | Microsoft Learn 使用大页面创建文件映射 - Win32 apps | Microsoft Learn 从文件句柄获取…

OpenHarmony4.1蓝牙芯片如何适配?触觉智能RK3568主板SBC3568演示

当打开蓝牙后没有反应时&#xff0c;需要排查蓝牙节点是否对应、固件是否加载成功&#xff0c;本文介绍开源鸿蒙OpenHarmony4.1系统下适配蓝牙的方法&#xff0c;触觉智能SBC3568主板演示 修改对应节点 开发板蓝牙硬件连接为UART1&#xff0c;修改对应的节点&#xff0c;路径为…

前端 JS面向对象 原型 prototype

目录 一、问题引出 二、prototype原型对象 三、小结 四、constructor 五、__proto__对象原型 六、原型链 一、问题引出 由于JS的构造函数存在内存浪费问题&#xff1a; function Star(name,age){this.namenamethis.ageagethis.singfunction () {console.log("唱歌&…

生成 Django 中文文档 PDF 版

文章目录 背景克隆 Django 文档和翻译仓库配置 conf.py设置和同步翻译生成 .pot 文件运行 sphinx-intl update复制翻译文件 构建 PDF生成 tex 文件安装 MikTeX生成 PDF Sphinx 生成文档 背景 浏览看到一个帖子&#xff0c;有个评论说可以用 sphinx 构建一个 pdf&#xff0c;正…

mysql 实现分库分表之 --- 基于 MyCAT 的分片策略详解

引言 在我们日常工作的项目中&#xff0c;特别是面向 C 端用户的产品&#xff0c;随着业务量的逐步扩大&#xff0c;数据量也呈指数级增长。为了应对日益增长的数据库压力&#xff0c;数据库优化已成为项目中不可或缺的一环&#xff0c;而分库分表则是海量数据优化方案中的重要…

JUC-locks锁

JUC-locks锁 1、JUC-locks锁概述2、管程模型3、ReentrantLock可重入锁3.1 ReentrantLock源码3.2 Sync静态内部类3.3 NonfairSync非公平锁3.4 FairSync公平锁 如有侵权&#xff0c;请联系&#xff5e; 如有错误&#xff0c;也欢迎批评指正&#xff5e; 1、JUC-locks锁概述 java…

GEE 数据集——美国gNATSGO(网格化国家土壤调查地理数据库)完整覆盖了美国所有地区和岛屿领土的最佳可用土壤信息

目录 简介 代码 引用 网址推荐 知识星球 机器学习 gNATSGO&#xff08;网格化国家土壤调查地理数据库&#xff09; 简介 gNATSGO&#xff08;网格化国家土壤调查地理数据库&#xff09;数据库是一个综合数据库&#xff0c;完整覆盖了美国所有地区和岛屿领土的最佳可用土…