GetDIBits将图像缓冲区设置为全0(全黑)

时间:2015-03-25 08:51:47

标签: c++ windows gdi bitblt getdibits

尝试将窗口的屏幕截图作为位图。下面的代码是创建一个大小合适的位图,但每个像素都是黑色的。换句话说,GetDIBits正在将imageBuffer设置为全部0。

发布的代码为每个在屏幕上打开和显示的记事本保存位图。没有一个断言失败。

BITMAPFILEHEADER和文件的实际写入被省略,因为带有断言的最终for循环显示GetDIBits将imageBuffer设置为全0,所以在那之后不需要检查代码。

(在可执行文件的属性中,在Configuration Properties-> General下,我将字符集设置为"未设置"以避免unicode必需品。)

#include "stdafx.h"

#include <vector>
#include <sstream>
#include <Windows.h>
#include <iostream>
#include <assert.h>
using namespace std;

BOOL CALLBACK getNotepadWindowsCallback(HWND window, LPARAM notepadWindowsLparam) {
    if (NULL != GetParent(window)) {
        return true;
    }
    if (false == IsWindowVisible(window)) {
        return true;
    }
    char text[1024] = { 0 };
    GetWindowText(window, text, sizeof(text));
    if (NULL == strstr(text, " - Notepad")) {
        return true;
    }
    reinterpret_cast<vector<HWND>*>(notepadWindowsLparam)->push_back(window);
    return true;
}

vector<HWND> getNotepadWindows() {
    vector<HWND> notepadWindows;
    EnumWindows(getNotepadWindowsCallback, reinterpret_cast<LPARAM>(&notepadWindows));
    return notepadWindows;
}

int _tmain(int argc, _TCHAR* argv[]) {
    for (HWND notepadWindow : getNotepadWindows()) {
        HDC notepadWindowDeviceContext = GetDC(notepadWindow);
        assert(NULL != notepadWindowDeviceContext);
        HDC memoryDeviceContext = CreateCompatibleDC(notepadWindowDeviceContext);
        assert(NULL != memoryDeviceContext);

        RECT notepadWindowRectangle;
        if (0 == GetClientRect(notepadWindow, &notepadWindowRectangle)) {
            assert(true == false);
        }
        SIZE notepadWindowSize;
        notepadWindowSize.cx = notepadWindowRectangle.right - notepadWindowRectangle.left + 1;
        notepadWindowSize.cy = notepadWindowRectangle.bottom - notepadWindowRectangle.top + 1;

        HBITMAP memoryBitmap = CreateCompatibleBitmap(notepadWindowDeviceContext, notepadWindowSize.cx, notepadWindowSize.cy);
        assert(NULL != memoryBitmap);
        HBITMAP defaultBitmap = static_cast<HBITMAP>(SelectObject(memoryDeviceContext, memoryBitmap));
        assert(NULL != defaultBitmap);

        assert(TRUE == BitBlt(memoryDeviceContext, 0, 0, notepadWindowSize.cx, notepadWindowSize.cy, notepadWindowDeviceContext, notepadWindowRectangle.left, notepadWindowRectangle.right, SRCCOPY));

        BITMAPINFO bitmapinfo = { 0 };
        bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bitmapinfo.bmiHeader.biWidth = notepadWindowSize.cx;
        bitmapinfo.bmiHeader.biHeight = notepadWindowSize.cy;
        bitmapinfo.bmiHeader.biPlanes = 1;
        bitmapinfo.bmiHeader.biBitCount = 4 * 8;
        bitmapinfo.bmiHeader.biCompression = BI_RGB;
        //bitmapinfo.bmiHeader.biSizeImage, per MSDN, may be set to zero for BI_RGB bitmaps

        int imageBufferSize = notepadWindowSize.cx*notepadWindowSize.cy;
        int* imageBuffer = new(int[imageBufferSize]);
        // doing a memset here to initialize imageBuffer to 0's makes no change - leaving it out makes clear GetDIBits is setting imageBuffer to 0's, because it goes in with random garbage
        assert(NULL != SelectObject(memoryDeviceContext, defaultBitmap)); // this must happen before GetDIBits, per MSDN, so memoryBitmap is not selected into a device context
        int returnValue = GetDIBits(memoryDeviceContext, memoryBitmap, 0, notepadWindowSize.cy, static_cast<LPVOID>(imageBuffer), &bitmapinfo, DIB_RGB_COLORS);
        assert(0 != returnValue);
        cout << "returnValue is " << returnValue << endl; // shows proper number of lines is written
        for (int i = 0; i < imageBufferSize; ++i) {
            assert(0 == imageBuffer[i]);
        }

        DeleteDC(memoryDeviceContext);
        ReleaseDC(NULL, notepadWindowDeviceContext);
    }
}

1 个答案:

答案 0 :(得分:0)

糟糕。有助于为其y1参数提供BitBlt notepadWindowRectangle.top而不是notepadWindowRectangle.right。修复它使它工作。