Qt 键盘鼠标录制回放软件 - JBMN
#include <mainwindow.h> #include <ui_mainwindow.h> WNDPROC lpPrevWndFunc = nullptr; LONGLONG intervalMose = 0; // 上一次鼠标时间 LONGLONG intervalKeyboard = 0; // 上一次键盘时间 MainWindow *pThis; // UI指针 bool isRecall = false; // 是否回放中 bool isRec = false; // 是否录制中 bool isResetRec = false; // 是否处于重录状态 int runTime = 1; QString jbText = ""; // 录制的脚本
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) {
ui->setupUi(this);
pThis = this; // 将自身对象暴露给外部全局变量指针, 这样在回调函数中就可以访问了
// 设置窗口透明度:
this->setWindowOpacity(0.8);
this->setWindowFlags(Qt::WindowStaysOnTopHint);
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) {
qDebug() << lanrenAPI::setWindowsMousePenetrate(hwnd, true);
} LRESULT CALLBACK MainWindow::func_Message(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (uMsg == WM_INPUT) {
UINT dwSize = 48;
LONGLONG inTime = 0;
QString nowTimeText;
POINT lpPint;
// 第一次调用函数传NULL获取需要的缓冲区大小 已经知道了就直接填48
//GetRawInputData((HRAWINPUT)lParam, (UINT)RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
// 分配指定的缓冲区大小
LPBYTE lpbBuffer = new BYTE[dwSize];
// 取数据到缓冲区
GetRawInputData((HRAWINPUT)lParam, (UINT)RID_INPUT, (LPVOID)lpbBuffer, (PUINT)&dwSize, (UINT)sizeof(RAWINPUTHEADER));
RAWINPUT* rawdata = (RAWINPUT *)lpbBuffer;
qDebug() << "键盘数据到达" << rawdata->data.keyboard.Message << rawdata->data.keyboard.VKey << inTime;
if (rawdata->header.dwType == RIM_TYPEKEYBOARD) {
inTime = updateIntervalKeyboard();
switch (rawdata->data.keyboard.VKey) {
case (VK_F8): { // 按下F8开始录制
if (rawdata->data.keyboard.Message == WM_KEYUP) {
if (isRec == false)
{
if (isRecall == true) {
goto endCall;
}
isRec = true;
isRecall = false;
nowTimeText = lanrenAPI::getNowTimeText();
GetCursorPos(&lpPint); // 获取当前鼠标相对于桌面的位置
if (isResetRec == false) {
jbText = pThis->ui->pte_jb->toPlainText();
jbText += jbText + "##" + nowTimeText + "##" + "\n鼠标初始 " + QString::number(lpPint.x) + " " + QString::number(lpPint.y) + "\n";
} else {
jbText = "鼠标初始 " + QString::number(lpPint.x) + " " + QString::number(lpPint.y) + "\n";
}
pThis->updataState();
LARGE_INTEGER a;
QueryPerformanceCounter(&a);
intervalKeyboard = a.QuadPart;
intervalMose = intervalKeyboard;
} else {
isRec = false;
isRecall = false;
pThis->ui->pte_jb->setPlainText(jbText);
pThis->updataState();
}
}
}
case (VK_F9): { // 按下F9开始回放
if (isRecall == false)
{
if (isRec == true) {
goto endCall;
}
isRecall = true;
isRec = false;
pThis->updataState();
runTime = QString.toInt(pThis->ui->led_time->text());
// 创建线程
RunScript* runscript = new RunScript;
// 绑定
connect(pThis, &MainWindow::setRunData, runscript, &RunScript::setRunData);
// 将参数发送过去
emit setRunData(runTime, jbText);
// 启动线程
runscript->start();
} else {
isRecall = false;
isRec = false;
pThis->ui->lb_state->setText("请稍等");
pThis->ui->lb_state->setStyleSheet("color: rgb(255, 170, 0);");
}
}
}
} else if (rawdata->header.dwType == RIM_TYPEMOUSE) {
inTime = updateIntervalMose();
qDebug() << "鼠标数据到达" << rawdata->data.mouse.lLastX << rawdata->data.mouse.lLastY << rawdata->data.mouse.ulButtons << rawdata->data.mouse.ulExtraInformation << inTime;
}
}
endCall:
return CallWindowProcA(lpPrevWndFunc, hwnd, uMsg, wParam, lParam);
} void MainWindow::updataState() { HWND hwnd = (HWND)(pThis->winId()); if (isRec == false && isRecall == false) { pThis->ui->lb_state->setText("待机中"); pThis->setWindowOpacity(0.8); pThis->ui->lb_state->setStyleSheet("color: rgb(0, 255, 255);"); lanrenAPI::setWindowsMousePenetrate(hwnd, false);
} else if (isRec == true && isRecall == false) {
if (isResetRec) {
pThis->ui->lb_state->setText("重录中");
} else {
pThis->ui->lb_state->setText("录制中");
}
pThis->setWindowOpacity(0.6);
pThis->ui->lb_state->setStyleSheet("color: rgb(0, 255, 0);");
lanrenAPI::setWindowsMousePenetrate(hwnd, true);
} else if (isRec == false && isRecall == true) {
pThis->ui->lb_state->setText("回放中");
pThis->setWindowOpacity(0.6);
pThis->ui->lb_state->setStyleSheet("color: rgb(255, 255, 0);");
lanrenAPI::setWindowsMousePenetrate(hwnd, true);
} else {
isRecall = false;
isRec = false;
pThis->ui->lb_state->setText("待机中");
pThis->setWindowOpacity(0.8);
pThis->ui->lb_state->setStyleSheet("color: rgb(0, 255, 255);");
lanrenAPI::setWindowsMousePenetrate(hwnd, false);
}
} // 自动判断编码格式 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"); } }
// 更新鼠标间隔 static LONGLONG updateIntervalMose() { LARGE_INTEGER a; LONGLONG ret; QueryPerformanceCounter(&a); ret = a.QuadPart - intervalMose; intervalMose = a.QuadPart; return ret; } // 更新键盘间隔 static LONGLONG updateIntervalKeyboard() { LARGE_INTEGER a; LONGLONG ret; QueryPerformanceCounter(&a); ret = a.QuadPart - intervalKeyboard; intervalKeyboard = a.QuadPart; return ret; }
原文地址: https://www.cveoy.top/t/topic/nsTJ 著作权归作者所有。请勿转载和采集!