windows鼠标模拟
知识点:
1.windows窗口获取
句柄模式,可通过vs中spy++获取窗口类名与app名称,子窗口句柄使用FindWindowEx可以获取,部分开发窗口做了事件屏蔽,并不能穿透事件代码如下:
QString appClassName("xxxx");
QString appName = QStringLiteral("xxxxx");
LPCWSTR app = reinterpret_cast<LPCWSTR>(appClassName.data());
LPCWSTR appCaption = reinterpret_cast<LPCWSTR>(appName.data());
HWND appwnd = ::FindWindowW(app, appCaption);
qDebug() << "topWndScreen appWnd:" << appwnd;
int res = ShowWindow(appwnd,SW_SHOWNORMAL);
qDebug() << "topWndScreen ShowWindow SW_RESTORE:" << res;
if(res < 0)
qDebug() << "Restore failed GetLastError:" << GetLastError();
HWND childWnd = ::FindWindowEx(appwnd,0,0,0);
qDebug() << "topWndScreen childWnd 1:" << childWnd;
childWnd = ::FindWindowEx(childWnd,0,0,0);
qDebug() << "topWndScreen childWnd 2:" << childWnd;
::SetWindowPos(childWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
SendMessage(childWnd, WM_KEYDOWN, 'A', 0);
2.单例多线程
使用单例过程跨线程调用的时候需要为判断条件进行加锁,并且注意头文件内声明无重复定义对象,否则大概率会出现单例事件多次实例化的情况
全代码如下:
主窗口Mainwindow
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mouseact.h"
#include <QDebug>
#include "singleform.h"
#include "timermanager.h"
#include <QKeyEvent>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btnPressLMouse_clicked()
{
MouseAct::getInstance()->doPressAct(ui->lineEdit_xPos->text().toInt(),ui->lineEdit_yPos->text().toInt(),0,0,1);
}
void MainWindow::on_btnDoubleLMouse_clicked()
{
qDebug() << "on_btnDoubleLMouse_clicked 1";
MouseAct::getInstance()->doPressAct(ui->lineEdit_xPos->text().toInt(),ui->lineEdit_yPos->text().toInt(),0,0,2);
qDebug() << "on_btnDoubleLMouse_clicked 2";
//MouseAct::getInstance()->doPressAct(ui->lineEdit_xPos->text().toInt(),ui->lineEdit_yPos->text().toInt(),0,0,2);
qDebug() << "on_btnDoubleLMouse_clicked 3";
}
void MainWindow::on_btnPressRMouse_clicked()
{
MouseAct::getInstance()->doPressAct(ui->lineEdit_xPos->text().toInt(),ui->lineEdit_yPos->text().toInt(),0,0,3);
}
void MainWindow::on_btnDoubleRMouse_clicked()
{
MouseAct::getInstance()->doPressAct(ui->lineEdit_xPos->text().toInt(),ui->lineEdit_yPos->text().toInt(),0,0,4);
}
void MainWindow::on_btnMoveMouse_clicked()
{
MouseAct::getInstance()->doPressAct(ui->lineEdit_xPos->text().toInt(),ui->lineEdit_yPos->text().toInt(),0,0,5);
}
void MainWindow::on_btnDropMouse_clicked()
{
MouseAct::getInstance()->doPressAct(ui->lineEdit_xPos->text().toInt(),ui->lineEdit_yPos->text().toInt(),800,800,6);
}
void MainWindow::on_pushButton_clicked()
{
MouseAct::getInstance()->topWndScreen();
}
void MainWindow::on_btnAddMouseEvent_clicked()
{
SingleForm * addItem = new SingleForm;
QListWidgetItem * item = new QListWidgetItem(ui->listWidget);
item->setSizeHint(QSize(ui->listWidget->size().width(),150));
ui->listWidget->addItem(item);
ui->listWidget->setItemWidget(item, addItem);
}
void MainWindow::on_btnRemoveSel_clicked()
{
ui->listWidget->takeItem(ui->listWidget->row(ui->listWidget->currentItem()));
}
void MainWindow::on_btnStart_clicked()
{
TimerManager * instance = TimerManager::getInstance();
connect(instance, &TimerManager::signalRemoveTimes, this, &MainWindow::slotRemoveTimes);
instance->setDataListWidget(ui->listWidget);
qDebug() << "MainWindow::on_btnStart_clicked value:" << ui->spinBox->value();
instance->setCountTimes(ui->spinBox->value());
instance->setInterValue(ui->lineEditTimeInterval->text().toInt());
instance->start();
}
void MainWindow::on_btnStop_clicked()
{
TimerManager::getInstance()->stop();
}
void MainWindow::slotRemoveTimes(int nTimes)
{
ui->spinBox->setValue(nTimes);
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if(event->modifiers() == Qt::ALT && event->key() == Qt::Key_F1)
on_btnStop_clicked();
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void slotRemoveTimes(int nTimes);
void keyPressEvent(QKeyEvent *event);
private slots:
void on_btnPressLMouse_clicked();
void on_btnDoubleLMouse_clicked();
void on_btnPressRMouse_clicked();
void on_btnDoubleRMouse_clicked();
void on_btnMoveMouse_clicked();
void on_btnDropMouse_clicked();
void on_pushButton_clicked();
void on_btnAddMouseEvent_clicked();
void on_btnRemoveSel_clicked();
void on_btnStart_clicked();
void on_btnStop_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
鼠标事件类
#include "mouseact.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QtDebug>
//#include <windows.h>
#include <winuser.h>
#pragma comment(lib, "User32.lib")//这个一定要有,不然编译不过
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
MouseAct::MouseAct()
{
}
//获取鼠标点击处的全局坐标值(屏幕坐标)
void MouseAct::getClickedPos()
{
LPPOINT pos;
if(GetCursorPos(pos)){
qDebug() << "MouseAct::getClickedPos GetCursorPos Success pos_x:" << pos->x << " pos_y:" << pos->y;
}
else
{
qDebug() << "MouseAct::getClickedPos GetCursorPos Error:" << GetLastError();
}
}
void MouseAct::topWndScreen()
{
QString appClassName("xxx");
QString appName = QStringLiteral("xxx");
LPCWSTR app = reinterpret_cast<LPCWSTR>(appClassName.data());
LPCWSTR appCaption = reinterpret_cast<LPCWSTR>(appName.data());
HWND appwnd = ::FindWindowW(app, appCaption);
qDebug() << "topWndScreen appWnd:" << appwnd;
int res = ShowWindow(appwnd,SW_SHOWNORMAL);
qDebug() << "topWndScreen ShowWindow SW_RESTORE:" << res;
if(res < 0)
qDebug() << "Restore failed GetLastError:" << GetLastError();
HWND childWnd = ::FindWindowEx(appwnd,0,0,0);
qDebug() << "topWndScreen childWnd 1:" << childWnd;
childWnd = ::FindWindowEx(childWnd,0,0,0);
qDebug() << "topWndScreen childWnd 2:" << childWnd;
::SetWindowPos(childWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
SendMessage(childWnd, WM_KEYDOWN, 'A', 0);
}
HWND MouseAct::GetCurrentWnd()
{
QString appClassName("LDPlayerMainFrame");
QString appName = QStringLiteral("xxx");
LPCWSTR app = reinterpret_cast<LPCWSTR>(appClassName.data());
LPCWSTR appCaption = reinterpret_cast<LPCWSTR>(appName.data());
HWND appwnd = ::FindWindowW(app, appCaption);
HWND childWnd = ::FindWindowEx(appwnd,0,0,0);
childWnd = ::FindWindowEx(childWnd,0,0,0);
EnableWindow(appwnd,true);
SetForegroundWindow(appwnd);
ShowWindow(appwnd, SW_SHOWNORMAL);
return appwnd;
}
//执行鼠标动作
void MouseAct::doPressAct(int x,int y,int x1,int y1,int type_id)
{
SetCursorPos(x,y);//必须要先设置一下鼠标的初始位置,不然会导致不成功
//获取屏幕尺寸大小
QDesktopWidget * desktop = QApplication::desktop();
QRect screen_rect = desktop->screenGeometry(0);
int desktop_width = screen_rect.width();
int desktop_height = screen_rect.height();
qDebug()<<"desktop_width"<<desktop_width;
qDebug()<<"desktop_height"<<desktop_height;
//topWndScreen();
//HWND wnd = GetCurrentWnd();
if(type_id==1)
{
//鼠标左键单击
mouse_event(MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_LEFTUP,x, y, 0, 0);//按下
//mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTUP,x, y, 0, 0);//松开
}
else if(type_id==2)
{
//鼠标左键双击
SetCursorPos(x,y);
mouse_event(MOUSEEVENTF_LEFTUP|MOUSEEVENTF_LEFTDOWN,0, 0, 0, 0);
}else if(type_id==3)
{
//鼠标右键单击
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTDOWN,x, y, 0, 0);
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTUP,x, y, 0, 0);
}else if(type_id==4)
{
//鼠标右键双击
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTDOWN,x, y, 0, 0);
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTUP,x, y, 0, 0);
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTDOWN,x, y, 0, 0);
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTUP,x, y, 0, 0);
}else if(type_id==5)
{
//鼠标移动
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE ,
x * 65536 / desktop_width,y * 65536 / desktop_height,0,GetMessageExtraInfo());
}else if(type_id==6)
{
//鼠标拖拽
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN,x, y, 0, 0);
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE ,
x1 * 65536 / desktop_width,y1 * 65536 / desktop_height,0,GetMessageExtraInfo());
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTUP,x1, y1, 0, 0);
qDebug()<<"--"<<x<<","<<y<<"to"<<x1<<","<<y1;
}
}
#ifndef MOUSEACT_H
#define MOUSEACT_H
#include <windows.h>
class MouseAct;
static MouseAct * m_instance = nullptr;
class MouseAct
{
public:
MouseAct();
static MouseAct * getInstance(){
if(m_instance == nullptr)
m_instance = new MouseAct;
return m_instance;
}
void getClickedPos() ;//获取鼠标点击处的全局坐标值(屏幕坐标)
void doPressAct(int,int,int,int,int);//执行鼠标动作。
void topWndScreen();
HWND GetCurrentWnd();
};
#endif // MOUSEACT_H
事件信息单元格
#include "singleform.h"
#include "ui_singleform.h"
#include <QMouseEvent>
#include <QDebug>
SingleForm::SingleForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::SingleForm)
{
ui->setupUi(this);
m_bLMouseState = false;
}
SingleForm::~SingleForm()
{
delete ui;
}
void SingleForm::mousePressEvent(QMouseEvent *event)
{
return QWidget::mousePressEvent(event);
}
void SingleForm::mouseReleaseEvent(QMouseEvent *event)
{
if(m_bLMouseState)
{
QPoint pos = event->globalPos();
ui->lineEdit_x->setText(QString::number(pos.x()));
ui->lineEdit_y->setText(QString::number(pos.y()));
}
m_bLMouseState = false;
return QWidget::mouseReleaseEvent(event);
}
void SingleForm::on_btnGetCurrentPos_pressed()
{
m_bLMouseState = true;
}
QPoint SingleForm::GetPos()
{
return QPoint(ui->lineEdit_x->text().toInt(), ui->lineEdit_y->text().toInt());
}
int SingleForm::GetPosRange()
{
return ui->lineEdit_range_value->text().toInt();
}
#ifndef SINGLEFORM_H
#define SINGLEFORM_H
#include <QWidget>
namespace Ui {
class SingleForm;
}
class SingleForm : public QWidget
{
Q_OBJECT
public:
explicit SingleForm(QWidget *parent = nullptr);
~SingleForm();
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
QPoint GetPos();
int GetPosRange();
private slots:
void on_btnGetCurrentPos_pressed();
private:
Ui::SingleForm *ui;
bool m_bLMouseState;
};
#endif // SINGLEFORM_H
循环消息事件执行
#include "timermanager.h"
#include <QListWidget>
#include <windows.h>
#include <QTime>
#include <QDebug>
#include "singleform.h"
#include "mouseact.h"
static TimerManager * m_Timerinstance = nullptr;
std::mutex texA;
TimerManager::TimerManager(QObject * parent)
:QThread(parent)
{
nCountTimes = 0;
lisWidget = nullptr;
nTimerInterval = 0;
}
int TimerManager::GetRsandValue(int nMax,int nMin)
{
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
int nValue = nMax - nMin;
nValue = qrand()%nValue + nMin;
qDebug() << "GetRsandValue nValue:" << nValue;
return nValue;
}
TimerManager * TimerManager::getInstance(){
texA.lock();
if(m_Timerinstance == nullptr){
m_Timerinstance = new TimerManager();
}
texA.unlock();
return m_Timerinstance;
}
void TimerManager::run()
{
if(lisWidget == nullptr)
return;
TimerManager * timeInstance = TimerManager::getInstance();
while(timeInstance->nCountTimes > 0)
{
timeInstance->setCountTimes(timeInstance->nCountTimes-1);
emit timeInstance->signalRemoveTimes(timeInstance->nCountTimes);
for(int i=0; i<lisWidget->count();++i)
{
Sleep(timeInstance->GetRsandValue(1100,1000));
SingleForm * item = (SingleForm*)lisWidget->itemWidget(lisWidget->item(i));
int nValue = timeInstance->GetRsandValue(item->GetPosRange(),0);
MouseAct::getInstance()->doPressAct(item->GetPos().x()+nValue,item->GetPos().y()+nValue,0,0,2);
Sleep(2*1000);
}
Sleep(timeInstance->nTimerInterval*1000);
}
}
void TimerManager::setInterValue(int nValue)
{
nTimerInterval = nValue;
}
void TimerManager::setCountTimes(int nTimes)
{
nCountTimes = nTimes;
}
void TimerManager::stop()
{
TimerManager::getInstance()->setCountTimes(0);
}
void TimerManager::setDataListWidget(QListWidget * data)
{
lisWidget = data;
}
void TimerManager::start()
{
QThread::start();
}
#pragma once
#ifndef TIMERMANAGER_H
#define TIMERMANAGER_H
#include <QThread>
#include <QDebug>
#include <mutex>
class QListWidget;
class TimerManager;
class TimerManager : public QThread
{
Q_OBJECT
public:
TimerManager(QObject * parent = nullptr);
static TimerManager * getInstance();
void run();
void stop();
void start();
void setCountTimes(int nTimes);
void setDataListWidget(QListWidget * data);
void setInterValue(int nValue);
int GetRsandValue(int nMax,int nMin);
int nCountTimes;
signals:
void signalRemoveTimes(int nTimes);
private:
int nTimerInterval;
QListWidget * lisWidget;
//static TimerManager* instance;
};
#endif // TIMERMANAGER_H
编译成功后ui界面如下:

该代码示例展示了在Windows系统中如何获取窗口句柄并模拟鼠标事件,如点击、移动等。同时,它还涉及到单例模式在多线程环境中的应用,确保了跨线程调用的正确性。通过`FindWindow`和`FindWindowEx`函数定位窗口,使用`SetWindowPos`和`SendMessage`发送键盘事件。此外,还包括了一个简单的事件调度器`TimerManager`,用于定时执行一系列鼠标事件。
347





