QT的实现模拟鼠标点击事件

突发奇想,想要解决一些重复性的点击工作,比如抢票或者其他需要点击刷手速的地方,写了这么一个Exe文件

效果如下:

模拟鼠标

然后我们就来说细节部分,首先是我的界面设计,如下图所示:

我先讲一哈我的设置思路,首先人为的点击鼠标,获取到我们想要点击的鼠标位置,然后再将这个鼠标位置记录下来,通过WinUser.h这个C++的头文件,来实现模拟鼠标点击。

        在实现这个功能的时候,我遇到了一个问题如何获取到点击的鼠标位置,我对QT进行了研究,决定通过重写mousePressEvent函数来实现,获取鼠标位置,因为到人点击鼠标的时候吗,就会触发这个mousepressevent这个函数,我给它加了限定条件,只有在获取鼠标的判定条件打开时,才会记录该鼠标位置,并显示到UI界面上面。

        但是在写完代码以后我才发现,有一个比较严重的地方,就是鼠标事件只能读取到,QT界面里面的位置,因此我采取了一个大胆的方式,读取坐标位置的时候,将整个界面放大到整个屏幕,但是为了用户能够找到自己要点击的鼠标位置,我又把界面进行透明化,在选好位置以后,通过按键q,退出,即可。

        然后剩下的就交给mouse_event来模拟人为鼠标点击。

最后就是代码部分!!!

h头文件的代码如下:

#ifndef CLICK_H
#define CLICK_H

#include <QMainWindow>
#include <windows.h>
#include <QMouseEvent>
#include<QKeyEvent>
#include "ui_click.h"


QT_BEGIN_NAMESPACE
namespace Ui { class click; }
QT_END_NAMESPACE

class click : public QMainWindow
{
    Q_OBJECT

public:
    click(QWidget *parent = nullptr);
    ~click();
    POINT pos = {0,0} ;    //保存鼠标点击点的x、y坐标。这里的坐标值是整个显示屏幕窗口的坐标    //与Qt程序窗口无关。与你操作系统的分辨率有关。
    void hide_all();
    void show_all();


public slots:
    void mousePressEvent(QMouseEvent *event);
    void keyPressEvent(QKeyEvent *event);
    void doPressleftAct();//执行鼠标左键动作。
    void doPressrightAct();//执行鼠标左键动作
private slots:
    void on_pushButton_clicked();
    void on_pushButton_2_clicked();

    void on_radioButton_clicked();

    void on_radioButton_2_clicked();
protected:
    void paintEvent(QPaintEvent *event) override;

private:
    bool ok;
    int click_num;//点击次数
    float time; //控制间隔时间
    bool mouse_type_pand=false;//控制鼠标点击类型
    int notfixed=0;//控制是否采集坐标
    Ui::click *ui;
};
#endif // CLICK_H

cpp文件是如下代码:

#include "click.h"
#include "ui_click.h"
#include "QDebug"
#include <QButtonGroup>
#include<qpainter.h>
#include <QTimer>
#include<QTime>
#include <QtTest/QtTest>
#include <WinUser.h>
#pragma execution_character_set("utf-8")

click::click(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::click)
{
    ui->setupUi(this);
    ui->radioButton->setChecked(1);
    QButtonGroup *block1=new QButtonGroup(this);            //分组
    block1->addButton(ui->radioButton,1);                   //一个值为0
    block1->addButton(ui->radioButton_2,0);                 //一个值为1
    ui->lineEdit_3->setPlaceholderText("Doublesize");
}

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

void click::doPressleftAct()//模拟按键单击,区分左右
{
    int x=pos.x;
    int y=pos.y;
    SetCursorPos(x,y);//移动鼠标位置
     //鼠标单击一下左键

//     mouse_event (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, x, y, 0, 0 );
//     mouse_event (MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, x, y, 0, 0 );
//     mouse_event (MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, x, y, 0, 0 );
     mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN,x, y, 0, 0);
     mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTUP,x, y, 0, 0);

//    if(type_id==2)
//    {//鼠标单击右键
//     qDebug()<<type_id;
//     mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTDOWN,x, y, 0, 0);
//     mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTUP,x, y, 0, 0);
//    }
}

void click::hide_all()//隐藏所有
{
    this->setWindowFlags(Qt::FramelessWindowHint);
    QList<QWidget*> widgets = this->findChildren<QWidget*>();
    this->setWindowOpacity(0.3);
    this->showMaximized();
    for (int i = 0; i < widgets.size(); i++)
    {
//        qDebug() << widgets[i]->objectName();
        widgets[i]->setVisible(false);
    }
}

void click::show_all()//展示所有
{
    this->showNormal();
    QList<QWidget*> widgets = this->findChildren<QWidget*>();//批量获得当前页面所有控件信息
    for (int i = 0; i < widgets.size(); i++)
    {
//        qDebug() << widgets[i]->objectName();
        widgets[i]->setVisible(true);
    }
    this->setWindowOpacity(1);
    this->setWindowFlags(Qt::Window);
    this->show();
    notfixed=0;
}

void click::mousePressEvent(QMouseEvent *event)//重写检测鼠标按下功能,并画点表示
{
    //未取定坐标值时,取坐标值。否则不做什么。
    qDebug()<<notfixed;
        if(notfixed==1){
            if(event->button ()==Qt::LeftButton){
                GetCursorPos(&pos);
                qDebug()<<pos.x<<pos.y;
                ui->lineEdit->setText (QString::number (pos.x)+","+QString::number (pos.y));
                repaint();
            }
        }
}

void click::keyPressEvent(QKeyEvent *event)
{
    // 判断按下的键是不是 Qt::Key_q
        if (event->key() == Qt::Key_Q) {
            // 处理按下 Q 键的逻辑
//            qDebug() << "You pressed Q key";
            show_all();
        }
        // 调用父类的默认实现
        QWidget::keyPressEvent(event);
}

void click::doPressrightAct()
{
    int x=pos.x;
    int y=pos.y;
    SetCursorPos(x,y);//移动鼠标位置

    if(mouse_type_pand)
    {//鼠标单击右键
     mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTDOWN,x, y, 0, 0);
     mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTUP,x, y, 0, 0);
    }
}


void click::on_pushButton_clicked()
{
//    qDebug()<<"1";
    notfixed=1;
//    qDebug()<<"2";
    hide_all();
}
void click::on_pushButton_2_clicked()
{
    ui->plainTextEdit->clear();
    time = ui->lineEdit_2->text().toFloat(); // num = 123, ok = true
    click_num=ui->lineEdit_3->text().toInt(&ok);
//    qDebug()<<"panding"<<ok;
    if(ok)
    {
        for(int i=0;i<click_num;i++)
        {
            QTime dieTime = QTime::currentTime().addSecs(1*time); // 获取当前时间加上3秒
            while (QTime::currentTime() < dieTime) // 循环等待直到时间到达
            QCoreApplication::processEvents(QEventLoop::AllEvents, 100); // 处理事件循环,避免界面冻结

            ui->plainTextEdit->appendPlainText("第"+QString::number(i+1)+"次数");
        }
    }
    else{
        if(!mouse_type_pand)
            doPressleftAct();
        else
            doPressrightAct();
    }
}

void click::on_radioButton_clicked()
{
    mouse_type_pand=false;
//    qDebug()<<mouse_type;
}


void click::on_radioButton_2_clicked()
{
    mouse_type_pand=true;
//    qDebug()<<mouse_type;
}

void click::paintEvent(QPaintEvent *event)
{
    if(notfixed==1)
    {
    QPainter painter(this);
    QPen pen;
    pen.setColor(QColor(Qt::red));//设置笔颜色
    pen.setWidth(10);//设置笔宽度
    painter.setPen(pen);//设置为要绘制的笔
    painter.setPen(pen);
    painter.drawPoint(pos.x, pos.y); // 画一个点在(100, 100)的位置
//    qDebug()<<"chufa";
    }
}

        在这里,再解释一哈代码,使用的时候,需要先选择鼠标位置(用鼠标点击即可,会在屏幕下面留下痕迹,如果觉得位置不对,就再次点击,会改变记录的位置,并刷新为当前位置的),然后按q键(英文)退出即可,然后根据自己需要,进行左键或右键的选择,然后点击模拟点击按钮就会开始运行了。

由于这是兴致使然,突发奇想写的exe,所以肯定有很多不足的地方,供大家学习和交流,批评改进。如果觉得对您有帮助,请点赞,收藏,关注三连哟!(*^▽^*)

        然后我的下一步计划,就是做一个简单的模拟位置和时间间隔,以及点击类型的存储,从而实现一个整套的,解放双手的模拟点击软件,说不定可以用到游戏的脚本上面哈哈

*************************************************************************************************************        在这里主要是写其他模拟鼠标点击的组合方式,比如

        使用QWidget::mousePressEvent()和QWidget::mouseReleaseEvent()函数来重写控件的鼠标事件处理函数,并在其中调用QApplication::sendEvent()或QApplication::postEvent()函数将事件转发给其他控件。例如:

// 在自定义的Label类中重写鼠标事件处理函数
void Label::mousePressEvent(QMouseEvent *event)
{
    // 调用父类的函数
    QLabel::mousePressEvent(event);
    // 如果是鼠标左键按下
    if (event->button() == Qt::LeftButton) {
        // 创建一个新的鼠标事件对象
        QMouseEvent *newEvent = new QMouseEvent(event->type(), event->localPos(), event->windowPos(), event->screenPos(),
                                                event->button(), event->buttons(), event->modifiers(), event->source());
        // 将事件转发给lineEdit控件
        QApplication::sendEvent(ui->lineEdit, newEvent);
    }
}

void Label::mouseReleaseEvent(QMouseEvent *event)
{
    // 调用父类的函数
    QLabel::mouseReleaseEvent(event);
    // 如果是鼠标左键释放
    if (event->button() == Qt::LeftButton) {
        // 创建一个新的鼠标事件对象
        QMouseEvent *newEvent = new QMouseEvent(event->type(), event->localPos(), event->windowPos(), event->screenPos(),
                                                event->button(), event->buttons(), event->modifiers(), event->source());
        // 将事件转发给lineEdit控件
        QApplication::sendEvent(ui->lineEdit, newEvent);
    }
}

然后使用QObject::installEventFilterO函数为目标控件安装一个事件过滤器,并在过滤器中处理鼠标事件,例如:

// 在主窗口类中为label控件安装事件过滤器
ui->label->installEventFilter(this);
// 在主窗口类中重写eventFilter()函数
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    // 如果被监视的对象是label控件
    if (watched == ui->label) {
        // 如果事件类型是鼠标按下
        if (event->type() == QEvent::MouseButtonPress) {
            // 转换为鼠标事件对象
            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
            // 如果是鼠标左键按下
            if (mouseEvent->button() == Qt::LeftButton) {
                // 在lineEdit控件中显示鼠标位置
                ui->lineEdit->setText(QString("x=%1 y=%2").arg(mouseEvent->x()).arg(mouseEvent->y()));
                // 返回true表示已经处理了该事件,不再向下传递
                return true;
            }
        }
    }
    // 否则调用父类的函数
    return QMainWindow::eventFilter(watched, event);
}

还有使用QCursor类的setPosO函数来设置鼠标的位置,并使用QTest类的mouseclickO或mousePressO和mouseReleaseO函数来模拟鼠标的点击。例如:

// 模拟鼠标左键点击
QCursor::setPos(100,200); // 移动到(100,200)位置
QTest::mouseClick(QApplication::desktop(), Qt::LeftButton); // 点击
// 模拟鼠标右键点击
QCursor::setPos(300,400); // 移动到(300,400)位置
QTest::mouseClick(QApplication::desktop(), Qt::RightButton); // 点击

但是要注意,使用QCursor的话,要包含#include <QtTest/QtTest>这个头文件,以及

您需要在工程文件(.pro文件)中加入testlib模块:

QT += testlib

--------------------------------------------------------------------------------------------------------------------------------

用python实现模拟鼠标点击等

首先,你需要安装一些第三方库,如pyHook、PyUserInput、pyperclip等。您可以使用pip命令来安装这些库,例如:

pip install pyHook
pip install PyUserInput
pip install pyperclip

然后,你需要导入这些库,并创建鼠标和键盘对象,例如:

from pykeyboard import PyKeyboard
from pymouse import PyMouse
import pyperclip

k = PyKeyboard() # 创建键盘对象
m = PyMouse() # 创建鼠标对象

接下来,你可以使用这些对象的方法来模拟人为的操作,例如:

  • 模拟鼠标点击:你可以使用m.click(x, y, button)方法来模拟鼠标在指定位置(x, y)点击指定按钮(button),其中button可以是1(左键),2(右键),或3(中键)。例如:
m.click(100, 200, 1) # 模拟鼠标在(100, 200)位置左键点击
  • 模拟键盘输入:你可以使用k.type_string(string)方法来模拟键盘输入指定字符串(string),或者使用k.tap_key(key)方法来模拟键盘敲击指定按键(key)。例如:
k.type_string("Hello world!") # 模拟键盘输入"Hello world!"
k.tap_key(k.enter_key) # 模拟键盘敲击回车键
  • 模拟鼠标拖动:你可以使用m.drag(x1, y1, x2, y2)方法来模拟鼠标从位置(x1, y1)拖动到位置(x2, y2)。例如:
m.drag(100, 200, 300, 400) # 模拟鼠标从(100, 200)位置拖动到(300, 400)位置

在这里推荐一个不错的代码仓库给大家,链接如下:

python-zhengty158/模拟鼠标键盘-自动登录.py at master · zhengty158/python-zhengty158 (github.com)

代码部分如下:

# -*- coding: utf-8 -*-
# 模拟操作鼠标键盘,自动登录网站账号,这里以船讯网为例
# 需安装第三方库:pyautogui, pyperclip
# python3可用!

import pyautogui as gui, webbrowser as bro, pyperclip
from time import sleep

# 打开登录页面
print('\n\n     船讯网\n\n')
ship_name = input('请输入要查找的船名(中英文均可)或IMO号,按回车键确认:\n\n>>> ')
print('\n\n现在开始自动登录和查询船舶资料\n\n 不要动键盘鼠标!')
sleep(3)
bro.open('http://www.shipxy.com/Home/Login/')
sleep(8)

# 定义复制粘贴函数,实现自动输入汉字
def paste(word):
    pyperclip.copy(word)
    gui.hotkey('ctrl', 'v')
    
gui.click(x = 579, y = 6)
# 点击账户输入框
gui.click(x = 584, y = 267)

username = 'username'
password = 'password'

# 通过操作键盘自动找准输入框,输入账号密码
sleep(1)
paste(username)
gui.typewrite(['tab'])
paste(password)
gui.typewrite(['enter'])
sleep(8)

# 自动查询用户输入的船名或IMO号
gui.click(x = 126, y = 203)
paste(ship_name)
gui.typewrite(['enter'])

input('')

以上就是我对于模拟鼠标的分享,希望能给大家带来帮助。

猜你喜欢

转载自blog.csdn.net/Helloorld_1/article/details/132034702