遇到字节数组/捕获屏幕截图的问题

时间:2013-03-31 00:20:05

标签: c winapi

大家好我有以下代码:

#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);
}

我想要实现的是截取屏幕截图并将其放入screenData。

我之所以需要这样,我可以检查它是否在任何位置都是某种RGB颜色,但我遇到了这样的问题。

如果有人能帮助我,我将不胜感激。

谢谢!

编辑:添加了内存分配,我尝试获取RGB的方法是通过一个返回colorref的函数,如下所示:

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)]);
}

2 个答案:

答案 0 :(得分:3)

你有一个,也许是两个问题。

首先,您将参数作为指针的地址传递,即BYTE **。但是,您只将它用作单个指针。这意味着当您致电GetDIBits时,它会填写错误的地址。您应该已经由编译器发出警告。

第二个问题更具潜力,因为可能存在您未显示的代码,但是您永远不会初始化screenData指针。您似乎没有分配内存来将位图数据复制到。

上述两个问题都会导致未定义的行为,这些行为有时似乎有效但不正确,或者可能随时崩溃。


至于指针问题,指针正是它的名字所说的:它指向某个东西。对于screenData指针,可以将其显示为:

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

但是,当您在&的调用中使用地址操作符captureScreenshot时,您将创建一个指向screenData变量的新指针:

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

从上面的简单“图片”中,很容易看出为什么使用&screenData不起作用,它只是指向一个完全不同的内存位置。

答案 1 :(得分:0)

正如@Joachim Pileborg指出的那样,screenData必须预先分配一个适当大小的缓冲区。如果screenData为空,GetDIBits()仅填充BITMAPINFO结构(请参阅here)。如果screenData未分配,则可能指向内存的随机部分,这通常会导致崩溃。

无论哪种方式,代码都应检查GetDIBits()的返回值,以了解发生了什么。