截图程序,支持多屏幕时跨屏幕截图。截图使用setMask达到镂空效果,截图后会有预览和保存功能。截图时按下Esc可退出。
mainwindow.ui
mainwindow.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
#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
#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)位置。多屏幕跨屏幕截图时,先分别截取每个屏幕的图,然后把他们拼起来。
代码