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



  • 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!



  • 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)



  • 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!



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



  • 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)



  • Got it. Thanks!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.