Programming/MFC-C++

[C++] 가려진 윈도우 캡쳐, 화면 캡쳐 후 BMP 저장

빠릿베짱이 2015. 6. 9. 10:14
반응형

가려진 윈도우 캡쳐 뿐만 아니라, 프로그램 개발 시 View 화면 캡쳐 응용 가능

SaveToFile 함수 : HBITMAP을 입력받아 저장하는 기능

Capture 함수 : 캡쳐하고자하는 윈도우의 핸들(hTargetWnd)과 저장할 파일명(lpszFilePath)을 입력받아 캡쳐 후 저장 기능

PrintWindow : 가려진 윈도우를 캡쳐하는 역할을 한다.


	BOOL Capture(HWND hTargetWnd, LPCTSTR lpszFilePath)
	{
		CRect rct;
		if(hTargetWnd)
			::GetWindowRect(hTargetWnd, &rct);
		else
			return FALSE;
		
		HBITMAP hBitmap = NULL;
		HBITMAP hOldBitmap = NULL;
		BOOL bSuccess = FALSE;

		HDC hDC = ::GetDC(hTargetWnd);
		HDC hMemDC = ::CreateCompatibleDC(hDC);
		hBitmap = ::CreateCompatibleBitmap(hDC, rct.Width(), rct.Height());

		if(!hBitmap)
			return FALSE;

		hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hBitmap);

		if(!::PrintWindow(hTargetWnd, hMemDC, 0))
			bSuccess = FALSE;
		else
			bSuccess = TRUE;

		//Save 함수 : http://blog.daum.net/odega/25
		if(bSuccess && !SaveToFile(hBitmap, lpszFilePath))
			bSuccess = FALSE;
		else
			bSuccess = TRUE;

		::SelectObject(hMemDC, hOldBitmap);
		DeleteObject(hBitmap);
		::DeleteDC(hMemDC);
		::ReleaseDC(hTargetWnd, hDC);

		return bSuccess;
	}

	

	BOOL SaveToFile(HBITMAP hBitmap, LPCTSTR lpszFileName)
	{
		HDC hDC;
		int iBits;
		WORD wBitCount;
		DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0;
		BITMAP Bitmap;
		BITMAPFILEHEADER bmfHdr;
		BITMAPINFOHEADER bi;
		LPBITMAPINFOHEADER lpbi;
		HANDLE fh, hDib, hPal,hOldPal=NULL;

		hDC = ::CreateDC("DISPLAY", NULL, NULL, NULL);
		iBits = ::GetDeviceCaps(hDC, BITSPIXEL) * ::GetDeviceCaps(hDC, PLANES);
		::DeleteDC(hDC);
		if (iBits <= 1)
			wBitCount = 1;
		else if (iBits <= 4)
			wBitCount = 4;
		else if (iBits <= 8)
			wBitCount = 8;
		else
			wBitCount = 24;
		GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
		bi.biSize = sizeof(BITMAPINFOHEADER);
		bi.biWidth = Bitmap.bmWidth;
		bi.biHeight = Bitmap.bmHeight;
		bi.biPlanes = 1;
		bi.biBitCount = wBitCount;
		bi.biCompression = BI_RGB;
		bi.biSizeImage = 0;
		bi.biXPelsPerMeter = 0;
		bi.biYPelsPerMeter = 0;
		bi.biClrImportant = 0;
		bi.biClrUsed = 0;
		dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;

		hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
		lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
		*lpbi = bi;

		hPal = GetStockObject(DEFAULT_PALETTE);
		if (hPal)
		{ 
			hDC = GetDC(NULL);
			hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
			::RealizePalette(hDC);
		}


		GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) 
			+dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS);

		if (hOldPal)
		{
			::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
			::RealizePalette(hDC);
			ReleaseDC(NULL, hDC);
		}

		fh = CreateFile(lpszFileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS, 
			FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 

		if (fh == INVALID_HANDLE_VALUE)
			return FALSE; 

		bmfHdr.bfType = 0x4D42; // "BM"
		dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;
		bmfHdr.bfSize = dwDIBSize;
		bmfHdr.bfReserved1 = 0;
		bmfHdr.bfReserved2 = 0;
		bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize;

		WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);

		WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
		GlobalUnlock(hDib);
		GlobalFree(hDib);
		CloseHandle(fh);
		return TRUE;
	}


반응형