Link to home
Start Free TrialLog in
Avatar of jadowdl
jadowdl

asked on

Difficulties with Screen Capture, C/C++...

Hi all.  I haven't really ever done any Windows programming before a week ago (done plenty of console/dos programming, but never anything with Windows API).  Decided to give it a whirl.  Probably should have done the beginner's stuff, but what's learning without a challenge? ;-)

The program is a screen capture application.  The function is a process that grabs the entire screen, copies it to a CBitmap, and then uses GetDIBits to convert that image to a BYTE array, every three bytes representing an R, G, and B component.  The Problem is that GetDIBits fails (perhaps along with other calls that are failing that I'm not realizing...).  

I've written everything below based on various code snippets both from this site and internet articles.  I think I understand what's going on, but obviously I don't understand everything, as I would then be able to debug and figure out what's going wrong.  Please keep in mind when answering that I've only been at Windows Programming for a week - I know C and C++ but not Windows API/typedefs

CODE:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
      //Other code goes here...

      RECT rc;
      ::GetWindowRect(::GetDesktopWindow(), &rc);

      //Something said GetDIBits doesn't work on Bitmaps > 64K, for debug administratively set screen width/height to 10
      int width = 10;  //rc.right - rc.left;
      int height = 10;  //rc.bottom - rc.top;

      CRect r(0,0, width, height);
      CBitmap screenshot;
      BYTE *screen = new BYTE[width*height*3];

      Capture(&screenshot, r, screen);
      
      //Other code goes here...

      delete[] screen;
      return 0;
      
}

//Modified from a previous expert's exchange post
void Capture(CBitmap * bmp, CRect const & r, BYTE *storage)  // r in screen coords
   {
      //Get Actual Bitmap, store it in bmp
    CDC dc;
    HWND wnd = ::GetDesktopWindow();
    HDC hdc = ::GetWindowDC(wnd);
    dc.Attach(hdc);

    CDC memDC;
    memDC.CreateCompatibleDC(&dc);

    CSize sz(r.Width(), r.Height());
    if(bmp->CreateCompatibleBitmap(&dc, sz.cx, sz.cy)==0)
            cerr<<"ERROR 1!"<<endl;
    CBitmap * oldbm = (CBitmap *)memDC.SelectObject(&bmp);
    if(memDC.BitBlt(r.left, r.top, r.Width(), r.Height(), &dc, 0, 0, SRCCOPY)==0)
            cerr<<"ERROR! 2"<<endl;

    //It would be handy if I could somehow debug bmp now, but I don't know how...assume it got set right...



      //Convert that bmp to 24 bit pixels in a BYTE array
      memDC.SelectObject(oldbm);  //make sure the bmp we're after isn't currently selected, also reset object context to original status...

      HBITMAP realbmp = (HBITMAP)(&bmp);
      BITMAPINFOHEADER header;
            header.biWidth = r.Width();
            header.biHeight = r.Height();
            header.biBitCount = 24;
            
            header.biSize            = sizeof(BITMAPINFOHEADER);
            header.biPlanes             = 1;
            header.biBitCount            = 24;
            header.biCompression      = BI_RGB;
            header.biSizeImage            = 0;
            header.biXPelsPerMeter      = 0;
            header.biYPelsPerMeter      = 0;
            header.biClrUsed            = 0;
            header.biClrImportant      = 0;

      BITMAPINFO info;
            info.bmiHeader = header;
      if(GetDIBits(memDC, realbmp, 0, r.Height(), storage, &info, DIB_RGB_COLORS)==0)
            cerr<<"Error 4!"<<endl;

    //Cleanup
    ::ReleaseDC(wnd, dc.Detach());
    ::ReleaseDC(wnd, memDC.Detach());
    }

//END CODE

Naturally, cerr shows "Error 4!", and the bytes in screen never get changed from default state.
Any ideas as to what's going wrong?  Thanks.

-jadowdl
ASKER CERTIFIED SOLUTION
Avatar of Roshan Davis
Roshan Davis
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial