Performing full screen grab in windows

Posted by Steven Lu on Stack Overflow See other posts from Stack Overflow or by Steven Lu
Published on 2010-05-14T05:16:31Z Indexed on 2010/05/14 5:24 UTC
Read the original article Hit count: 261

Filed under:
|
|
|
|

I am working an idea that involves getting a full capture of the screen including windows and apps, analyzing it, and then drawing items back onto the screen, as an overlay.

I want to learn image processing techniques and I could get lots of data to work with if I can directly access the Windows screen. I could use this to build automation tools the likes of which have never been seen before. More on that later.

I have full screen capture working for the most part.

HWND hwind = GetDesktopWindow();
HDC hdc = GetDC(hwind);

int resx = GetSystemMetrics(SM_CXSCREEN);
int resy = GetSystemMetrics(SM_CYSCREEN);
int BitsPerPixel = GetDeviceCaps(hdc,BITSPIXEL);
HDC hdc2 = CreateCompatibleDC(hdc);

BITMAPINFO info;
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info.bmiHeader.biWidth = resx;
info.bmiHeader.biHeight = resy;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount  = BitsPerPixel;
info.bmiHeader.biCompression = BI_RGB;

void *data;
hbitmap = CreateDIBSection(hdc2,&info,DIB_RGB_COLORS,(void**)&data,0,0);
SelectObject(hdc2,hbitmap);

Once this is done, I can call this repeatedly:

BitBlt(hdc2,0,0,resx,resy,hdc,0,0,SRCCOPY);

The cleanup code (I have no idea if this is correct):

DeleteObject(hbitmap);
ReleaseDC(hwind,hdc);
if (hdc2) {
    DeleteDC(hdc2);
}

Every time BitBlt is called it grabs the screen and saves it in memory I can access thru data.

Performance is somewhat satisfactory. BitBlt executes in 50 milliseconds (sometimes as low as 33ms) at 1920x1200x32.

What surprises me is that when I switch display mode to 16 bit, 1920x1200x16, either through my graphics settings beforehand, or by using ChangeDisplaySettings, I get a massively improved screen grab time between 1ms and 2ms, which cannot be explained by the factor of two reduction in bit-depth. Using CreateDIBSection (as above) offers a significant speed up when in 16-bit mode, compared to if I set up with CreateCompatibleBitmap (6-7ms/f).

Does anybody know why dropping to 16bit causes such a speed increase? Is there any hope for me to grab 32bit at such speeds? if not for the color depth, but for not forcing a change of screen buffer modes and the awful flickering.

© Stack Overflow or respective owner

Related posts about c++

Related posts about screenshot