GDI+下的桌面截图并保存

虽然说是GDI+,但是只在最后保存文件的时候用到了。。。取页面信息还是GDI的那一套,这个是因为GDI+中没有C#的方便的CopyToScreen函数。。。
第一个函数GetEncoderClsid属于GDI+,根据类型参数返回编码方式,然后调用GDI+ Bitmap对象的Save函数保存文件。
GDI核心函数是BitBlt和GetDIBits,首先获得桌面窗口的DC,创建兼容的DC并选入兼容Bitmap,使用bitblt拷贝位图数据,通过兼容DC中的bitmap对象构造位图文件头信息,GetDIBits参考该文件头信息填充缓冲区,将兼容DC中的值写入位图文件,最后再调用GDI+进行保存。
GDI+可以提供转化到png bmp gif jpeg tiff等多种格式,而不仅仅是GDI的bmp。
以下是代码,注意调用时要首先初始化GDI+,否则可能在GetEncoderClsid中会出现Access Violation

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
	// CLSID encoderClsid;
	// GetEncoderClsid(L"image/png", &encoderClsid);
	// GetEncoderClsid(L"image/bmp", &encoderClsid);
	// GetEncoderClsid(L"image/gif", &encoderClsid);
	// GetEncoderClsid(L"image/jpeg", &encoderClsid);
	// GetEncoderClsid(L"image/tiff", &encoderClsid);
	UINT num= 0;
	UINT size= 0;
	ImageCodecInfo* pImageCodecInfo = NULL;
	GetImageEncodersSize(&num, &size);
	if(size== 0)
	{
		return -1;
	}
	pImageCodecInfo= (ImageCodecInfo*)(malloc(size));
	if(pImageCodecInfo== NULL)
	{
		return -1;
	}
	GetImageEncoders(num, size, pImageCodecInfo);
	for(UINT j=0; j< num; ++j)
	{
		if(wcscmp(pImageCodecInfo[j].MimeType, format)== 0)
		{
			*pClsid= pImageCodecInfo[j].Clsid;
			free(pImageCodecInfo);
			return j;
		}
	}
	free(pImageCodecInfo);
	return -1;
}
void ScreenToJpg()
{
	HDC desk=GetDC(GetDesktopWindow());
	int screenWidth = GetDeviceCaps(desk,HORZRES);     //屏幕宽
	int screenHeight = GetDeviceCaps(desk,VERTRES);     //屏幕高
	HBITMAP memBitmap=CreateCompatibleBitmap(desk,screenWidth,screenHeight);
	HDC memDC=CreateCompatibleDC(desk);
	SelectObject(memDC,memBitmap);
	BitBlt(memDC,0,0,screenWidth,screenHeight,desk,0,0,SRCCOPY);
	BITMAP bmpInfo;
	GetObject(memBitmap,sizeof(bmpInfo),&bmpInfo);
	BITMAPINFO m_BITMAPINFO;
	memset(&m_BITMAPINFO, 0, sizeof(BITMAPINFO));
	m_BITMAPINFO.bmiHeader.biSize     = sizeof(BITMAPINFOHEADER);
	m_BITMAPINFO.bmiHeader.biPlanes     = 1;
	m_BITMAPINFO.bmiHeader.biBitCount    = bmpInfo.bmBitsPixel;
	m_BITMAPINFO.bmiHeader.biCompression   = BI_RGB;
	m_BITMAPINFO.bmiHeader.biWidth     = bmpInfo.bmWidth;
	m_BITMAPINFO.bmiHeader.biHeight     = bmpInfo.bmHeight;
	BYTE * pBuffer = new BYTE[bmpInfo.bmWidthBytes * bmpInfo.bmHeight];
	GetDIBits(desk,memBitmap,0,screenHeight,pBuffer, (LPBITMAPINFO) &m_BITMAPINFO, DIB_RGB_COLORS);
	Bitmap *pSrcBmp = Bitmap::FromBITMAPINFO(&m_BITMAPINFO, (void*)pBuffer);
	// 保存成jpg文件
	CLSID encoderClsid;
	GetEncoderClsid(L"image/jpeg", &encoderClsid);
	pSrcBmp->Save(L"desktop.jpg", &encoderClsid);
	// 释放内存
	delete pSrcBmp;
	delete pBuffer;
	DeleteObject(memBitmap);
	DeleteDC(memDC);
	ReleaseDC(GetDesktopWindow(),desk);
}

7 thoughts on “GDI+下的桌面截图并保存

Leave a Reply

Your email address will not be published. Required fields are marked *