QT截图程序,可多屏幕截图

截图程序,支持多屏幕时跨屏幕截图。截图使用setMask达到镂空效果,截图后会有预览和保存功能。截图时按下Esc可退出。

mainwindow.ui

mainwindow.cpp

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QFileDialog>
#include <QPushButton>
#include <QPixmap>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle(QString(tr("截图")));
    ui->centralwidget->setMouseTracking(true);
    ui->comboBox->addItem(QString(tr(".")));
    ui->comboBox->addItem(QString(tr("Select Folder")));
    connect(ui->comboBox, SIGNAL(activated(int)), this, SLOT(SelectFolder(int)));
    connect(ui->button_reset, SIGNAL(clicked(bool)), this, SLOT(ResetSnap(bool)));
    connect(ui->button_save, SIGNAL(clicked(bool)), this, SLOT(SavePicture(bool)));
}

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

void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    qDebug()<<this->geometry();
    QMainWindow::mouseMoveEvent(event);
}

void MainWindow::SetImage(QPixmap &pixmap)
{
    const double defultWidth = 400.0;
    const double defaultHeight = 160.0;

    ui->label->setPixmap(pixmap);
    double pixscale = 1.0 * pixmap.width()/pixmap.height();
    double initscale = defultWidth/defaultHeight;
    if (pixscale > initscale)
    {
        ui->label->setFixedWidth(defultWidth);
        ui->label->setFixedHeight(defultWidth / pixscale);
    }
    else
    {
        ui->label->setFixedHeight(defaultHeight);
        ui->label->setFixedWidth(defaultHeight * pixscale);
    }
}

void MainWindow::SelectFolder(int index)
{
    if (index == 1)
    {
        qDebug()<<ui->comboBox->itemText(index);
        QString directory = QFileDialog::getExistingDirectory(this,
                                    tr("QFileDialog::getExistingDirectory()"),
                                    ".");
        if (!directory.isEmpty())
        {
            qDebug()<<directory;
            ui->comboBox->addItem(directory);
            ui->comboBox->setCurrentText(directory);
        }
        else
        {
            ui->comboBox->setCurrentIndex(0);
        }
    }
}

void MainWindow::ResetSnap(bool)
{
    this->hide();
    emit resetSnap();
}

void MainWindow::SavePicture(bool)
{
    if (ui->lineEdit->text().trimmed() == QString(""))
    {
        ui->lineEdit->setFocus();
        return;
    }
    if (ui->comboBox->currentText() != ".")
    {
        ui->label->pixmap()->save(ui->comboBox->currentText() + "/" + ui->lineEdit->text(), "PNG");
    }
    else
    {
        ui->label->pixmap()->save(ui->lineEdit->text(), "PNG");
    }
}

maskwidget.cpp

cpp 复制代码
#include "maskwidget.h"
#include "ui_maskwidget.h"
#include <QMouseEvent>
#include <QRegion>
#include <QScreen>
#include <QPainter>
#include <QGuiApplication>
#include <QPixmap>
#include <QDebug>
#include <QtMath>

MaskWidget::MaskWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MaskWidget)
{
    ui->setupUi(this);
    setMouseTracking(true);
    setWindowFlags(Qt::FramelessWindowHint);

    setWindowOpacity(0.8);
    QList<QScreen*> screens = QGuiApplication::screens();
    int width = 0;
    int height = 0;
    for (QScreen *screen : screens)
    {
        width += screen->geometry().width();
        if (height < screen->geometry().height())
        {
            height = screen->geometry().height();
        }
        qDebug()<<screen->geometry();
    }
    this->setFixedSize(width, height);

    m.hide();

    connect(&m, SIGNAL(resetSnap()), this, SLOT(ResetSnap()));
}

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

void MaskWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        m_pressPos = event->pos();

        isPressed = true;
        update();
    }

    QWidget::mousePressEvent(event);
}

void MaskWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if (isPressed)
    {
        isPressed = false;
        QRegion all(0, 0, width(), height());

        QRegion sub(m_maskRect);
        setMask(all.subtracted(sub));


        QPixmap combined(this->width(), this->height());
        combined.fill(Qt::transparent);
        QPainter painter(&combined);

        QList<QScreen*> screens = QGuiApplication::screens();
        for (QScreen *screen : screens)
        {
            m_image = screen->grabWindow(0);
            painter.drawPixmap(screen->geometry().x(), 0, screen->geometry().width(), screen->geometry().height(), m_image);
        }

        auto gpos = mapToGlobal(event->pos());
        auto gposStart = mapToGlobal(m_pressPos);
        qDebug()<<gpos<<gposStart;
        m_image = combined.copy(qMin(gpos.x(), gposStart.x()), qMin(gpos.y(), gposStart.y()),
                                qFabs(gpos.x() - gposStart.x()), qFabs(gpos.y() - gposStart.y()));
        this->hide();

        m.SetImage(m_image);
        update();

        m.show();

    }

    return QWidget::mouseReleaseEvent(event);
}

void MaskWidget::mouseMoveEvent(QMouseEvent* event)
{
    if (isPressed)
    {
        m_newPos = event->pos();
        QRegion all(0, 0, width(), height());
        m_maskRect = QRect(qMin(m_pressPos.x(), m_newPos.x()),
                       qMin(m_pressPos.y(), m_newPos.y()),
                       qFabs(m_newPos.x() - m_pressPos.x()),
                       qFabs(m_newPos.y() - m_pressPos.y()));

        QRegion sub(m_maskRect);
        setMask(all.subtracted(sub));
        
        update();
    }
    return QWidget::mouseMoveEvent(event);
}

void MaskWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    
    painter.setPen(Qt::red);
    painter.drawRect(m_maskRect.x()-1, m_maskRect.y()-1, m_maskRect.width()+2, m_maskRect.height() + 2);

}

void MaskWidget::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Escape)
    {
        close();
    }
    QWidget::keyPressEvent(event);
}

void MaskWidget::showEvent(QShowEvent *event)
{
    QWidget::showEvent(event);
}

void MaskWidget::ResetSnap()
{
    QRegion all(0, 0, width(), height());
    setMask(all);
    m_maskRect.setRect(0,0,0,0);
    this->show();
}

main.cpp

cpp 复制代码
#include "mainwindow.h"
#include "maskwidget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    MaskWidget m;
    m.move(0, 0);
    m.show();



    return a.exec();
}

多个屏幕时,默认设置位置和大小总是在一个屏,需要用move()将它移动到(0, 0)位置。多屏幕跨屏幕截图时,先分别截取每个屏幕的图,然后把他们拼起来。

代码

相关推荐
「QT(C++)开发工程师」5 小时前
【qt版本概述】
开发语言·qt
一路冰雨9 小时前
Qt打开文件对话框选择文件之后弹出两次
开发语言·qt
老赵的博客10 小时前
QT 自定义界面布局要诀
开发语言·qt
码码哈哈0.010 小时前
VSCode 2022 离线安装插件QT VSTOOl报错此扩展不能安装在任何当前安装的产品上。
ide·vscode·qt
feiyangqingyun14 小时前
Qt/C++离线地图的加载和交互/可以离线使用/百度和天地图离线/支持手机上运行
c++·qt·qt天地图·qt离线地图·qt地图导航
gz94561 天前
windows下,用CMake编译qt项目,出现错误By not providing “FindQt5.cmake“...
开发语言·qt
「QT(C++)开发工程师」1 天前
Ubuntu 26.04 LTS 大升级:Qt 6 成为未来新引擎
qt
兆。1 天前
python实战案例----使用 PyQt5 构建简单的 HTTP 接口测试工具
爬虫·python·qt
喝哈喝哈1 天前
pycharm中配置pyqt5
python·qt·pycharm
Qt云程序员1 天前
Qt、C++实现五子棋人机对战与本地双人对战(高难度AI,极少代码)
c++·人工智能·qt