Search code examples
c++winapimingwscreenshotoverlay

Performing full screen grab in windows


I am working on 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.


Solution

  • I solved my original question about the incredible speed up of switching to 16 bit color mode. Turns out it was causing the Aero theme to be disabled, which accounts for most of it. With Aero off in 32bit it is just about as fast.

    Link to other topic with a good answer.