2015-03-25 134 views
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>(&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); 
    } 
} 
+0

此代码片断很大。你可以请张贴[MCVE](http://stackoverflow.com/help/mcve) – 2015-03-25 09:18:29

+0

你还没有绘制任何东西的位图,所以自然是'空白'。你也不应该从一个memDC创建一个位图,因为你会得到一个黑白图像。您应该从目标窗口中将BitBlt转换为已将memBmp选入其中的DC。一旦完成,你可以从你的memBmp中获取这些位。在hdc中选择位图只是意味着后续写入该dc会影响该位图 - 这并不意味着该DC中已经存在的图像将被复制到新选定的位图 - 因此,当您尝试使用位图时,位图仍为空得到它的位。 :) – enhzflep 2015-03-25 11:12:50

+0

@enhzflep,我必须对某事感到困惑。 HDC memoryDe​​viceContext = CreateCompatibleDC(notepadWindowDeviceContext'防止得到黑白图像吗?是不是我将BitBlt从目标窗口(notepadWindowDeviceContext)转换为DC(memoryDe​​viceContext),并将其中的memoryBitmap选入它?(这是断言(TRUE == BitBlt ...线我指的是)。是不是通过内存DC从窗口DC复制到内存位图的位? – jester 2015-03-25 18:37:29

回答

0

哎呀。帮助为其y1参数提供BitBlt notepadWindowRectangle.top而不是notepadWindowRectangle.right。修复它使其工作。