I have the following code to take a bitmap of a portion of the screen specified by the Box Area.
Area is just a struct that holds Width, Height, X1, Y1, X2, Y2 and represents a box. Basically a RECT with additional features.
For some reason, if Box is (0, 0, 100, 100); It will take a perfect screenshot of the 100x100 area. If Box's X1 or Y1 is more than 0 (Ex: (10, 10, 110, 110); It will take a screenshot that is 100x100, except that the first 10 rows and columns will be black! It also does this for any window that I specify that is not the desktop. I cannot figure out why! I tried everything from changing Bitblt to the correct area and offsets, etc.
Any Ideas?
Bitmaps::Bitmaps(HWND Window, Box Area, uint32_t BitsPerPixel) : Pixels(nullptr), width(Area.W), height(Area.H), size(0), TransparentColor(Rgb(0)), DC(0), Image(0)
{
memset(&Info, 0, sizeof(BITMAPINFO));
HDC hdc = GetDC(Window);
BITMAP bmp;
HBITMAP hbmp = (HBITMAP)GetCurrentObject(hdc, OBJ_BITMAP);
if (GetObject(hbmp, sizeof(BITMAP), &bmp) == 0)
ErrorMessage(ERROR_INVALID_WINDOW_HANDLE);
width = (Area.W == 0) ? bmp.bmWidth : Area.W;
height = (Area.H == 0) ? bmp.bmHeight : Area.H;
HDC MemDC = GetDC(0);
HDC bufferDC = CreateCompatibleDC(MemDC);
HBITMAP bufferBitmap = CreateCompatibleBitmap(MemDC, width, height);
DeleteObject(SelectObject(bufferDC, bufferBitmap));
BitBlt(bufferDC, Area.X1, Area.Y1, width, height, hdc, Area.X1, Area.Y1, SRCCOPY);
size = ((width * BitsPerPixel + 31) / 32) * 4 * height;
Info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
Info.bmiHeader.biWidth = width;
Info.bmiHeader.biHeight = height;
Info.bmiHeader.biPlanes = 1;
Info.bmiHeader.biBitCount = BitsPerPixel;
Info.bmiHeader.biCompression = BI_RGB;
Info.bmiHeader.biSizeImage = size;
bFileHeader.bfType = 0x4D42;
bFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(Info.bmiHeader);
bFileHeader.bfSize = bFileHeader.bfOffBits + size;
unsigned char* TEMP = new unsigned char[size];
GetDIBits(bufferDC, bufferBitmap, 0, height, TEMP, &Info, DIB_RGB_COLORS);
DeleteDC(bufferDC);
DeleteObject(bufferBitmap);
ReleaseDC(0, MemDC);
ReleaseDC(Window, hdc);
unsigned char* BuffPos = TEMP;
height = (height < 0 ? -height : height);
Pixels = new RGB[width * height];
for (int I = 0; I < height; I++)
{
for (int J = 0; J < width; J++)
{
Pixels[(height - 1 - I) * width + J].RGBA.B = *(BuffPos++);
Pixels[(height - 1 - I) * width + J].RGBA.G = *(BuffPos++);
Pixels[(height - 1 - I) * width + J].RGBA.R = *(BuffPos++);
Pixels[(height - 1 - I) * width + J].RGBA.A = (Info.bmiHeader.biBitCount > 24 ? *(BuffPos++) : 0);
}
if(Info.bmiHeader.biBitCount == 24)
BuffPos += width % 4;
}
delete[] TEMP;
}