我一直关注: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183402%28v=vs.85%29.aspx
捕获一个Windows绘图区域,也就是打印它。
重要的功能是“int CaptureAnImage(HWND hWnd)” 当我直接复制并向其发送合法的内容时,每一件工作都很好。
但是我需要能够将它存储在该函数之外(将其作为位图返回),所以我创建了自己的“printscreen”结构。
struct PrintScreen {
BITMAP * bmpScreen;
BITMAPFILEHEADER * bmfHeader;
BITMAPINFOHEADER * bi;
char * data;
DWORD len;
};
并更改,因此它分配内存,而我在函数中使用指针。
(使用分配的内存和指针的新代码)
struct PrintScreen * CaptureAnImage(HWND hWnd)
{
HDC hdcScreen;
HDC hdcWindow;
HDC hdcMemDC = NULL;
HBITMAP hbmScreen = NULL;
BITMAP * bmpScreen = GlobalAlloc(GMEM_FIXED,sizeof(BITMAP));
BITMAPFILEHEADER * bmfHeader = GlobalAlloc(GMEM_FIXED,sizeof(BITMAPFILEHEADER));
BITMAPINFOHEADER * bi = GlobalAlloc(GMEM_FIXED,sizeof(BITMAPINFOHEADER));
struct PrintScreen * printScreen = GlobalAlloc(GMEM_FIXED,sizeof(struct PrintScreen));
// Retrieve the handle to a display device context for the client
// area of the window.
hdcScreen = GetDC(NULL);
hdcWindow = GetDC(hWnd);
// Create a compatible DC which is used in a BitBlt from the window DC
hdcMemDC = CreateCompatibleDC(hdcWindow);
if(!hdcMemDC)
{
printf("Bajs");
MessageBox(hWnd, _T("CreateCompatibleDC has failed"),_T("Failed"), MB_OK);
goto done;
}
// Get the client area for size calculation
RECT rcClient;
if(!GetClientRect(hWnd, &rcClient)) {
printf("Treash");
}
printf("Rect:%d,%d,%d,%d\n",rcClient.right,rcClient.top, rcClient.left,rcClient.bottom);
//This is the best stretch mode
SetStretchBltMode(hdcWindow,HALFTONE);
SetBrushOrgEx(hdcWindow,0,0,NULL);
//The source DC is the entire screen and the destination DC is the current window (HWND)
if(!StretchBlt(hdcWindow,
0,0,
rcClient.right, rcClient.bottom,
hdcScreen,
0,0,
GetSystemMetrics (SM_CXSCREEN),
GetSystemMetrics (SM_CYSCREEN),
SRCCOPY))
{
printf("Bajs");
MessageBox(hWnd, _T("StretchBlt has failed"),_T("Failed"), MB_OK);
goto done;
}
// Create a compatible bitmap from the Window DC
hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);
printf("\n%ld\n",rcClient.right);
if(!hbmScreen)
{
MessageBox(hWnd, _T("CreateCompatibleBitmap Failed"),_T("Failed"), MB_OK);
goto done;
}
// Select the compatible bitmap into the compatible memory DC.
SelectObject(hdcMemDC,hbmScreen);
// Bit block transfer into our compatible memory DC.
if(!BitBlt(hdcMemDC,
0,0,
rcClient.right-rcClient.left, rcClient.bottom-rcClient.top,
hdcWindow,
0,0,
SRCCOPY))
{
MessageBox(hWnd, _T("BitBlt has failed"), _T("Failed"), MB_OK);
goto done;
}
// Get the BITMAP from the HBITMAP
GetObject(hbmScreen,sizeof(BITMAP),bmpScreen);
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.
char *lpbitmap = (char *)GlobalAlloc(GMEM_FIXED,dwBmpSize);
// 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);
//findInvWindow(bmpScreen, lpbitmap);
// A file is created, this is where we will save the screen capture.
HANDLE hFile = CreateFile(_T("C:\\Users\\Hugo\\Dropbox\\Code blocks\\Test\\Poe Test\\bin\\Debug\\captureqwsx.bmp"),
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
printf("Error creating file");
}
printf("Done");
// 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);
printf("Size:%d\n",dwBmpSize);
//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);
//Close the handle for the file that was created
CloseHandle(hFile);
printScreen->bmpScreen = bmpScreen;
printScreen->bmfHeader = bmfHeader;
printScreen->bi = bi;
printScreen->data = lpbitmap;
printScreen->len = dwSizeofDIB;
//Clean up
done:
DeleteObject(hbmScreen);
DeleteObject(hdcMemDC);
ReleaseDC(NULL,hdcScreen);
ReleaseDC(hWnd,hdcWindow);
return printScreen;
}
我的问题是,有时它工作正常,我得到一个没有框架的合法版画屏幕,但我经常得到框架,图像的大小不会改变,但它压缩它所以窗口的框架是里面也是。
我试过调试什么功能可能会这样,等等,但有点新的C,从我的观点来看,所有功能都表示他们已经成功了。
编辑: 带框架 http://i62.tinypic.com/2uifyj4.jpg
没有,因为它应该是:(编辑链接) http://i.stack.imgur.com/iMxhM.jpg
抱歉没有直接链接,但必须为此点亮代表。并且显然不能发布超过2个链接。
EDIT2: 显然,错误不是帧被添加,而是捕获窗口数据,它捕获整个窗口的“上/下”,包括帧。
仍然不知道是什么原因导致它有时获得正确的数据,有时却没有。所有功能都返回成功...(更新“帧”图片以显示错误)