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(::GetDeskt opWindow() , &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->CreateCompatibleBi tmap(&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
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(::GetDeskt
//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(&
CSize sz(r.Width(), r.Height());
if(bmp->CreateCompatibleBi
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);
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.