【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 );
参考資料
- c++ - Qt grabWindow coordinates shifted from GetCursorPos and GetWindowRect - Stack Overflow
- c++ - Qt grabWindow coordinates shifted from GetCursorPos and GetWindowRect - Stack Overflow
- How to get window handle (HWND) of core application window on Win32 for QSpaceNavigator | Qt Forum
- Converting from Qt's WId to Windows HWND?
- QWidget Class | Qt Widgets 5.5