C++ Qt 窗口消息钩子 | 键盘鼠标数据获取 | 代码示例

本示例演示如何使用 C++ Qt 框架实现窗口消息钩子,并获取键盘和鼠标数据。

头文件 (mainwindow.h)

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFileDialog>
#include <QFile>
#include <QMessageBox>
#include <QTextCodec>
#include <QFileInfo>
#include 'lanrenapi.h'

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    static WNDPROC lpPrevWndFunc;
    //自动判断编码格式
    QString GetCorrectUnicode(const QByteArray &ba);
    void clicked_bt_load(bool clicked);
    void clicked_bt_save(bool clicked);
    void clicked_bt_save_as(bool clicked);
    void clicked_bt_replace(bool clicked);
    static APIENTRY func_Message(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
private:
    Ui::MainWindow *ui;
    HWND hwnd;

};

#endif // MAINWINDOW_H

源文件 (mainwindow.cpp)

#include "mainwindow.h"
#include "ui_mainwindow.h"

// 定义 lpPrevWndFunc 变量
WNDPROC MainWindow::lpPrevWndFunc = nullptr;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{

    ui->setupUi(this);
    //设置窗口透明度:
    this->setWindowOpacity(0.8);
    connect(ui->bt_load,&QPushButton::clicked,this,&clicked_bt_load);
    connect(ui->bt_save,&QPushButton::clicked,this,&clicked_bt_save);
    connect(ui->bt_save_as,&QPushButton::clicked,this,&clicked_bt_save_as);
    connect(ui->bt_replace,&QPushButton::clicked,this,&clicked_bt_replace);
    //获取窗口的句柄
    HWND hwnd=(HWND)(this->winId());
    //hook原始输入数据 键盘
    if (lanrenAPI::hookRawInputData(hwnd,HID_USAGE_GENERIC_KEYBOARD)==0){

        QMessageBox::information(this,"错误!","创建原始键盘数据设备!");
    }
    //hook原始输入数据 鼠标
    if (lanrenAPI::hookRawInputData(hwnd,HID_USAGE_GENERIC_MOUSE)==0){
     QMessageBox::information(this,"错误!","创建原始鼠标数据设备!");
    }


    //建立消息机制,收到数据会通知
    lpPrevWndFunc=(WNDPROC)SetWindowLongPtr(hwnd,GWLP_WNDPROC,(LONG_PTR)&func_Message);

    qDebug()<<lpPrevWndFunc;

}
MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::clicked_bt_load(bool clicked){

    QString fileName= QFileDialog::getOpenFileName(this,"导入脚本","C:\Users\Administrator",tr("TEXT (*.txt)"));


    //读取内容  放到textEdit中
    //默认编码格式是 utf-8
    QFile file(fileName);
    //设置打开方式
    file.open(QIODeviceBase::ReadOnly);

     while(!file.atEnd()){
         QByteArray array= file.readLine();
         QTextCodec * codec=QTextCodec::codecForName(GetCorrectUnicode(array).toLatin1());

         ui->pte_jb->moveCursor(QTextCursor::End);
         ui->pte_jb->insertPlainText(codec->toUnicode(array));
     }
     //关闭文件
     file.close();

     ui->cb_history->addItem(fileName);
}
void MainWindow::clicked_bt_save(bool clicked){

    QString  str=ui->pte_jb->toPlainText();
    char*  ch;
    QByteArray ba = str.toUtf8(); // must
    ch=ba.data();

     QFile file(ui->cb_history->currentText());
     //写文件
     file.open(QIODevice::WriteOnly);
     file.write(ch);
     file.close();

}
void MainWindow::clicked_bt_save_as(bool clicked){
    QString fileName= QFileDialog::getSaveFileName(this,"另存脚本","C:\Users\Administrator",tr("TEXT (*.txt)"));
    char*  ch;
    QByteArray ba = fileName.toUtf8(); // must
    ch=ba.data();

     QFile file(ui->cb_history->currentText());
     //写文件
     file.open(QIODevice::WriteOnly);
     file.write(ch);
     file.close();

}

void MainWindow::clicked_bt_replace(bool clicked){
    LARGE_INTEGER start;
    QueryPerformanceCounter(&start);

    lanrenAPI::setWindowsMousePenetrate(hwnd,true);
    LARGE_INTEGER end;
    QueryPerformanceCounter(&end);
    qDebug() << end.QuadPart-start.QuadPart;
}
LRESULT APIENTRY func_Message(
    HWND hwnd,        // handle to window
    UINT uMsg,        // message identifier
    WPARAM wParam,    // first message parameter
    LPARAM lParam)    // second message parameter
{
    if (uMsg==RID_INPUT){
        RAWINPUT rawdata;
        GetRawInputData((HRAWINPUT)lParam,RID_INPUT,&rawdata,(PUINT)40,16);
        switch (rawdata.header.dwType)
        {
        case RIM_TYPEKEYBOARD:
            qDebug() << "键盘数据到达";

        case RIM_TYPEMOUSE:
            qDebug() << "鼠标数据到达";
        }
    }

    return CallWindowProcA (MainWindow::lpPrevWndFunc, hwnd, uMsg, wParam, lParam);
}
//自动判断编码格式
QString MainWindow::GetCorrectUnicode(const QByteArray &ba)
{
    QTextCodec::ConverterState state;
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
    QString text = codec->toUnicode( ba.constData(), ba.size(), &state);
    if (state.invalidChars > 0)
    {
        text = QTextCodec::codecForName( "GBK" )->toUnicode(ba);
        return QString("GBK");
    }
    else
    {
        text = ba;
        return QString("UTF-8");
    }
}

错误解决

:-1: error: debug/mainwindow.o:mainwindow.cpp:(.rdata$.refptr._ZN10MainWindow13lpPrevWndFuncE[.refptr._ZN10MainWindow13lpPrevWndFuncE]+0x0): undefined reference to `MainWindow::lpPrevWndFunc'   报这个错误咋办

这是链接错误,编译器找不到定义 MainWindow::lpPrevWndFunc 的实现。你需要在 MainWindow 类外部定义和初始化 lpPrevWndFunc 变量,例如:

// 头文件 (mainwindow.h)
WNDPROC MainWindow::lpPrevWndFunc = nullptr;

说明

  • lanrenAPI 类需要替换为您的实际代码,用于实现原始输入数据钩子功能。
  • 该示例仅演示了基本的窗口消息钩子实现,您可能需要根据您的实际需求进行调整。
  • 请确保您已经正确配置了 Qt 开发环境。
  • 使用 qDebug() 输出调试信息可以帮助您理解代码逻辑。
  • 为了更安全地处理 Unicode 字符,建议使用 QString 类来存储和操作文本。
  • 为了确保代码的跨平台兼容性,建议使用 Qt 提供的 API 来处理文件操作。

总结

本文介绍了使用 C++ Qt 框架实现窗口消息钩子的方法,并提供了获取键盘和鼠标数据的示例代码。通过本文的介绍,您可以更好地理解窗口消息钩子的工作原理,并将其应用于您的 Qt 项目中。

C++ Qt 窗口消息钩子 | 键盘鼠标数据获取 | 代码示例

原文地址: https://www.cveoy.top/t/topic/nr8k 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录