自己琢磨了一上午左右,因为需要做一些测试的事情,所以想着能不能简化一些重复的鼠标操作。上网搜索到右一些工具,如惠普的qtp什么的,做自动化测试是挺方便的,但是要钱。身为一个资深白嫖档,花钱是不可能花钱的,想着就自己写一个吧。基本就是调用windows的api实现繁琐的鼠标点击操作。其他没什么的。这里需要用到钩子函数。不清楚的可以百度下
看代码:
.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTextEdit>
#include <QPushButton>
#include <QLabel>
#include <windows.h>
#include <QLineEdit>
struct myPoint{
int x;
int y;
long long btn;
};
class Widget;
class Hook
{
public:
Hook();
void InstallHook();
void UnInstallHook();
};
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
public slots:
void SaveSetting();
public:
QTextEdit *m_pStepEdit=nullptr;
QLineEdit *m_pSpeedEdit=nullptr;
QLineEdit *m_pCountEdit=nullptr;
};
#endif // WIDGET_H
.cpp
#include "widget.h"
#include <QVBoxLayout>
#include <QMouseEvent>
#include <qdebug.h>
#include <windows.h>
#include <winuser.h>
#include <QIntValidator>
static Widget *wgt;
int m_Count=1;
int m_Speed=1000;
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
wgt=this;
this->resize(800,600);
QFont textFont;
textFont.setPointSize(12);
textFont.setFamily("Microsoft YaHei");
m_pStepEdit=new QTextEdit(this);
m_pStepEdit->setFont(textFont);
m_pSpeedEdit=new QLineEdit(this);
m_pCountEdit=new QLineEdit(this);
m_pSpeedEdit->setFont(textFont);
m_pCountEdit->setFont(textFont);
m_pSpeedEdit->setText("1000");
m_pCountEdit->setText("1");
m_pCountEdit->setValidator(new QIntValidator);
m_pSpeedEdit->setValidator(new QIntValidator);
QLabel *SpeedLabel=new QLabel(tr("Speed(ms) :"));
QLabel *CountLabel=new QLabel(tr("Count:"));
SpeedLabel->setFont(textFont);
CountLabel->setFont(textFont);
QHBoxLayout *SettingLayout=new QHBoxLayout(this);
SettingLayout->addWidget(SpeedLabel);
SettingLayout->addWidget(m_pSpeedEdit);
SettingLayout->addWidget(CountLabel);
SettingLayout->addWidget(m_pCountEdit);
SettingLayout->setSpacing(5);
SettingLayout->setMargin(5);
QWidget *settingWgt=new QWidget(this);
settingWgt->setLayout(SettingLayout);
QPushButton *SaveBtn=new QPushButton(tr("Save"));
SaveBtn->setFixedSize(100,27);
SaveBtn->setFont(textFont);
QVBoxLayout *mainLayout=new QVBoxLayout(this);
mainLayout->addWidget(m_pStepEdit);
mainLayout->addWidget(settingWgt);
mainLayout->addWidget(SaveBtn);
mainLayout->setSpacing(5);
mainLayout->setMargin(5);
this->setLayout(mainLayout);
connect(SaveBtn,&QPushButton::clicked,this,&Widget::SaveSetting);
Hook hok;
hok.InstallHook();
}
Widget::~Widget()
{
}
void Widget::SaveSetting()
{
m_Count=m_pCountEdit->text().toInt();
m_Speed=m_pSpeedEdit->text().toInt();
}
static HHOOK keyHook=nullptr;
static HHOOK mouseHook=nullptr;
QList<myPoint> PointList;
bool m_bF8=false;
bool m_bF9=false;
bool m_bF10=false;
LRESULT CALLBACK keyProc(int nCode,WPARAM wParam,LPARAM lParam)
{
KBDLLHOOKSTRUCT *pkbhs=(KBDLLHOOKSTRUCT*)lParam;
if(nCode == HC_ACTION&&lParam>0)
{
//F8代表开始录制鼠标事件
//F9暂停录制
//F10执行操作
//F11清空操作
if(GetKeyState(pkbhs->vkCode)& 0x8000) //判断键盘按下
{
if(pkbhs->vkCode==VK_F8)
{
wgt->hide();
wgt->m_pStepEdit->append("-----------------Recording-----------------");
m_bF8=true;
m_bF9=false;
}
if(pkbhs->vkCode==VK_F9)
{
wgt->show();
m_bF8=false;
m_bF9=true;
wgt->m_pStepEdit->append("-----------------End-----------------");
}
if(pkbhs->vkCode==VK_F10)
{
wgt->m_pStepEdit->append("-----------------Starting-----------------");
wgt->hide();
for(int i=0;i<m_Count;i++) //执行次数
{
for(int i=0;i<PointList.size();i++)
{
SetCursorPos(PointList[i].x,PointList[i].y);
Sleep(m_Speed);
if(PointList[i].btn==WM_LBUTTONUP)
{
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
Sleep(10);
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
}
else if(PointList[i].btn==WM_RBUTTONUP)
{
mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);
Sleep(10);
mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);
}
else if(PointList[i].btn==WM_MBUTTONUP)
{
mouse_event(MOUSEEVENTF_MIDDLEDOWN,0,0,0,0);
Sleep(10);
mouse_event(MOUSEEVENTF_MIDDLEUP,0,0,0,0);
}
}
}
wgt->m_pStepEdit->append("-----------------Finished-----------------");
wgt->show();
}
if(pkbhs->vkCode==VK_F11)
{
wgt->show();
wgt->m_pStepEdit->clear();
PointList.clear();
}
}
}
return CallNextHookEx(keyHook, nCode, wParam, lParam);
}
LRESULT CALLBACK Mouseproc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(wParam == WM_LBUTTONUP||wParam == WM_RBUTTONUP||wParam == WM_MBUTTONUP) //左 中 右键
{
if(m_bF8)
{
POINT p;
GetCursorPos(&p);
myPoint Point;
Point.x=p.x;
Point.y=p.y;
Point.btn=wParam;
PointList.append(Point);
QString strBtn="";
if(wParam == WM_LBUTTONUP)
{
strBtn="LeftBtn";
}
if(wParam == WM_RBUTTONUP)
{
strBtn="RightBtn";
}
if(wParam == WM_MBUTTONUP)
{
strBtn="MiddleBtn";
}
QString strText=QString("X:%1 Y:%2").arg(p.x).arg(p.y)+"Btn:"+strBtn;
wgt->m_pStepEdit->append(strText);
}
}
return CallNextHookEx(mouseHook,nCode,wParam,lParam);
}
Hook::Hook()
{
}
void Hook::InstallHook()
{
keyHook =SetWindowsHookEx( WH_KEYBOARD_LL,keyProc,nullptr,0); //注册键盘标钩子
mouseHook =SetWindowsHookEx(WH_MOUSE_LL,Mouseproc,nullptr,0); //注册鼠标钩子
}
void Hook::UnInstallHook()
{
if(keyHook!=nullptr)
{
UnhookWindowsHookEx(keyHook);
keyHook=nullptr;
}
if(mouseHook!=nullptr)
{
UnhookWindowsHookEx(mouseHook);
mouseHook=nullptr;
}
}
界面很简洁的,基本就是记录下鼠标的位置,及是鼠标的左中右键。其他就没什么了,然后在重复执行操作就行。
界面大致是这样的,可以设置运行间隔时间,因为有些应用程序打开的时候速度很慢,所以你需要把执行的时间放慢一点,后面就是设置执行的次数。后面的话我会继续完善键盘事件,这个东西做好的话还是挺实用的。
欢迎评论区留言哦。