Search code examples
c++qtqt5screenshotmultiple-monitors

Screenshot capture of dual monitor in Qt 5


In the context of a Qt application, I'm using the following code snippet for taking a screenshot of the full desktop:

QDesktopWidget* dw = QApplication::desktop();
QPixmap pixmap = QPixmap::grabWindow(dw->winId(), 0, 0,
                                     dw->width(), dw->height());
pixmap.save(name, "JPG", screenshot_quality);

This approach works pretty well in Linux and Windows and with dual monitor, independently of screen's resolutions; that is, it works still if the two monitors are working with different resolutions.

However, with Qt 5, I get the following run-time warning:

static QPixmap QPixmap::grabWindow(WId, int, int, int, int) is deprecated, use QScreen::grabWindow() instead. Defaulting to primary screen.

So I reviewed the Qt 5 doc and I wrote this:

QScreen * screen = QGuiApplication::primaryScreen();
QPixmap pixmap = screen->grabWindow(0);
pixmap.save(name, "JPG", screenshot_quality);

But this approach does not capture the second screen.

So I searched a little more and, according to this thread, Taking Screenshot of Full Desktop with Qt5, I designed the screenshot capture as follows:

QScreen * screen = QGuiApplication::primaryScreen();
QRect g = screen->geometry();
QPixmap pixmap = screen->grabWindow(0, g.x(), g.y(), g.width(), g.height());
pixmap.save(name, "JPG", screenshot_quality);

Unfortunately, this does not work either.

What catches my attention is that the method with Qt 4 works well. Since I imagine there must be some way to make it in Qt 5.

How can be done with Qt 5?


Solution

  • Naturally, QGuiApplication::primaryScreen() will give you a single screen.

    You could:

    • Use QList<QScreen *> QGuiApplication::screens() to get all screens associated with the application.
    • Take screenshots for all of them.
    • Create another blank image.
    • Size it according to how you want to compose the screens.
    • Manually compose them into a final image using QPainter.
    QPixmap grabScreens() {
      auto screens = QGuiApplication::screens();
      QList<QPixmap> scrs;
      int w = 0, h = 0, p = 0;
      foreach (auto scr, screens) {
        QPixmap pix = scr->grabWindow(0);
        w += pix.width();
        if (h < pix.height()) h = pix.height();
        scrs << pix;
      }
      QPixmap final(w, h);
      QPainter painter(&final);
      final.fill(Qt::black);
      foreach (auto scr, scrs) {
        painter.drawPixmap(QPoint(p, 0), scr);
        p += scr.width();
      }
      return final;
    }