我想将窗口的上下文转换为位图。我用窗口画出触摸的基本线条。我遇到的问题是我的位图是黑色的。这可能是由于我没有正确抓取设备上下文或做其他错误的事实。
函数CreateBitmapInfoStruct
和CreateBMPFile
来自this MSDN example。
另请注意,g_hWnd
是一个全局变量,其中包含我要保存图片的窗口句柄。
我的最终目标是能够将位图保存到我拥有的mysql字段(BLOB)中。这就是我最初的问题。无论如何,我首先尝试创建一个BMP文件。
我在这里和其他地方搜索过。我发现的最佳解决方案是this MSDN example之后推荐的。但是,它无法正常工作。
任何有关此特定问题的帮助和/或将位图写入blob到mysql表中的任何帮助,将不胜感激。
这是我的代码:
HDC hDC = GetDC(g_hWnd);
LPRECT rect = (LPRECT)malloc(sizeof(RECT));
GetWindowRect(g_hWnd,rect);
int h = rect->right - rect->left;
int w = rect->bottom - rect->top;
LPRECT rect = (LPRECT)malloc(sizeof(RECT));
GetWindowRect(g_hWnd,rect);
HBITMAP hBmp = CreateCompatibleBitmap(hDC,w,h);
PBITMAPINFO pbmi;
pbmi = CreateBitmapInfoStruct(g_hWnd,hBmp);
CreateBMPFile(g_hWnd, TEXT("c:\\TEMPO\\TestG2.bmp"), pbmi,
hBmp, hDC) ;
ReleaseDC(g_hWnd,hDC);
DeleteObject(hBmp);
DeleteObject(pbmi);
if (rect != nullptr)
free(rect);
编辑:
捕获屏幕(getDC)的实际答案是修改this sample in MSDN。
我在这里修改了样本(删除了拉伸)注意仍然使用goto,我将删除它 关于GOTO的说明......虽然我不使用它,但我发现它也不是问题。我认为关于GOTO声明已经做了太多...就像在汇编时,我们不会做goto(JUMPS)
以下是代码:
void saveBitmap()
{
HDC hdcScreen;
HDC hdcWindow;
HDC hdcMemDC = NULL;
HBITMAP hbmScreen = NULL;
BITMAP bmpScreen;
// Retrieve the handle to a display device context for the client
// area of the window.
hdcScreen = GetDC(NULL);
hdcWindow = GetDC(g_hWnd);
// Create a compatible DC which is used in a BitBlt from the window DC
hdcMemDC = CreateCompatibleDC(hdcWindow);
if(!hdcMemDC)
{
goto done;
}
RECT rcClient;
GetClientRect(g_hWnd, &rcClient);
hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left,
rcClient.bottom-rcClient.top);
if(!hbmScreen)
{
goto done;
}
SelectObject(hdcMemDC,hbmScreen);
if(!BitBlt(hdcMemDC,
0,0,
rcClient.right-rcClient.left, rcClient.bottom-rcClient.top,
hdcWindow,
0,0,
SRCCOPY))
{
goto done;
}
GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmpScreen.bmWidth;
bi.biHeight = bmpScreen.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 *
bmpScreen.bmHeight;
// Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that
// call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc
// have greater overhead than HeapAlloc.
HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize);
char *lpbitmap = (char *)GlobalLock(hDIB);
// Gets the "bits" from the bitmap and copies them into a buffer
// which is pointed to by lpbitmap.
GetDIBits(hdcWindow, hbmScreen, 0,
(UINT)bmpScreen.bmHeight,
lpbitmap,
(BITMAPINFO *)&bi, DIB_RGB_COLORS);
// A file is created, this is where we will save the screen capture.
HANDLE hFile = CreateFile(L"c:\\tempo\\captureqwsx.bmp",
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
// Add the size of the headers to the size of the bitmap to get the total file size
DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER);
//Offset to where the actual bitmap bits start.
bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +
(DWORD)sizeof(BITMAPINFOHEADER);
//Size of the file
bmfHeader.bfSize = dwSizeofDIB;
//bfType must always be BM for Bitmaps
bmfHeader.bfType = 0x4D42; //BM
DWORD dwBytesWritten = 0;
WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
//Unlock and Free the DIB from the heap
GlobalUnlock(hDIB);
GlobalFree(hDIB);
//Close the handle for the file that was created
CloseHandle(hFile);
//Clean up
done:
DeleteObject(hbmScreen);
DeleteObject(hdcMemDC);
ReleaseDC(NULL,hdcScreen);
ReleaseDC(g_hWnd,hdcWindow);
}
答案 0 :(得分:4)
您可以使用GetDIBits()。 此功能将图像像素数据复制到您自己分配的内存中。
有关详细信息和解释,请参阅GetDIBits and loop through pixels using X, Y。