Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to capture a screenshot of the whole QMainWindow with title bar?
Forum Updated to NodeBB v4.3 + New Features

How to capture a screenshot of the whole QMainWindow with title bar?

Scheduled Pinned Locked Moved General and Desktop
6 Posts 2 Posters 7.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    rushmore
    wrote on last edited by
    #1

    I tried QWidget::grab() and render() methods. Both only captures the client area. Is it possible to capture the whole window including title bar and status bar?

    Thanks!

    1 Reply Last reply
    0
    • jazzycamelJ Offline
      jazzycamelJ Offline
      jazzycamel
      wrote on last edited by
      #2

      As the titlebar and window frame are managed by the operating system rather than Qt this is a non-trivial problem. There are two approaches:

      1. If you are only catering for one OS then look into using the native API (I've done this for MacOSX for instance).

      2. As the desktop is accessible as a widget via QDesktopWidget() you can use grabWidget() to get a screen grab and then use QPixmap.copy() combined with your window's geometry() to crop it to the correct size. I might have an example of this somewhere...

      Hope this helps ;o)

      For the avoidance of doubt:

      1. All my code samples (C++ or Python) are tested before posting
      2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
      1 Reply Last reply
      0
      • R Offline
        R Offline
        rushmore
        wrote on last edited by
        #3

        Thanks for the reply. I did think about the 2nd approach. But you have to make the window on top of the desktop. If there is no other option, I'll have to go with this one. I'm only on Mac OS X but I don't know much about native API. Would you mind sharing your code of the 1st approach?

        Thank you again!

        1 Reply Last reply
        0
        • jazzycamelJ Offline
          jazzycamelJ Offline
          jazzycamel
          wrote on last edited by
          #4

          As you're on Mac I can probably give you worked examples of both some point tomorrow (when I'm back at my desk).

          For the avoidance of doubt:

          1. All my code samples (C++ or Python) are tested before posting
          2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
          1 Reply Last reply
          0
          • jazzycamelJ Offline
            jazzycamelJ Offline
            jazzycamel
            wrote on last edited by
            #5

            Hi Rushmore,

            The following is a worked example that demonstrates both screen capture methods described previously:

            ScreenShot.pro
            @
            QT += core gui

            TARGET = ScreenShot
            TEMPLATE = app

            SOURCES += main.cpp
            mainwindow.cpp

            HEADERS += mainwindow.h

            LIBS += -framework Carbon
            @

            mainwindow.h
            @
            #ifndef MAINWINDOW_H
            #define MAINWINDOW_H

            #include <QtGui>

            class MainWindow : public QMainWindow
            {
            Q_OBJECT

            public:
            MainWindow(QWidget *parent = 0);
            ~MainWindow();

            private:
            int titleBarHeight();

            QLabel *label;
            

            private slots:
            void takeQtScreenShot();
            void takeNativeScreenShot();
            void clearScreenShot();
            };

            #endif // MAINWINDOW_H
            @

            mainwindow.cpp
            @
            #include <Carbon/Carbon.h>
            #include "mainwindow.h"

            MainWindow::MainWindow(QWidget *parent)
            : QMainWindow(parent)
            {
            QWidget *cw=new QWidget(this);
            QVBoxLayout *l=new QVBoxLayout(cw);

            QPushButton *qtb=new QPushButton("Qt Screen Shot", this);
            connect(qtb, SIGNAL(clicked()), this, SLOT(takeQtScreenShot()));
            l->addWidget(qtb);
            
            QPushButton *nb=new QPushButton("Native Screen Shot", this);
            connect(nb, SIGNAL(clicked()), this, SLOT(takeNativeScreenShot()));
            l->addWidget(nb);
            
            QPushButton *cb=new QPushButton("Clear Screen Shot", this);
            connect(cb, SIGNAL(clicked()), this, SLOT(clearScreenShot()));
            l->addWidget(cb);
            
            label=new QLabel(this);
            
            l->addWidget(label);
            setCentralWidget(cw);
            

            }

            MainWindow::~MainWindow(){}

            int MainWindow::titleBarHeight(){
            QStyleOptionTitleBar options;
            options.initFrom(this);

            return this->style()->pixelMetric(
                       QStyle::PM_TitleBarHeight,
                        &options,
                        this)-4;
            

            }

            void MainWindow::takeQtScreenShot(){
            QDesktopWidget dw;
            QWidget *screen=dw.screen(dw.screenNumber(this));

            QRect rect=geometry();
            int tbh=titleBarHeight();
            QPixmap p=QPixmap::grabWindow(
                        screen->winId(),
                        rect.x(),
                        rect.y()-tbh,
                        rect.width(),
                        rect.height()+tbh);
            label->setPixmap(p);
            

            }

            void MainWindow::takeNativeScreenShot(){
            QRect rect=this->geometry();
            CGRect captureRect;
            int tbh=titleBarHeight();
            captureRect.origin.x=rect.x();
            captureRect.origin.y=rect.y()-tbh;
            captureRect.size.width=rect.width();
            captureRect.size.height=rect.height()+tbh;

            CGImageRef img=CGWindowListCreateImage(
                        captureRect,
                        kCGWindowListOptionOnScreenOnly,
                        kCGNullWindowID,
                        kCGWindowImageDefault);
            
            if(img==NULL){
                qDebug()<<"CGWindowListCreateImage failed!";
                return;
            }
            
            QTemporaryFile *tfile=new QTemporaryFile;
            if(!tfile->open()){
                qDebug()<<"Failed to open tfile";
                return;
            }
            
            CFStringRef file=CFStringCreateWithCString(
                        NULL,
                        tfile->fileName().toLocal8Bit().data(),
                        kCFStringEncodingUTF8);
            CFStringRef type=CFSTR("public.jpeg");
            CFURLRef urlRef = CFURLCreateWithFileSystemPath(
                        kCFAllocatorDefault,
                        file,
                        kCFURLPOSIXPathStyle,
                        false);
            CGImageDestinationRef idst=CGImageDestinationCreateWithURL(
                        urlRef, type, 1, NULL);
            CGImageDestinationAddImage(idst, img, NULL);
            CGImageDestinationFinalize(idst);
            
            label->setPixmap(QPixmap(tfile->fileName()));
            

            }

            void MainWindow::clearScreenShot(){
            label->setPixmap(QPixmap());
            }
            @

            main.cpp
            @
            #include "mainwindow.h"

            int main(int argc, char *argv[])
            {
            QApplication a(argc, argv);
            MainWindow w;
            w.show();

            return a.exec&#40;&#41;;
            

            }
            @

            Hope this helps ;o)

            For the avoidance of doubt:

            1. All my code samples (C++ or Python) are tested before posting
            2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
            1 Reply Last reply
            0
            • R Offline
              R Offline
              rushmore
              wrote on last edited by
              #6

              Got it. Thanks!

              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved