0
試圖將窗口的屏幕截圖作爲位圖。下面的代碼是創建一個大小合適的位圖,但每個像素都是黑色的。換句話說,GetDIBits將imageBuffer設置爲全0。GetDIBits將圖像緩衝區設置爲全0(全黑)
發佈的代碼爲每個在屏幕上打開並可見的記事本保存一個位圖。沒有任何斷言失敗。
的BITMAPFILEHEADER和實際寫入到一個文件中被省略,因爲最後的循環與斷言設置ImageBuffer的所有0的節目的GetDIBits,所以沒有必要點後,檢查代碼。
(在可執行文件的屬性,在配置屬性 - >常規,我有字符設置爲「未設置」,以避免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);
}
}
此代碼片斷很大。你可以請張貼[MCVE](http://stackoverflow.com/help/mcve) – 2015-03-25 09:18:29
你還沒有繪製任何東西的位圖,所以自然是'空白'。你也不應該從一個memDC創建一個位圖,因爲你會得到一個黑白圖像。您應該從目標窗口中將BitBlt轉換爲已將memBmp選入其中的DC。一旦完成,你可以從你的memBmp中獲取這些位。在hdc中選擇位圖只是意味着後續寫入該dc會影響該位圖 - 這並不意味着該DC中已經存在的圖像將被複制到新選定的位圖 - 因此,當您嘗試使用位圖時,位圖仍爲空得到它的位。 :) – enhzflep 2015-03-25 11:12:50
@enhzflep,我必須對某事感到困惑。 HDC memoryDeviceContext = CreateCompatibleDC(notepadWindowDeviceContext'防止得到黑白圖像嗎?是不是我將BitBlt從目標窗口(notepadWindowDeviceContext)轉換爲DC(memoryDeviceContext),並將其中的memoryBitmap選入它?(這是斷言(TRUE == BitBlt ...線我指的是)。是不是通過內存DC從窗口DC複製到內存位圖的位? – jester 2015-03-25 18:37:29