GetDIBits устанавливает буфер изображения на все 0 (все черные)
Попытка сделать снимок окна в виде растрового изображения. Приведенный ниже код создает растровое изображение правильного размера, но каждый пиксель черный. Другими словами, GetDIBits устанавливает imageBuffer на все 0.
Размещенный код сохраняет растровое изображение для каждого открытого и видимого на экране блокнота. Ни одно из утверждений не выполнено.
BITMAPFILEHEADER и фактическая запись в файл опущены, потому что последний цикл for с утверждениями показывает, что GetDIBits устанавливает imageBuffer со всеми 0, поэтому нет необходимости проверять код после этой точки.
(В свойствах исполняемого файла, в разделе "Свойства конфигурации" -> "Основные", я установил "Не установлен" для набора символов, чтобы избежать необходимости в 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>(¬epadWindows));
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, ¬epadWindowRectangle)) {
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 ответ
К сожалению. Помогает дать BitBlt notepadWindowRectangle.top вместо notepadWindowRectangle.right для его параметра y1. Исправление, которое заставляет это работать.