I can successfully capture parts of the screen using BitBlt and GetDIBits thanks to the code in Nick Nougat's answer here.
Capturing the entire screen or desktop seems to work but when I provide the HDC of an app, it prints weird data (in bgra format).
HWND dekstopHWND = GetDesktopWindow();
// prints correct desktop pixels
HWND appHWND = FindWindowA(NULL, "Hello World!"); // working handle of an electron app
//prints 0 0 0 0 as pixels
HWND appHWND = FindWindowA(NULL, "Untitled - Notepad"); // Notepad app
//prints 255 255 255 0 as pixels
...
- The function
GetDeviceCaps
says that the electron app supportsBitBlt
and the deviceTECHNOLOGY
israster display
. - The width of the app's DC is always full screen, independent of the window size:
printf("width %d\n", GetDeviceCaps(GetDC(appHWND), HORZRES)); //1920
, is that correct behaviour?
I'm very new to Windows API... Which one of the steps or functions can be causing this? Thank you.
....
HBITMAP GetScreenBmp(HDC hdc) {
int nScreenWidth = 100;
int nScreenHeight = 100;
HDC hCaptureDC = CreateCompatibleDC(hdc);
HBITMAP hBitmap = CreateCompatibleBitmap(hdc, nScreenWidth, nScreenHeight);
HGDIOBJ hOld = SelectObject(hCaptureDC, hBitmap);
BitBlt(hCaptureDC, 0, 0, nScreenWidth, nScreenHeight, hdc, 0, 0, SRCCOPY | CAPTUREBLT);
SelectObject(hCaptureDC, hOld); // always select the previously selected object once done
DeleteDC(hCaptureDC);
return hBitmap;
}
int main() {
HWND appHWND = FindWindowA(NULL, "Hello World!");
HDC hdc = GetDC(appHWND);
HBITMAP hBitmap = GetScreenBmp(hdc);
BITMAPINFO MyBMInfo = { 0 };
MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);
// Get the BITMAPINFO structure from the bitmap
if (0 == GetDIBits(hdc, hBitmap, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS)){
cout << "error" << endl;
}
// create the bitmap buffer
BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];
// Better do this here - the original bitmap might have BI_BITFILEDS, which makes it
// necessary to read the color table - you might not want this.
MyBMInfo.bmiHeader.biCompression = BI_RGB;
// get the actual bitmap buffer
if (0 == GetDIBits(hdc, hBitmap, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixels, &MyBMInfo, DIB_RGB_COLORS)) {
cout << "error2" << endl;
}
for (int i = 0; i < 100; i++) {
printf("%d\t", (int)lpPixels[i]);
}
DeleteObject(hBitmap);
ReleaseDC(NULL, hdc);
delete[] lpPixels;
return 0;
}