Windows下使用Qt实现截图功能


前言

本文主要讲述了在Windows平台下使用Qt实现类似微信截图的功能,通过下面示例进行讲解,以便大家学习,如有错误之处,欢迎大家批评指正。

项目效果
请添加图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、实现思路

1. 创建遮罩层
需要创建一个自定义的QWidget作为遮罩层,这个遮罩层应该覆盖整个屏幕,并且设置为半透明,我创建了ScreenOverlay类,详见下文示例完整代码;

2. 监听截屏按钮点击事件
点击截图按钮后显示遮罩层,并准备进行屏幕截取,在这里调用ScreenOverlay类对象的show()触发ScreenOverlay类中的showEvent()获取全屏截图;

3. 截取屏幕内容
在遮罩层显示后,监听ScreenOverlay类的鼠标事件来定义截图的区域,在鼠标移动过程中使用update()刷新paintEvent(),更新截图显示以及图像信息;

4. 显示截图
鼠标左键松开后获取相应的截图,通过信号与槽发送信号将截图显示在主界面上的QLabel,并隐藏遮罩层。

二、实现截图时隐藏当前窗口

在这里我创建了一个单选按钮,在进行截图时根据单选按钮的状态决定是否隐藏当前窗口,在测试过程中发现当前窗口使用hide()隐藏是有耗时的,所以使用了Qtimer的singleShot函数进行了延时:

//开始截图
void MainWindow::on_pb_screen_clicked()
{
    if(ui->rb_hide->isChecked())
    {
        //当前窗口隐藏有耗时,需要延时触发遮罩类对象的showEvent事件
        this->hide();
        QTimer::singleShot(200,Qt::PreciseTimer,this,[this]()
        {
            m_screenOverlay->show();
        });
    }
    else
    {
        m_screenOverlay->show();
    }
}

三、示例完整代码

1.screenoverlay.h

#ifndef SCREENOVERLAY_H
#define SCREENOVERLAY_H

#include <QWidget>
#include <QRect>
#include <QPixmap>
#include <QScreen>
#include <QPainter>
#include <QMouseEvent>
#include <QApplication>
#include <QDesktopWidget>

class ScreenOverlay : public QWidget
{
    Q_OBJECT

public:
    explicit ScreenOverlay(QWidget *parent = nullptr);

protected:
    void showEvent(QShowEvent *) override;
    void paintEvent(QPaintEvent *) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;

signals:
    void signal_shotPixmap(QPixmap shotPixmap);

private:
    bool m_selestFlag;      //截屏标志
    QPoint m_startPoint;    //截屏起点
    QPoint m_endPoint;      //截屏终点
    QRect m_selectRect;     //截屏矩形区域
    QPixmap m_fullScreen;   //全屏图像
    QPixmap m_blurScreen;   //模糊全屏图像

};
#endif // SCREENOVERLAY_H

2.screenoverlay.cpp

#include "screenoverlay.h"

ScreenOverlay::ScreenOverlay(QWidget *parent)
    : QWidget(parent, Qt::Window | Qt::FramelessWindowHint)
{
    //设置窗口尺寸
    this->resize(QApplication::desktop()->size());
    m_selestFlag = false;
    m_startPoint = QPoint();
    m_endPoint = QPoint();
    m_selectRect = QRect();
    m_fullScreen = QPixmap();
    m_blurScreen = QPixmap();
}

//通过show()显式调用
void ScreenOverlay::showEvent(QShowEvent *)
{
    //设置透明度实现模糊背景
    m_startPoint = QPoint();
    m_endPoint = QPoint();
    m_selectRect = QRect();
    m_fullScreen = QApplication::primaryScreen()->grabWindow(0);
    QPixmap pix(m_fullScreen.width(),m_fullScreen.height());
    pix.fill((QColor(160, 160, 160, 200)));
    m_blurScreen = m_fullScreen;
    QPainter p(&m_blurScreen);
    p.drawPixmap(0,0,pix);
}

//重写绘图事件
void ScreenOverlay::paintEvent(QPaintEvent *)
{
    //创建QPainter对象进行绘制
    QPainter painter(this);
    QPen pen;
    pen.setColor(Qt::green);
    pen.setWidth(2);
    pen.setStyle(Qt::DotLine);
    painter.setPen(pen);

    //绘制模糊全屏图像
    painter.drawPixmap(0,0,m_blurScreen);

    //绘制截屏区域图像
    QRect curRect = QRect(m_startPoint,m_endPoint).normalized();
    QPoint startPoint = curRect.topLeft();
    QPoint endPoint = curRect.bottomRight();
    m_selectRect = QRect(startPoint,endPoint);
    int x = m_selectRect.x();
    int y = m_selectRect.y();
    int w = m_selectRect.width();
    int h = m_selectRect.height();
    painter.drawRect(m_selectRect);
    if(!m_selectRect.isEmpty())
    {
        painter.drawPixmap(x,y,m_fullScreen.copy(m_selectRect));
    }

    //使用黄色画笔绘制图像信息
    painter.setPen(QPen(Qt::yellow));
    painter.drawText(x+2,y-8,QString("Pos:(%1 x %2)   Size:(%3 x %4)")
                     .arg(x).arg(y).arg(w).arg(h));

}

//鼠标按下
void ScreenOverlay::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        m_selestFlag = true;
        m_startPoint = event->pos();
    }
}

//鼠标移动
void ScreenOverlay::mouseMoveEvent(QMouseEvent *event)
{
    if(m_selestFlag)
    {
        m_endPoint = event->pos();
        this->update();
    }
}

//鼠标松开
void ScreenOverlay::mouseReleaseEvent(QMouseEvent *event)
{
    //左键松开获取截图
    if(event->button() == Qt::LeftButton)
    {
        if(m_selestFlag)
        {
            m_selestFlag = false;
            if(!m_selectRect.isEmpty())
            {
                //从屏幕图像中复制选择区域
                QPixmap shotPixmap = m_fullScreen.copy(m_selectRect);
                emit signal_shotPixmap(shotPixmap);

                //隐藏遮罩层
                this->hide();
            }
        }
    }

    //右键松开取消
    if(event->button() == Qt::RightButton)
    {
        QPixmap nullPix;
        emit signal_shotPixmap(nullPix);
        this->hide();
    }
}

3.mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTimer>
#include "screenoverlay.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void initWidget();

private slots:
    void slot_shotPixmap(QPixmap shotPixmap);

    void on_pb_screen_clicked();

private:
    Ui::MainWindow *ui;

    ScreenOverlay *m_screenOverlay;   //屏幕遮罩类对象

};
#endif // MAINWINDOW_H

4.mainwindow.cpp

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

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->initWidget();
}

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

//初始化界面
void MainWindow::initWidget()
{
    this->setFixedSize(800,600);

    //屏幕遮罩类对象
    m_screenOverlay = new ScreenOverlay();
    connect(m_screenOverlay, &ScreenOverlay::signal_shotPixmap,this,&MainWindow::slot_shotPixmap);

}

//将截图显示在界面上
void MainWindow::slot_shotPixmap(QPixmap shotPixmap)
{
    ui->lb_show->clear();
    if(!shotPixmap.isNull())
    {
        ui->lb_show->setPixmap(shotPixmap.scaled(ui->lb_show->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation));
    }
    this->show();
}

//开始截图
void MainWindow::on_pb_screen_clicked()
{
    if(ui->rb_hide->isChecked())
    {
        //当前窗口隐藏有耗时,需要延时触发遮罩类对象的showEvent事件
        this->hide();
        QTimer::singleShot(200,Qt::PreciseTimer,this,[this]()
        {
            m_screenOverlay->show();
        });
    }
    else
    {
        m_screenOverlay->show();
    }
}

5.mainwindow.ui
请添加图片描述


总结

根据上文的思路我们也是使用Qt实现了截图功能,最主要的其实就是对Qt下事件的使用,这个示例中的遮罩类的鼠标、绘图等事件都进行了重写,如果我们以后遇到类似开发功能,就可以直接使用这个遮罩类,不用再重复造轮子啦~


hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

参考博客:使用Qt实现截图功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值