基于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 类,它负责全局键盘和鼠标事件的捕获。

cpp 复制代码
#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 区分不同的按键和鼠标键。
cpp 复制代码
#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 类,主要负责接收事件信号并显示。

cpp 复制代码
#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 的实现包括系统托盘、事件显示和键码翻译逻辑。

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

项目运行

  • 运行后,主窗口会捕获并显示键盘和鼠标事件,支持托盘最小化,并且能够通过系统托盘图标显示或退出。
  • 应用场景:适用于事件监控、快捷键监控等场景。
相关推荐
rfidunion6 小时前
QT5.7.0编译移植
开发语言·qt
微露清风6 小时前
系统性学习C++-第十八讲-封装红黑树实现myset与mymap
java·c++·学习
hqwest6 小时前
码上通QT实战08--导航按钮切换界面
开发语言·qt·slot·信号与槽·connect·signals·emit
CSARImage7 小时前
C++读取exe程序标准输出
c++
一只小bit7 小时前
Qt 常用控件详解:按钮类 / 显示类 / 输入类属性、信号与实战示例
前端·c++·qt·gui
一条大祥脚7 小时前
26.1.9 轮廓线dp 状压最短路 构造
数据结构·c++·算法
项目題供诗8 小时前
C语言基础(一)
c++
@areok@8 小时前
C++opencv图片(mat)传入C#bitmap图片
开发语言·c++·opencv
鸽芷咕8 小时前
【2025年度总结】时光知味,三载同行:落笔皆是沉淀,前行自有光芒
linux·c++·人工智能·2025年度总结
羑悻的小杀马特8 小时前
指尖敲代码,笔尖写成长:2025年度总结与那些没说出口的碎碎念
linux·c++·博客之星·2025年度总结