0

Hi guys I have the following code:

#define ScreenXResolution GetDeviceCaps(GetDC(0), HORZRES)
#define ScreenYResolution GetDeviceCaps(GetDC(0), VERTRES)

BYTE *screenData = malloc(sizeof(BYTE) * (3 * ScreenXResolution * ScreenYResolution));
captureScreenshot(&screenData);

void captureScreenshot(BYTE *screenData)
{
    HDC hdc = GetDC(NULL), hdcMem = CreateCompatibleDC(hdc);
    HBITMAP hBitmap = CreateCompatibleBitmap(hdc, ScreenXResolution, ScreenYResolution);
    BITMAPINFOHEADER bmi = {0};
    bmi.biSize = sizeof(BITMAPINFOHEADER);
    bmi.biPlanes = 1;
    bmi.biBitCount = 24;
    bmi.biWidth = ScreenXResolution;
    bmi.biHeight = -ScreenYResolution;
    bmi.biCompression = BI_RGB;
    SelectObject(hdcMem, hBitmap);
    BitBlt(hdcMem, 0, 0, ScreenXResolution, ScreenYResolution, hdc, 0, 0, SRCCOPY);
    GetDIBits(hdc, hBitmap, 0, ScreenYResolution, screenData, (BITMAPINFO*)&bmi, DIB_RGB_COLORS);
    DeleteObject(hBitmap);
    DeleteDC(hdcMem);
    ReleaseDC(NULL, hdc);
}

What I'm trying to achieve is taking a screenshot of their screen and putting it in screenData.

The reason why I need that is so I can check if it's a certain RGB color at whichever position but I'm having issues doing so.

If anyone could help me out that would be greatly appreciated.

thanks!

edit: Added the memory allocation, The way I try to get the RGB is by a function returning a colorref like this:

COLORREF getRGBFromScreenshot(BYTE *screenshot, int x, int y)
{
    return RGB(screenshot[3 * ((y * ScreenXResolution) + x) + 2], screenshot[3 * ((y * ScreenXResolution) + x) + 1], screenshot[3 * ((y * ScreenXResolution) + x)]);
}
4

2 回答 2

3

You have one, perhaps two problems.

The first is that you pass the argument as an address of the pointer, i.e. BYTE **. However, you only use it as a single pointer. This means that when you call GetDIBits it will fill in on the wrong address. You should have gotten a warning about this by the compiler.

The second problem is more potential, as there might be code you don't show, but it's that you never initialize the screenData pointer. You don't seem to be allocating the memory to copy the bitmap data into.

Both of the above problems will lead to undefined behavior, which might seem to work sometimes but not correctly, or may crash at any time.


As for the pointer issue, a pointer is exactly what it name says: It points to something. In the case of your screenData pointer it can be visualized something like this:

+------------+      +---------------------------------+
| screenData | ---> | Memory allocated for screenData |
+------------+      +---------------------------------+

However, when you use the address-of operator & in the call to captureScreenshot, you are creating a new pointer to the screenData variable:

+-------------+      +------------+      +---------------------------------+
| &screenData | ---> | screenData | ---> | Memory allocated for screenData |
+-------------+      +------------+      +---------------------------------+

From the simple "pictures" above, it's easy to see why using &screenData will not work, it simply points to a completely different memory location.

于 2013-03-31T00:36:36.883 回答
0

As @Joachim Pileborg notes, screenData has to be pre-allocated an appropriately-sized buffer. If screenData is null, GetDIBits() only fills the BITMAPINFO structure (see here). If screenData is unassigned, it may point to a random part of memory and this will often cause crashes.

Either way, the code should check the return value from GetDIBits() to find out what is going on.

于 2013-03-31T00:38:57.360 回答