カンテラの光の下で

dNaga392's memorandom

【Qt】ウィジェットのスクリーンショット

メインウィンドウをスクリーンショットする

メインウィンドウのスクリーンショットを撮る場合、 QPixmap::grabWidget を利用する。

    // メインウィンドウのスクリーンショット
    pixmap = QPixmap::grabWidget( this );
    // クリップボードにビットマップをコピー
    QClipboard * clipboad = qApp->clipboard();
    clipboad->setPixmap( pixmap );

ただし、この場合ウィンドウフレームは含まれない。 これはウィンドウフレームがQtの処理範囲外のためである。

そのため、ウィンドウフレームを含める場合は、 より大きい範囲、スクリーンのスクリーンショットを撮ってトリミングをする。

    QDesktopWidget dw;
    QWidget * screen=dw.screen( dw.screenNumber(this) );
    QRect rect = geometry();
    WId wid = screen->winId();
    // タイトルバーの高さを取得
    QStyleOptionTitleBar options;
    options.initFrom(this);
    int tbh = this->style()->pixelMetric( QStyle::PM_TitleBarHeight, &options, this ) - 4;
    // QPixmap::grabWindow(WId,int,int,int,int) の実行に必要なアトリビュートを設定
    setAttribute( Qt::WA_TranslucentBackground );
    // ウィンドウフレーム描画の数値を設定
    // 以下の6変数はWin7の実測値のため、実行環境の影響を受ける
    const int fw = 8; ///< frame width
    const int fh = 5; ///< frame height
    const int cx = rect.x() - fw;                  ///< caption x
    const int cy = rect.y() - (tbh + fh - 3);      ///< caption y
    const int cw = rect.width() + fw * 2;          ///< caption width
    const int ch = rect.height() + (tbh + fh * 2); ///< caption height
    pixmap = QPixmap::grabWindow( wid, cx, cy, cw, ch );

    // スクリーン外の非表示部分も描画するため、
    // ウィジェット部分を再描画する。
    QPixmap pix_wdt = QPixmap::grabWidget( this );
    QPainter painter( &pixmap );
    painter.drawPixmap( fw, (tbh + fh - 3), pix_wdt );
    // クリップボードにビットマップをコピー
    QClipboard * clipboad = qApp->clipboard();
    clipboad->setPixmap( pixmap );

コメントに記載したようにリテラル整数は実測値のため、 環境によっては意図する結果が得られない場合がある。

MDIのサブウィンドウをスクリーンショットする

MDIサブウィンドウの場合、ウィンドウフレームもQtの処理範囲に含まれる。 そのため、QMdiSubWindow を QPixmap::grebWidget することでフレーム付きスクショが撮れる。

    // ウィンドウフレームを含むスクリーンショット
    QMdiSubWindow * activeWindow = mdiArea->activeSubWindow();
    if ( activeWindow == NULL)
    {
        return false;
    }
    Q_ASSERT( activeWindow );
    pixmap = QPixmap::grabWidget( activeWindow );
    // クリップボードにビットマップをコピー
    QClipboard * clipboad = qApp->clipboard();
    clipboad->setPixmap( pixmap );

ウィンドウフレームなしのスクリーンショットの場合、 QMdiSubWindow の widget を QPixmap::grebWidget することで得られる。

    // ウィンドウフレームを含まないスクリーンショット
    QMdiSubWindow * activeWindow = mdiArea->activeSubWindow();
    if ( activeWindow == NULL)
    {
        return false;
    }
    Q_ASSERT( activeWindow );
    pixmap = QPixmap::grabWidget( activeWindow->widget() );
    // クリップボードにビットマップをコピー
    QClipboard * clipboad = qApp->clipboard();
    clipboad->setPixmap( pixmap );

参考資料