VS2008、MFC、C++ プロジェクトで、ウィンドウの内容 (クライアント領域) をキャプチャしたいと考えています。ここで説明されている PrintWindow 手法を使用してみました: C++ でウィンドウのスクリーンショットをビットマップ オブジェクトとして取得する方法は?
次のコードを使用して、ウィンドウの内容をブリットすることも試みました。
void captureWindow(int winId)
{
HDC handle(::GetDC(HWND(winId)));
CDC sourceContext;
CBitmap bm;
CDC destContext;
if( !sourceContext.Attach(handle) )
{
printf("Failed to attach to window\n");
goto cleanup;
}
RECT winRect;
sourceContext.GetWindow()->GetWindowRect(&winRect);
int width = winRect.right-winRect.left;
int height = winRect.bottom-winRect.top;
destContext.CreateCompatibleDC( &sourceContext );
if(!bm.CreateCompatibleBitmap(&sourceContext, width, height)) {
printf("Failed to create bm\n");
goto cleanup;
}
{
//show a message in the window to enable us to visually confirm we got the right window
CRect rcText( 0, 0, 0 ,0 );
CPen pen(PS_SOLID, 5, 0x00ffff);
sourceContext.SelectObject(&pen);
const char *msg = "Window Captured!";
sourceContext.DrawText( msg, &rcText, DT_CALCRECT );
sourceContext.DrawText( msg, &rcText, DT_CENTER );
HGDIOBJ hOldDest = destContext.SelectObject(bm);
if( hOldDest==NULL )
{
printf("SelectObject failed with error %d\n", GetLastError());
goto cleanup;
}
if ( !destContext.BitBlt( 0, 0, width, height, &sourceContext, 0, 0, SRCCOPY ) ){
printf("Failed to blit\n");
goto cleanup;
}
//assume this function saves the bitmap to a file
saveImage(bm, "capture.bmp");
destContext.SelectObject(hOldDest);
}
cleanup:
destContext.DeleteDC();
sourceContext.Detach();
::ReleaseDC(0, handle);
}
このコードは、ほとんどのアプリケーションで正常に機能します。ただし、スクリーンショットをキャプチャする必要がある特定のアプリケーションには、OpenGl または Direct3D を使用してレンダリングされたと思われるウィンドウがあります。どちらの方法でも、アプリの大部分を問題なくキャプチャできますが、「3D」領域は黒く残るか文字化けします。
私はアプリケーション コードにアクセスできないため、変更することはできません。
「3d」ウィンドウを含むすべてのコンテンツをキャプチャする方法はありますか?