Search code examples
c++windowswinapibitmaphwnd

Bitmap from program child window returns as black


Current situation: I have a program called "NoxPlayer" which is basically an android emulator. I also have a c++ program which locates the window handle of said NoxPlayer and makes a bitmap of the current state of the window and saves it to the clipboard.

But here comes the problem.


This is how the program looks to me: NoxPlayer

And this is what it saves in the clipboard: Clipboard

But this is what i want: Image


I could have simple cut the top part of the bitmap but what i wish to try and do is get the inner part of the window as seen here Image without cutting the bitmap.

I first tried going down the window hierarchy and getting the bitmap of child windows but what i got was black bitmaps as seen here: Black window

Window hierarchy as seen from Microsoft Spy++: Hierarchy

The ones i marked around with red color are the ones i tried to get a bitmap from, since ScreenBoardClassWindow and all its children fall into this Box when checking their position by highlighting them in Microsoft Spy++


This is the code i used to create a bitmap and save it to the clipboard:

  RECT rc;
  GetClientRect(NoxHandle, &rc);

  //create
  HDC hdcScreen = GetDC(NULL);
  HDC hdc = CreateCompatibleDC(hdcScreen);
  HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen,rc.right - rc.left, rc.bottom - rc.top);
  SelectObject(hdc, hbmp);

  //Print to memory hdc
  PrintWindow(NoxHandle, hdc, PW_CLIENTONLY);

  //copy to clipboard
  OpenClipboard(NULL);
  EmptyClipboard();
  SetClipboardData(CF_BITMAP, hbmp);
  CloseClipboard();

  //release
  DeleteDC(hdc);
  DeleteObject(hbmp);
  ReleaseDC(NULL, hdcScreen);

Code is taken from here: Link


Thanks in advance


EDIT The window i use to currently get the bitmap from is the Program Parent window "NoxPlayer". When using any of the children windows I get the black bitmap problem.


Solution

  • Find the right window, example, QWidgetClassWindow then use GetWindowRect to find the coordinates in relation to desktop window. Use BitBlt instead of PrintWindow.

    With this example the target application must be visible on the screen. It should not be obstructed by other windows.

    RECT rc;
    HWND hwnd = h_QWidgetClassWindow;
    GetWindowRect(hwnd, &rc);
    int w = rc.right - rc.left;
    int h = rc.bottom - rc.top;
    
    Sleep(3000);
    //create
    HDC hdc = GetDC(0);
    HDC memdc = CreateCompatibleDC(hdc);
    HBITMAP hbmp = CreateCompatibleBitmap(hdc, w, h);
    HBITMAP oldbmp = (HBITMAP)SelectObject(memdc, hbmp);
    
    BitBlt(memdc, 0, 0, w, h, hdc, rc.left, rc.top, SRCCOPY);
    SelectObject(memdc, oldbmp);
    
    //copy to clipboard
    OpenClipboard(NULL);
    EmptyClipboard();
    SetClipboardData(CF_BITMAP, hbmp);
    CloseClipboard();
    
    //release
    DeleteDC(memdc);
    DeleteObject(hbmp);
    ReleaseDC(0, hdc);
    

    Also make sure your application is DPI aware, so that it gets the right coordinates.