0

I use this code to capture the desktop:

Frame::Frame()
{
    source_win=GetDesktopWindow();
    RECT r;
    GetWindowRect(source_win,&r);
    width=r.right;
    height=r.bottom;

    source_context=GetDC(source_win);
    sink_context=CreateCompatibleDC(source_context);
    sink_bitmap=CreateCompatibleBitmap(source_context,width,height);
    old_obj=SelectObject(sink_context,sink_bitmap);

    memset(&info_out,0,sizeof(info_out));
    info_out.bmiHeader.biSize=sizeof(info_out.bmiHeader);
    GetDIBits(source_context,sink_bitmap,0,0,NULL,&info_out,DIB_RGB_COLORS);
    info_out.bmiHeader.biBitCount=24;
    info_out.bmiHeader.biCompression=BI_RGB;
    bitmapdata=malloc(getScanlineSize(info_out.bmiHeader.biWidth
        ,info_out.bmiHeader.biBitCount)
        *info_out.bmiHeader.biHeight);
    p_rows=(void**)malloc(sizeof(void*)*info_out.bmiHeader.biHeight);
    for(int k=0;k<info_out.bmiHeader.biHeight;k++)
    {
        p_rows[info_out.bmiHeader.biHeight-k-1]=(char*)bitmapdata +     k*getScanlineSize(info_out.bmiHeader.biWidth,info_out.bmiHeader.biBitCount);
    }
}

void Frame::capture()
{
    BitBlt(sink_context,0,0,width,height,source_context,0,0,SRCCOPY|CAPTUREBLT);
    GetDIBits(sink_context,sink_bitmap,0,info_out.bmiHeader.biHeight
            ,bitmapdata,&info_out,DIB_RGB_COLORS);
}

Frame::~Frame()
{
    free(p_rows);
    free(bitmapdata);
    SelectObject(sink_context,old_obj);
    DeleteObject(sink_bitmap);
    DeleteDC(sink_context);
    ReleaseDC(source_win,source_context);
}

Provided that at least one double buffered application is running, this works well on Windows XP for capturing a fullscreen OpenGL app. However, in Windows 7, it only produces black frames. How to modify the code to get it work again?

If it matters, I am running the 64-bit edition. Detours is not an option due to incompatible license.

EDIT: The code works perfectly for non-fullscreen applications. The problem is that the DesktopWindow is black when a fullscreen application is running.

user877329
  • 6,717
  • 8
  • 46
  • 88
  • You do know this is terrible code right? You are using c-style casts, `malloc/free`, void pointers, ... . You should really clean that up. – KillianDS Jul 19 '12 at 08:33
  • Most of the void pointers comes from GDI objects. And raw malloc because I need a block of bitmap data, then pointers to each row. If not introducing more wrapper classes there is nothing I can do. – user877329 Jul 19 '12 at 10:26
  • @user877329: I think KillianDS was suggesting using new/delete instead of malloc/free. Also in C++ you should use `static_cast(expression)` instead of C style cast. Of course using new/delete you don't have to cast at all. – datenwolf Jul 19 '12 at 12:17
  • yes, but the pixel buffer has no specific type. It is just a block of raw memory. Is this better? bitmapdata=new char[...]; //Works because every pointer can implicity be casted to a void* – user877329 Jul 19 '12 at 12:53

0 Answers0