c++ - 重复调用 CreateCompatibleBitmap() 最终因 GetLastError() == 6 失败

标签 c++ winapi

我有一个程序每秒截取一次屏幕截图并计算屏幕的平均颜色。然而,大约 45 分钟的运行后,我的检查 if ((OffscrBmp = CreateCompatibleBitmap(bitmapDC, nScreenWith, nScreenHeight)) == NULL)

开始返回 true。对 GetLastError() 的调用返回 6,但我似乎找不到关于这意味着什么的任何文档。

为什么对该函数的数千次调用都能正常工作,然后突然每次调用都失败了?

这是我的全部功能:

COLORREF ScreenColourCapture::getScreenColour() {
    // Most of this is adapted from http://www.cplusplus.com/forum/beginner/25138/
    LPBITMAPINFO lpbi = NULL;
    HBITMAP OffscrBmp = NULL;
    HDC OffscrDC = NULL;
    int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
    int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
    HDC bitmapDC = CreateCompatibleDC(0);
    HBITMAP hBmp = CreateCompatibleBitmap(GetDC(0), nScreenWidth, nScreenHeight);
    SelectObject(bitmapDC, hBmp);
    BitBlt(bitmapDC, 0, 0, nScreenWidth, nScreenHeight, GetDC(0), 0, 0, SRCCOPY);
    if ((OffscrBmp = CreateCompatibleBitmap(bitmapDC, nScreenWidth, nScreenHeight)) == NULL) {
        int error = GetLastError();
        logging->error("CreateCompatibleBitmap failed!");
        return 0;
    }
    if ((OffscrDC = CreateCompatibleDC(bitmapDC)) == NULL) {
        logging->error("CreateCompatibleDC failed!");
        return 0;
    }
    HBITMAP OldBmp = (HBITMAP)SelectObject(OffscrDC, OffscrBmp);
    BitBlt(OffscrDC, 0, 0, nScreenWidth, nScreenHeight, bitmapDC, 0, 0, SRCCOPY);
    if ((lpbi = (LPBITMAPINFO)(new char[sizeof(BITMAPINFOHEADER)+256 * sizeof(RGBQUAD)])) == NULL)
        return 0;
    ZeroMemory(&lpbi->bmiHeader, sizeof(BITMAPINFOHEADER));
    lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    SelectObject(OffscrDC, OldBmp);

    // First, call GetDIBits with no pixel array. This way it will populate bitmapinfo for us. Then
    // call it with the pixel array and the now populated lpbi.
    GetDIBits(OffscrDC, OffscrBmp, 0, nScreenHeight, NULL, lpbi, DIB_RGB_COLORS);
    LPVOID lpvBits = new char[lpbi->bmiHeader.biSizeImage];
    GetDIBits(OffscrDC, OffscrBmp, 0, nScreenHeight, lpvBits, lpbi, DIB_RGB_COLORS);

    // Pass BMP data off for computation
    COLORREF averageColour = getMeanColourFromPixels((BYTE *)lpvBits, lpbi);

    // Wrap things up
    delete[] lpvBits;
    delete[] lpbi;
    DeleteObject(hBmp);
    DeleteObject(OldBmp);
    DeleteObject(OffscrBmp);
    ReleaseDC(GetDesktopWindow(), bitmapDC);
    DeleteDC(OffscrDC);

    return averageColour;
}

我的其余代码在这里,因为它的值(value):https://github.com/crummy/screenglow/tree/master/ConsoleApplication1

最佳答案

您必须先从 HDC 中取消选择位图,然后才能销毁它,否则您就是在泄漏它。它是这样的:

HBITMAP hBmp = CreateCompatibleBitmap(...);
HBITMAP previousBitmap = (HBITMAP)SelectObject(bitmapDC, hBmp);
// ...
SelectObject(bitmapDC, previousBitmap);
DeleteObject(hBmp);

此外,您调用 GetDC(0) 但不保存返回值,因此您不能 ReleaseDC 它。此外,bitmapDC 是由 CreateCompatibleDC 创建的,应该使用 DeleteObject 而不是 ReleaseDC 来删除。

关于c++ - 重复调用 CreateCompatibleBitmap() 最终因 GetLastError() == 6 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25829796/

相关文章:

delphi - 在delphi中调用DLL时发生异常?

c++ - 在 WM_INPUT 消息中寻找键重复数据

c++ - Windows 是进入休眠模式还是使用 C++ 休眠?

C++ 时间() 函数

c++ - unique_ptr 到 nullptr 是不可复制的

c++ - 如何使用 rad studio 显示窗口总数?

winapi - 使用 SetWinEventHook Hook 窗口有时不起作用

c++ - Visual Studio 中的 Decltype 转换运算符

c++ - 是否有必要在 main 的末尾解锁互斥量?

c++ - 如何将 `std::lower_bound` 与这个定制容器一起使用?