1

I followed a tutorial to get a window on a HDC. I converted it to a bitmap to search a specific pixel. Normally this is faster than searching directly on a hdc. So I did it but when I loop to look the pixels it returns me 0 or 4294967295. I searched for this problem a long time but I can't find a solution.. I hope you can help me!

Here is my code:

void getPixel(HWND& _window) {
    
    COLORREF color;
    RECT rect;
    GetWindowRect(_window, &rect);
    HDC hdc = GetDC(_window);

    HDC hMemoryDC = CreateCompatibleDC(hdc);
    HBITMAP hbitmap = CreateCompatibleBitmap(hMemoryDC, rect.right - rect.left, rect.bottom - rect.top);
    HBITMAP hOldBitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, hbitmap));
    
    BitBlt(hMemoryDC, 0, 0, rect.right - rect.left, rect.bottom - rect.top, hdc, rect.left, rect.top, SRCCOPY);
    

    for (int i = 0; i < 2000; i++) {
        for (int j = 0; j < 2000; j++) {
            color = GetPixel(hMemoryDC, i, j);
            std::cout << "color = " << color << " " << GetRValue(color) << " " << GetGValue(color) << " " << GetBValue(color) << std::endl;
        }
    }
    

    ReleaseDC(_window, hdc);
    DeleteDC(hMemoryDC);
    DeleteObject(hbitmap);
    DeleteObject(hOldBitmap);
}

HWND _window returns me the correct window, I can print it with "PrintWindow" function and it works, so the problem is not there.

I put 2000 in the for loop but even with rect.right - rect.left and rect.bottom - rect.top it doesn't work. I tried to change this function: BitBlt(hMemoryDC, 0, 0, rect.right - rect.left, rect.bottom - rect.top, hdc, 0, 0, SRCCOPY); or: BitBlt(hMemoryDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, hdc, 0, 0, SRCCOPY);

I tried also to change GetDC(_window) to GetDC(NULL) but nothing works..

Hope you can help me! Thanks!

PsyKozZ09
  • 21
  • 3

1 Answers1

3

4294967295 (hex 0xFFFFFFFF) is CLR_INVALID, which means you are accessing invalid pixels. You should be using the window's actual width/height dimensions in your loop.

But also, you are retrieving, and copying pixels from, the window's HDC, but you are using the window's screen coordinates in the x1/y1 parameters of BitBlt(). Those parameters should be 0/0 instead, respectively, since the HDC represents just the window and not the whole screen.

Try this instead:

void getPixel(HWND hwnd) {
    
    RECT rect;
    GetWindowRect(hwnd, &rect);
    int width = rect.right - rect.left;
    int height = rect.bottom - rect.top;

    HDC hDC = GetDC(hwnd);
    HDC hMemoryDC = CreateCompatibleDC(hDC);
    HBITMAP hMemoryBmp = CreateCompatibleBitmap(hMemoryDC, width, height);
    HBITMAP hOldBitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, hMemoryBmp));
    
    BitBlt(hMemoryDC, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
    
    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            COLORREF color = GetPixel(hMemoryDC, i, j);
            std::cout << "color = " << color << " " << GetRValue(color) << " " << GetGValue(color) << " " << GetBValue(color) << std::endl;
        }
    }
    
    SelectObject(hMemoryDC, hOldBitmap);
    DeleteObject(hMemoryBmp);
    DeleteDC(hMemoryDC);
    ReleaseDC(hwnd, hDC);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thanks you! But I don't know why, now the color returns me just 0. I tried on the window paint, on file explorer (to check the pixels) and it returns me 0 too. As if the bitmap was black – PsyKozZ09 Nov 18 '22 at 08:00
  • What happens if you add error checking to your code? Is `hwnd` valid? Is `hdc` valid? `hMemoryDC`? Etc. Are any errors before reported by those APIs? Does it work if you call `GetPixel()` on `hDC`? What window exactly are you trying to capture pixels from? If the window has had `SetWindowDisplayAffinity()` called on it, you won't be able to access its pixels at all. What does `GetWindowDisplayAffinity()` report? – Remy Lebeau Nov 18 '22 at 15:26