3

I want to capture the contents (client area) of a window, in my VS2008, MFC, C++ project. I have tried using the PrintWindow technique described here: How to get screenshot of a window as bitmap object in C++?

I have also tried blitting the contents of the window using the following code:

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);
}

The code works fine for most applications. The specific application where I need to capture the screenshot however, has a window that I think is rendered using OpenGl or Direct3D. Both methods will capture most of the app just fine, but the "3d" area will be left black or garbled.

I do not have access to the application code, so I cannot change it in any way.

Is there any way to capture all the contents, including the "3d" window?

Community
  • 1
  • 1
Vanvid
  • 83
  • 1
  • 9

1 Answers1

0

The data in your 3D area is generated by the graphics adapter further down the graphics funnel and may not be available to your application to read the byte data from the rendering context. In OpenGL you can can use glReadPixels() to pull that data back up the funnel into your application memory. See here for usage: http://www.opengl.org/sdk/docs/man/xhtml/glReadPixels.xml

Richard
  • 21
  • 3