QT 多屏幕截图

目前百度能百度到的,都是让大家调用以下方法获取屏幕

QGuiApplication::primaryScreen();

但这个函数只能获取主屏幕,对多个显示器的截屏就完全不好使了。

所以用以下方法获取所有显示器,并判断当前鼠标、界面位于哪个显示器,即可实现多个屏幕的截图。

int curMonitor = deskTop->screenNumber ( this );
this->baseScreen = screens.at(curMonitor);

截图主要事件为鼠标按下,鼠标移动,鼠标抬起。需要一个全局的点来标记鼠标最开始按下时的点。

以下为三个事件的处理:

void QtScreenShot::mousePressEvent(QMouseEvent* e)
{
    this->startPoint = e->pos();
    this->startGlobalPoint = e->globalPos();
}

void QtScreenShot::mouseMoveEvent(QMouseEvent* e)
{
    QPoint curPoint;
    curPoint = e->pos();
    if (hasArea)
    {
        qDebug() << "return";
        return;
    }
    int posX = startPoint.x();
    int posY = startPoint.y();
    int posWid = curPoint.x() - startPoint.x();
    int posHig = curPoint.y() - startPoint.y();

    this->editArea->setGeometry(posX, posY, posWid, posHig);
    QImage ima = this->getSelectImage(posX, posY, posWid, posHig);
    this->editArea->setBgImage(ima);
    this->editArea->show();
}

void QtScreenShot::mouseReleaseEvent(QMouseEvent* e)
{
    if (e->button() == Qt::RightButton)
    {
        closeAll();
        this->accept();
        return;
    }
    if (hasArea)
    {
        qDebug() << "return";
        return;
    }
    QPoint curPoint;
    curPoint = e->pos();
    int posX = startPoint.x();
    int posY = startPoint.y();
    int posWid = curPoint.x() - startPoint.x();
    int posHig = curPoint.y() - startPoint.y();

    QPoint glcurPoint;
    glcurPoint = e->globalPos();
    this->globalSelectArea.setRect(startGlobalPoint.x(), startGlobalPoint.y(), glcurPoint.x() - startGlobalPoint.x(), glcurPoint.y() - startGlobalPoint.y());
    this->editArea->setGeometry(posX, posY, posWid, posHig);
    QImage ima = this->getSelectImage(posX, posY, posWid, posHig);
    this->editArea->setBgImage(ima);
    this->editArea->show();
    this->toolBar->setPos(curPoint.x(), curPoint.y());
    this->toolBar->show();
    this->hasArea = true;
}

以下为我写的一个demo。测试界面位于哪个屏幕,就可以在哪个屏幕截图,同时还提供操作撤销功能。

如果需要鼠标位于什么屏幕就在哪个屏幕截图,仅需增加一个定时器,在定时器的槽函数中判断当前鼠标的屏幕并重新初始化。(注意根据hasArea判断是否已经取了截图区域)

具体的demo包括DrawingOperationStack(操作栈)、ScreenShotEditArea(截图编辑区)、ScreenShotToolBar(操作栏)三个部分组成。工程我放入了百度网盘中,链接如下:

链接:https://pan.baidu.com/s/1OaHkAlVBiWPx5FU2z3IMrw 
提取码:gogo

具体的代码也贴出来:

测试用的widget(拖进来个按钮和label,按钮用于触发截图,label显示图片):

#include "widget.h"
#include "ui_widget.h"
#include 
#include 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    this->hide();
}

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

void Widget::on_pushButton_clicked()
{
    QDesktopWidget* deskTop = QApplication::desktop();
    int curMonitor = deskTop->screenNumber(this);
    st = new QtScreenShot(curMonitor,this);
    st->setParent(this);
    connect(st,SIGNAL(onScreenShotOK()),this,SLOT(closeScreenShot()));
    st->exec();
}

void Widget::closeScreenShot()
{
    QImage image = st->getScreenShotImage();
    image = image.scaled(ui->label_1->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    QPixmap im = QPixmap::fromImage(image);
    ui->label_1->setPixmap(im);
    st->accept();
}

drawingoperationstack.h:

#ifndef DRAWINGOPERATIONSTACK_H
#define DRAWINGOPERATIONSTACK_H

#include 
#include 
#include 
struct DrawingOperation{
    int curMode;
    QRect recogRect;
    QRect tempRect;
};

class DrawingOperationStack
{
public:
    DrawingOperationStack();
    void pushInStack(int curMode, QRect rectr, QRect rectt);
    DrawingOperation popStack();
    DrawingOperation getCurOperation();
    bool isEmptyStack();
private:
    QStack stack;

};

#endif // DRAWINGOPERATIONSTACK_H

drawingoperationstack.cpp

#include "drawingoperationstack.h"
#include 
DrawingOperationStack::DrawingOperationStack()
{
    this->stack.clear();
}

void DrawingOperationStack::pushInStack(int curMode, QRect rectr, QRect rectt)
{
    DrawingOperation *st;
    st = new DrawingOperation;
    st->curMode = curMode;
    st->recogRect = rectr;
    st->tempRect = rectt;
    //qDebug()<mode<rect;
    this->stack.push(st);
}

DrawingOperation DrawingOperationStack::popStack()
{
    DrawingOperation op;
    op.curMode = -1;
    op.recogRect = QRect(0,0,0,0);
    op.tempRect = QRect(0,0,0,0);

    if(this->stack.isEmpty())
    {
        return op;
    }
    DrawingOperation *opera = this->stack.pop();
    op.recogRect = opera->recogRect;
    op.tempRect = opera->tempRect;
    op.curMode = opera->curMode;
    //this->stack.pop();
    delete opera;
    //qDebug()<stack.isEmpty())
    {
        return op;
    }
    DrawingOperation *opera = this->stack.back();
    op.recogRect = opera->recogRect;
    op.tempRect = opera->tempRect;
    op.curMode = opera->curMode;
    return op;
}

bool DrawingOperationStack::isEmptyStack()
{
    return this->stack.isEmpty();
}

qtscreenshoteditarea.h

#ifndef QTSCREENSHOTEDITAREA_H
#define QTSCREENSHOTEDITAREA_H

#include 
#include 
#include "drawingoperationstack.h"
class QtScreenShotEditArea : public QWidget
{
    Q_OBJECT
public:
    explicit QtScreenShotEditArea(QWidget *parent = nullptr);

    void setBgImage(QImage &image);
    void paintEvent(QPaintEvent *event);
    void setMode(int mode);
    void setOpRect(QRect rectR,QRect rectT);
    QImage getImage();
protected:
    void mousePressEvent(QMouseEvent *e);//鼠标按下事件
    void mouseMoveEvent(QMouseEvent *e);//鼠标按下后移动事件
    void mouseReleaseEvent(QMouseEvent *e);//鼠标按下后抬起事件
private:
    QRect tempRect;
    QPoint startPoint;
    QRect recogRect;
    QImage bgImage;
    int curMode;
signals:
    void emitOperation(DrawingOperation op);
};

#endif // QTSCREENSHOTEDITAREA_H

qtscreenshoteditarea.cpp

#include "qtscreenshoteditarea.h"
#include 
#include 
#include 
#include 
QtScreenShotEditArea::QtScreenShotEditArea(QWidget *parent) : QWidget(parent)
{
    this->recogRect = QRect(0,0,0,0);
    this->tempRect = QRect(0,0,0,0);
    setWindowFlags(windowFlags() | Qt::FramelessWindowHint|Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
    bgImage = QImage(0,0,QImage::Format_RGB32);
    setAttribute(Qt::WA_TranslucentBackground, true);
    curMode = -1;

}

void QtScreenShotEditArea::setBgImage(QImage &image)
{
    this->bgImage = image;
    this->update();
}

void QtScreenShotEditArea::paintEvent(QPaintEvent *event)
{
     QPainter painter(this);
     if(bgImage.size().width() == 0 && bgImage.size().height() == 0)
     {
         return;
     }
     QPoint pt(0,0);
     QColor recogColor(223,80,80);
     QColor tempColor(0,137,255);
     painter.drawImage(pt,bgImage);
     if(recogRect.width() != 0 && recogRect.height() != 0)
     {
         QPoint pt1(recogRect.x(),recogRect.y());
         QPoint pt2(recogRect.x(),recogRect.y() + recogRect.height());
         QPoint pt3(recogRect.x() + recogRect.width(), recogRect.y() + recogRect.height());
         QPoint pt4(recogRect.x() + recogRect.width(), recogRect.y());
         painter.setPen(QPen(recogColor));
         painter.drawLine(pt1,pt2);
         painter.drawLine(pt2,pt3);
         painter.drawLine(pt3,pt4);
         painter.drawLine(pt4,pt1);
     }

     if(tempRect.width() !=0 &&tempRect.height() != 0)
     {
         QPoint pt1(tempRect.x(),tempRect.y());
         QPoint pt2(tempRect.x(),tempRect.y() + tempRect.height());
         QPoint pt3(tempRect.x() + tempRect.width(), tempRect.y() + tempRect.height());
         QPoint pt4(tempRect.x() + tempRect.width(), tempRect.y());
         painter.setPen(QPen(tempColor));
         painter.drawLine(pt1,pt2);
         painter.drawLine(pt2,pt3);
         painter.drawLine(pt3,pt4);
         painter.drawLine(pt4,pt1);
     }

}

void QtScreenShotEditArea::setMode(int mode)
{
    curMode = mode;
}

void QtScreenShotEditArea::setOpRect(QRect rectR,QRect rectT)
{

    this->tempRect = rectT;

    this->recogRect = rectR;
    //qDebug()<tempRect<recogRect;
    this->update();
}

QImage QtScreenShotEditArea::getImage()
{
    QImage image;
    QPixmap pix;
    pix = this->grab(QRect(0,0,this->width(),this->height()));
    image = pix.toImage();

    return image;
}

void QtScreenShotEditArea::mousePressEvent(QMouseEvent *e)
{
    this->startPoint = e->pos();
}

void QtScreenShotEditArea::mouseMoveEvent(QMouseEvent *e)
{
    QPoint pt = e->pos();
    QRect curRect = QRect(startPoint.x(),startPoint.y(), pt.x() - startPoint.x(), pt.y() - startPoint.y());
    if(curMode ==0)
    {
        this->recogRect = curRect;
    }
    if(curMode == 1)
    {
        this->tempRect = curRect;
    }
    this->update();
}

void QtScreenShotEditArea::mouseReleaseEvent(QMouseEvent *e)
{
    QPoint pt = e->pos();
    QRect curRect = QRect(startPoint.x(),startPoint.y(), pt.x() - startPoint.x(), pt.y() - startPoint.y());
    DrawingOperation op;
    op.curMode =curMode;
    if(curMode == -1)
    {
        return;
    }
    if(curMode ==0)
    {
        this->recogRect = curRect;

    }
    if(curMode == 1)
    {
        this->tempRect = curRect;
    }
    op.recogRect = this->recogRect;
    op.tempRect = this->tempRect;
    //qDebug()<update();
}

qtscreenshottoolbar.h

#ifndef QTSCREENSHOTTOOLBAR_H
#define QTSCREENSHOTTOOLBAR_H

#include 
#include 
#include 
class QtScreenShotToolBar : public QWidget
{
    Q_OBJECT
public:
    explicit QtScreenShotToolBar(QWidget *parent = nullptr);

    void setPos(int x, int y);
    void setMode(int mode);
    void init();

    void paintEvent(QPaintEvent *event);
    void resetChosen(int num);
protected:
    void mouseReleaseEvent(QMouseEvent *e);//鼠标按下后抬起事件

private:
    bool bChosen[5];
signals:
    void setDrawMode(int mode);
    void removeDrawMode(int mode);
};

#endif // QTSCREENSHOTTOOLBAR_H

qtscreenshottoolbar.cpp

#include "qtscreenshottoolbar.h"
#include 
#include 
#include 

QtScreenShotToolBar::QtScreenShotToolBar(QWidget *parent) : QWidget(parent)
{
    //this->setGeometry(100,100,100,20);
    setWindowFlags(windowFlags() | Qt::FramelessWindowHint|Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
    setAttribute(Qt::WA_TranslucentBackground, true);

    this->init();
    this->update();
}

void QtScreenShotToolBar::setPos(int x, int y)
{
    int curX = x- 100;
    if(curX<0)
    {
        curX = 0;
    }
    this->setGeometry(curX,y,100,20);
    this->update();
}

void QtScreenShotToolBar::setMode(int mode)
{

    bChosen[mode] = true;
    resetChosen(mode);
    qDebug()<update();
}

void QtScreenShotToolBar::init()
{
    //this->setGeometry(100,100,100,20);
    for(int i=0;i<5;i++)
    {
        bChosen[i] = false;
    }
//    this->set
}

void QtScreenShotToolBar::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    qDebug()<<"painting!";
    for(int i=0;i<5;i++)
    {
        qDebug()<pos();
    if(pt.y()<0 || pt.y()>20)
    {
        return;
    }
    int chosenNum = 0;
    if(pt.x() < 0)
    {
        return;
    }
    else if(pt.x() < 20)
    {
        chosenNum = 0;
    }
    else if(pt.x() < 40)
    {
        chosenNum = 1;
    }
    else if(pt.x() < 60)
    {
        chosenNum = 2;
    }
    else if(pt.x() < 80)
    {
        chosenNum = 3;
    }
    else if(pt.x()<100)
    {
        chosenNum = 4;
    }
    else{
        return;
    }
    bChosen[chosenNum] = !bChosen[chosenNum];
    if(bChosen[chosenNum] == true)
    {
        resetChosen(chosenNum);
        emit setDrawMode(chosenNum);
    }
    else
    {
        resetChosen(chosenNum);
        emit removeDrawMode(chosenNum);
    }
    if(chosenNum > 1)
    {
        bChosen[chosenNum] = false;
    }


    this->update();
}

void QtScreenShotToolBar::resetChosen(int num)
{
    for(int i=0; i<5;i++)
    {
        if(i != num)
        {
            bChosen[i] = false;
        }
    }
}

qtscreenshot.h

#ifndef QTSCREENSHOT_H
#define QTSCREENSHOT_H
#include 
#include 
#include 
#include 
#include 
#include 
#include "qtscreenshottoolbar.h"
#include "qtscreenshoteditarea.h"
#include "drawingoperationstack.h"
class QtScreenShot :public QDialog
{
    Q_OBJECT

public:

public:
    explicit QtScreenShot(int curScreen, QWidget* parent = nullptr);

    void init(int curScreen);
    void ShowToolBar();
    void paintEvent(QPaintEvent* event);
    QImage getScreenShotImage();
    QImage getFullScreenImage();
    void closeAll();
    bool hasGotImage;
public slots:
    void onDrawModeSet(int mode);
    void onDrawModeRemove(int mode);
    void onGetOperation(DrawingOperation op);
    //void reject();
protected:
    void mousePressEvent(QMouseEvent* e);//鼠标按下事件
    void mouseMoveEvent(QMouseEvent* e);//鼠标按下后移动事件
    void mouseReleaseEvent(QMouseEvent* e);//鼠标按下后抬起事件

private:
    QScreen* baseScreen;//屏幕截图
    QRect selectArea;//选中截图区域大小(相对)
    QRect globalSelectArea;
    QRect selectTempArea;
    QRect globalTempArea;
    QRect selectRecogArea;
    QRect globalSelectRecogArea;
    QtScreenShotToolBar *toolBar;//截图工具栏
    QtScreenShotEditArea *editArea;//截图编辑界面
    QPoint startPoint;
    QPoint startGlobalPoint;
    QImage baseImage;
    DrawingOperationStack operationStack;
    int curMode;
    int curScreen;
    QImage ansImage;
private:
    QImage getSelectImage(int x, int y, int width, int height);
    void bindSignalSlots();
    QImage AdjustBrightness(QImage Img, int iBrightValue);
    void AutoUnOperation(DrawingOperation delOperation, DrawingOperation curOperation);
    bool hasArea;

signals:
    void onScreenShotOK();
};

#endif // QTSCREENSHOT_H

qtscreenshot.cpp

#include "qtscreenshot.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
QtScreenShot::QtScreenShot(int curScreen, QWidget* parent) :
    QDialog(parent)
{
    this->init(curScreen);

}

void QtScreenShot::init(int curScreen)
{
    this->selectArea = QRect(-1, -1, -1, -1);
    this->selectRecogArea = QRect(-1, -1, -1, -1);
    this->selectTempArea = QRect(-1, -1, -1, -1);
    QList screens = QGuiApplication::screens();
    qDebug() << screens.size();

    qDebug() << curScreen;
    this->baseScreen = screens.at(curScreen);
    QRect rectCurWin = this->baseScreen->geometry();;
    qDebug() << rectCurWin;
    QSize siz = this->baseScreen->size();
    this->setGeometry(rectCurWin);

    setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::FramelessWindowHint);
    setAttribute(Qt::WA_TranslucentBackground, true);

    this->hasGotImage = false;
    this->editArea = new QtScreenShotEditArea(this);
    this->editArea->hide();
    this->toolBar = new QtScreenShotToolBar(this);
    this->toolBar->hide();

    this->baseImage = baseScreen->grabWindow(0).toImage();
    this->curMode = -1;
    this->hasArea = false;
    this->bindSignalSlots();
}

void QtScreenShot::bindSignalSlots()
{
    connect(toolBar, SIGNAL(setDrawMode(int)), this, SLOT(onDrawModeSet(int)));
    connect(toolBar, SIGNAL(removeDrawMode(int)), this, SLOT(onDrawModeRemove(int)));
    connect(editArea, SIGNAL(emitOperation(DrawingOperation)), this, SLOT(onGetOperation(DrawingOperation)));
}

QImage QtScreenShot::AdjustBrightness(QImage Img, int iBrightValue)
{
    int red, green, blue;
    int pixels = Img.width() * Img.height();
    unsigned int* data = (unsigned int*)Img.bits();

    for (int i = 0; i < pixels; ++i)
    {
        red = qRed(data[i]) + iBrightValue;
        red = (red < 0x00) ? 0x00 : (red > 0xff) ? 0xff : red;
        green = qGreen(data[i]) + iBrightValue;
        green = (green < 0x00) ? 0x00 : (green > 0xff) ? 0xff : green;
        blue = qBlue(data[i]) + iBrightValue;
        blue = (blue < 0x00) ? 0x00 : (blue > 0xff) ? 0xff : blue;
        data[i] = qRgba(red, green, blue, qAlpha(data[i]));
    }

    return Img;

}

void QtScreenShot::AutoUnOperation(DrawingOperation delOperation, DrawingOperation curOperation)
{
    /**/
    /**/
    if (delOperation.curMode == -1)
    {
        this->hasArea = false;
        editArea->hide();
        toolBar->hide();
    }
    else
    {
        /*无论什么操作,先清空*/
        /**/
        QRect rect(0, 0, 0, 0);
        editArea->setOpRect(rect, rect);
        editArea->setMode(-1);
        /*可还原再还原*/
        /**/
        if (curOperation.curMode != -1)
        {
            editArea->setMode(curOperation.curMode);
            editArea->setOpRect(curOperation.recogRect, curOperation.tempRect);
            this->toolBar->setMode(curOperation.curMode);
        }
    }

}
void QtScreenShot::ShowToolBar()
{

}

void QtScreenShot::paintEvent(QPaintEvent* event)
{
    QPainter painter(this);
    QImage image = getFullScreenImage();
    image = AdjustBrightness(image, -30);
    painter.drawImage(0, 0, image);
}

QImage QtScreenShot::getScreenShotImage()
{
    QImage pixmap = this->editArea->getImage();
    this->ansImage = pixmap;
    return this->ansImage;
}

QImage QtScreenShot::getFullScreenImage()
{
    return baseImage;
}

void QtScreenShot::closeAll()
{
    while (!operationStack.isEmptyStack())
    {
        operationStack.popStack();
    }

}

void QtScreenShot::onDrawModeSet(int mode)
{
    curMode = mode;
    if (mode < 0)
    {
        return;
    }
    else if (mode < 2)
    {
        this->editArea->setMode(mode);
    }
    else if (mode == 2)
    {
        qDebug() << "in redo ";
        DrawingOperation op = operationStack.popStack();
        DrawingOperation op2 = operationStack.getCurOperation();
        AutoUnOperation(op, op2);
    }
    else if (mode == 3)
    {
        emit onScreenShotOK();

    }
    else if (mode == 4)
    {
        this->closeAll();
        this->accept();
    }
    else
    {
        return;
    }

}

void QtScreenShot::onDrawModeRemove(int mode)
{
    curMode = -1;
    if (mode < 0)
    {
        return;
    }
    else if (mode < 2)
    {
        this->editArea->setMode(-1);
    }
    else if (mode == 2)
    {

    }
    else if (mode == 3)
    {
        emit onScreenShotOK();
    }
    else if (mode == 4)
    {

    }
    else
    {
        return;
    }
}

void QtScreenShot::onGetOperation(DrawingOperation op)
{
    this->operationStack.pushInStack(op.curMode, op.recogRect, op.tempRect);
}

void QtScreenShot::mousePressEvent(QMouseEvent* e)
{
    this->startPoint = e->pos();
    this->startGlobalPoint = e->globalPos();
}

void QtScreenShot::mouseMoveEvent(QMouseEvent* e)
{
    QPoint curPoint;
    curPoint = e->pos();
    //qDebug() << "move";
    if (hasArea)
    {
        qDebug() << "return";
        return;
    }
    int posX = startPoint.x();
    int posY = startPoint.y();
    int posWid = curPoint.x() - startPoint.x();
    int posHig = curPoint.y() - startPoint.y();

    this->editArea->setGeometry(posX, posY, posWid, posHig);
    QImage ima = this->getSelectImage(posX, posY, posWid, posHig);
    this->editArea->setBgImage(ima);
    this->editArea->show();
    //qDebug() << "showarea in move";
}

void QtScreenShot::mouseReleaseEvent(QMouseEvent* e)
{
    if (e->button() == Qt::RightButton)
    {
        closeAll();
        this->accept();
        return;
    }
    if (hasArea)
    {
        qDebug() << "return";
        return;
    }
    QPoint curPoint;
    curPoint = e->pos();
    int posX = startPoint.x();
    int posY = startPoint.y();
    int posWid = curPoint.x() - startPoint.x();
    int posHig = curPoint.y() - startPoint.y();

    QPoint glcurPoint;
    glcurPoint = e->globalPos();
    this->globalSelectArea.setRect(startGlobalPoint.x(), startGlobalPoint.y(), glcurPoint.x() - startGlobalPoint.x(), glcurPoint.y() - startGlobalPoint.y());
    this->editArea->setGeometry(posX, posY, posWid, posHig);
    QImage ima = this->getSelectImage(posX, posY, posWid, posHig);
    this->editArea->setBgImage(ima);
    this->editArea->show();
    this->toolBar->setPos(curPoint.x(), curPoint.y());
    this->toolBar->show();
    this->hasArea = true;
    qDebug() << startPoint << curPoint;
    qDebug() << "showarea in release";
}

QImage QtScreenShot::getSelectImage(int x, int y, int width, int height)
{
    QImage pixmap = baseImage;

    return pixmap.copy(x, y, width, height);
}

你可能感兴趣的:(qt,c++)