Search code examples
c++qtscreenshotmultiple-monitorsprintscreen

How can I take a print screen using Qt / C++ with various monitors?


I'm new to Qt Creator, but I'm trying to create and application than takes a Screen Shot every minute, I found a code in Qt Creator to do this but it only works with one monitor, if I have two or more it only takes a screen shot of one the monitors.

this it's the code I'm ussing.

this it's the screenshot.h

#ifndef SCREENSHOT_H
#define SCREENSHOT_H

#include <QPixmap> 
#include <QWidget>

class QCheckBox;
class QGridLayout;
class QGroupBox;
class QHBoxLayout;
class QLabel;
class QPushButton;
class QSpinBox;
class QVBoxLayout;

class screenshot : public QWidget
{
    Q_OBJECT

public:
    screenshot();

protected:
   void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;

private slots:
   void newScreenshot();
   void saveScreenshot();
   void shootScreen();
   void updateCheckBox();

private:
   void createOptionsGroupBox();
   void createButtonsLayout();
   QPushButton *createButton(const QString &text, QWidget *receiver, const char *member);
   void updateScreenshotLabel();

   QPixmap originalPixmap;

   QLabel *screenshotLabel;
   QGroupBox *optionsGroupBox;
   QSpinBox *delaySpinBox;
   QLabel *delaySpinBoxLabel;
   QCheckBox *hideThisWindowCheckBox;
   QPushButton *newScreenshotButton;
   QPushButton *saveScreenshotButton;
   QPushButton *quitScreenshotButton;

   QVBoxLayout *mainLayout;
   QGridLayout *optionsGroupBoxLayout;
   QHBoxLayout *buttonsLayout;
};

#endif // SCREENSHOT_H

and this it's the screenshot.cpp

#include <QtWidgets>

#include "screenshot.h"

screenshot::screenshot()
{
    screenshotLabel = new QLabel;
    screenshotLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    screenshotLabel->setAlignment(Qt::AlignCenter);
    screenshotLabel->setMinimumSize(240, 160);

    createOptionsGroupBox();
    createButtonsLayout();

    mainLayout = new QVBoxLayout;
    mainLayout->addWidget(screenshotLabel);
    mainLayout->addWidget(optionsGroupBox);
    mainLayout->addLayout(buttonsLayout);
    setLayout(mainLayout);

    shootScreen();
    delaySpinBox->setValue(5);

    setWindowTitle(tr("Screenshot"));
    resize(300, 200);
}

void screenshot::resizeEvent(QResizeEvent * /* event */)
{
     QSize scaledSize = originalPixmap.size();
     scaledSize.scale(screenshotLabel->size(), Qt::KeepAspectRatio);
     if (!screenshotLabel->pixmap() || scaledSize != screenshotLabel->pixmap()->size())
         updateScreenshotLabel();
  }

  void screenshot::newScreenshot()
  {
       if (hideThisWindowCheckBox->isChecked())
           hide();
       newScreenshotButton->setDisabled(true);

      QTimer::singleShot(delaySpinBox->value() * 1000, this, SLOT(shootScreen()));
 }

 void screenshot::saveScreenshot()
 {
     QString format = "jpg";
     QString initialPath = QDir::currentPath() + tr("/untitled.") + format;

     QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), initialPath,
                                                tr("%1 Files (*.%2);;All Files (*)")
                                                .arg(format.toUpper())
                                                .arg(format));
   if (!fileName.isEmpty())
       originalPixmap.save(fileName, format.toLatin1().constData());
}

void screenshot::shootScreen()
{
    if (delaySpinBox->value() != 0)
       qApp->beep();
    originalPixmap = QPixmap(); // clear image for low memory situations
                            // on embedded devices.
   QScreen *screen = QGuiApplication::primaryScreen();
   if (screen)
      originalPixmap = screen->grabWindow(0);
    updateScreenshotLabel();

   newScreenshotButton->setDisabled(false);
   if (hideThisWindowCheckBox->isChecked())
      show();
}

void screenshot::updateCheckBox()
{
  if (delaySpinBox->value() == 0) {
      hideThisWindowCheckBox->setDisabled(true);
      hideThisWindowCheckBox->setChecked(false);
  } else {
      hideThisWindowCheckBox->setDisabled(false);
  }
}

void screenshot::createOptionsGroupBox()
{
    optionsGroupBox = new QGroupBox(tr("Options"));

    delaySpinBox = new QSpinBox;
    delaySpinBox->setSuffix(tr(" s"));
    delaySpinBox->setMaximum(60);
    connect(delaySpinBox,SIGNAL(valueChanged(int)), this, SLOT(updateCheckBox()));
    //connect(delaySpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateCheckBox()));

    delaySpinBoxLabel = new QLabel(tr("Screenshot Delay:"));

    hideThisWindowCheckBox = new QCheckBox(tr("Hide This Window"));

    optionsGroupBoxLayout = new QGridLayout;
    optionsGroupBoxLayout->addWidget(delaySpinBoxLabel, 0, 0);
    optionsGroupBoxLayout->addWidget(delaySpinBox, 0, 1);
    optionsGroupBoxLayout->addWidget(hideThisWindowCheckBox, 1, 0, 1, 2);
    optionsGroupBox->setLayout(optionsGroupBoxLayout);
}

void screenshot::createButtonsLayout()
{
    newScreenshotButton = createButton(tr("New Screenshot"), this, SLOT(newScreenshot()));
   saveScreenshotButton = createButton(tr("Save Screenshot"), this, SLOT(saveScreenshot()));
   quitScreenshotButton = createButton(tr("Quit"), this, SLOT(close()));

   buttonsLayout = new QHBoxLayout;
   buttonsLayout->addStretch();
   buttonsLayout->addWidget(newScreenshotButton);
   buttonsLayout->addWidget(saveScreenshotButton);
   buttonsLayout->addWidget(quitScreenshotButton);
}

   QPushButton *screenshot::createButton(const QString &text, QWidget *receiver,
                                  const char *member)
{
    QPushButton *button = new QPushButton(text);
    button->connect(button, SIGNAL(clicked()), receiver, member);
    return button;
}

 void screenshot::updateScreenshotLabel()
 {
    screenshotLabel->setPixmap(originalPixmap.scaled(screenshotLabel->size(),
                                                 Qt::KeepAspectRatio, Qt::SmoothTransformation));
 }

Can some help me modify this code or tell me how can I do it ??

Thanks


Solution

  • The QGuiApplication class has a screens() method that returns a list of pointers to all the QScreen objects for the computer. So you'd want to use that, and e.g. replace this code:

    QScreen *screen = QGuiApplication::primaryScreen();
    if (screen)
       originalPixmap = screen->grabWindow(0);
    

    with something more like this:

    QList<QScreen *> screens = QGuiApplication::screens();
    QList<QPixmap> pixmapsList;
    for (int i=0; i<screens.size(); i++)
    {
       const QRect r = screens[i]->geometry();
       pixmapsList.push_back(screens[i]->grabWindow(0), r.x(), r.y(), r.width(), r.height());
    }
    

    ... then of course you'll need to modify the file-saving code to save each QPixmap in the pixmapsList, rather than just a single QPixmap, but that's straightforward to do.