方法一
BOOL SaveHwndToBmpFile(HWND hWnd, LPCTSTR lpszPath) { HWND hDesktop = ::GetDesktopWindow(); ASSERT(hDesktop); if(NULL == hWnd) { hWnd = hDesktop; } RECT rect; ::GetWindowRect(hWnd, &rect); int nWidht = rect.right - rect.left; int nHeight = rect.bottom - rect.top; HDC hSrcDC = ::GetWindowDC(hWnd); ASSERT(hSrcDC); HDC hMemDC = ::CreateCompatibleDC(hSrcDC); ASSERT(hMemDC); HBITMAP hBitmap = ::CreateCompatibleBitmap(hSrcDC, nWidht, nHeight); ASSERT(hBitmap); HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hBitmap); ::BitBlt(hMemDC, 0, 0, nWidht, nHeight, hSrcDC, 0, 0, SRCCOPY); BITMAP bitmap = {0}; ::GetObject(hBitmap, sizeof(BITMAP), &bitmap); BITMAPINFOHEADER bi = {0}; BITMAPFILEHEADER bf = {0}; CONST int nBitCount = 24; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bitmap.bmWidth; bi.biHeight = bitmap.bmHeight; bi.biPlanes = 1; bi.biBitCount = nBitCount; bi.biCompression = BI_RGB; DWORD dwSize = ((bitmap.bmWidth * nBitCount + 31) / 32) * 4 * bitmap.bmHeight; HANDLE hDib = GlobalAlloc(GHND, dwSize + sizeof(BITMAPINFOHEADER)); LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); *lpbi = bi; ::GetDIBits(hMemDC, hBitmap, 0, bitmap.bmHeight, (BYTE*)lpbi + sizeof(BITMAPINFOHEADER), (BITMAPINFO*)lpbi, DIB_RGB_COLORS); try { CFile file; file.Open(lpszPath, CFile::modeCreate | CFile::modeWrite); bf.bfType = 0x4d42; dwSize += sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); bf.bfSize = dwSize; bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); file.Write((BYTE*)&bf, sizeof(BITMAPFILEHEADER)); file.Write((BYTE*)lpbi, dwSize); file.Close(); } catch(CFileException* e) { e->ReportError(); e->Delete(); } GlobalUnlock(hDib); GlobalFree(hDib); ::SelectObject(hMemDC, hOldBitmap); ::DeleteObject(hBitmap); ::DeleteDC(hMemDC); ::ReleaseDC(hWnd, hSrcDC); return TRUE; } // 调用方法 HWND hWnd = ::FindWindow(NULL, _T("XXX")); if(hWnd) { SaveHwndToBmpFile(hWnd, _T("F://12.bmp")); }
方法二
窗口截图,可以获取遮挡窗口完整的图像,并保存到bmp文件中去。主要用到的函数中PrintWindow,VC6不支持该函数,请使用VS2008来编译。其它需求如平台要求请参考MSDN文档。
void SaveHwndToBmpFile(HWND hWnd, LPCTSTR lpszPath) { HDC hDC = ::GetWindowDC(hWnd); ASSERT(hDC); HDC hMemDC = ::CreateCompatibleDC(hDC); ASSERT(hMemDC); RECT rc; ::GetWindowRect(hWnd, &rc); HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, rc.right - rc.left, rc.bottom - rc.top); ASSERT(hBitmap); HBITMAP hOldBmp = (HBITMAP)::SelectObject(hMemDC, hBitmap); ::PrintWindow(hWnd, hMemDC, 0); BITMAP bitmap = {0}; ::GetObject(hBitmap, sizeof(BITMAP), &bitmap); BITMAPINFOHEADER bi = {0}; BITMAPFILEHEADER bf = {0}; CONST int nBitCount = 24; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bitmap.bmWidth; bi.biHeight = bitmap.bmHeight; bi.biPlanes = 1; bi.biBitCount = nBitCount; bi.biCompression = BI_RGB; DWORD dwSize = ((bitmap.bmWidth * nBitCount + 31) / 32) * 4 * bitmap.bmHeight; HANDLE hDib = GlobalAlloc(GHND, dwSize + sizeof(BITMAPINFOHEADER)); LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); *lpbi = bi; ::GetDIBits(hMemDC, hBitmap, 0, bitmap.bmHeight, (BYTE*)lpbi + sizeof(BITMAPINFOHEADER), (BITMAPINFO*)lpbi, DIB_RGB_COLORS); try { CFile file; file.Open(lpszPath, CFile::modeCreate | CFile::modeWrite); bf.bfType = 0x4d42; dwSize += sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); bf.bfSize = dwSize; bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); file.Write((BYTE*)&bf, sizeof(BITMAPFILEHEADER)); file.Write((BYTE*)lpbi, dwSize); file.Close(); } catch(CFileException* e) { e->ReportError(); e->Delete(); } GlobalUnlock(hDib); GlobalFree(hDib); ::SelectObject(hMemDC, hOldBmp); ::DeleteObject(hBitmap); ::DeleteObject(hMemDC); ::ReleaseDC(hWnd, hDC); } // 调用方法 HWND hWnd = ::FindWindow(NULL, _T("XXX")); if(hWnd) { SaveHwndToBmpFile(hWnd, _T("F://12.bmp")); }