[ATL/WTL]_[保存CBitmap到文件-保存屏幕内容到文件]

场景:

1. 在做图片处理时,比如放大后或加特效后需要保存CBitmap(HBITMAP)到文件.

2.截取屏幕内容到文件时.

3.不需要加入第3方库时.

说明: 这段代码部分来自网上,第一次学atl/wtl,gdi不是很熟悉,以后转换为wtl版本吧。当然wtl项目直接用也没问题. 现在想想wxWidgets的wxImage类对这类操作方便多了。只需要调用一个SaveFile方法。

保存HBITMAP到文件:

static bool SaveBitmapToFile(CBitmap& bitmap, LPWSTR lpFileName)
{
	HBITMAP hBitmap;	// 为刚才的屏幕位图句柄
	HDC hDC; //设备描述表
	int iBits; //当前显示分辨率下每个像素所占字节数
	WORD wBitCount; //位图中每个像素所占字节数
	DWORD dwPaletteSize = 0, //定义调色板大小
		dwBmBitsSize,  //位图中像素字节大小
		dwDIBSize,	 //位图文件大小
		dwWritten;  //写入文件字节数
	BITMAP Bitmap; //位图属性结构
	BITMAPFILEHEADER bmfHdr; //位图文件头结构
	BITMAPINFOHEADER bi; //位图信息头结构
	LPBITMAPINFOHEADER lpbi; //指向位图信息头结构
	HANDLE fh,	 //定义文件
		hDib,	 //分配内存句柄
		hPal,	//调色板句柄
		hOldPal = NULL;

	//计算位图文件每个像素所占字节数
	hBitmap = bitmap;
	hDC = CreateDC(L"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 if	(iBits <= 24)
		wBitCount =	24;
	else if (iBits <= 32)
		wBitCount = 32;

	//计算调色板大小
	if (wBitCount <= 8)
		dwPaletteSize =	(1 << wBitCount) * sizeof (RGBQUAD);

	//设置位图信息头结构
	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.biClrUsed = 0;
	bi.biClrImportant = 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,
		(LPBITMAPINFO)lpbi,	DIB_RGB_COLORS);  

	//恢复调色板
	if (hOldPal)
	{
		SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
		RealizePalette(hDC);
		::ReleaseDC(NULL, hDC);
	}  

	//创建位图文件
	fh = CreateFile(lpFileName, 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;
}  

保存屏幕到文件:

static void SaveScreenToFile(LPCTSTR szFileName)
{
	HDC hScrDC = ::GetDC(NULL);
	HDC hMemDC = NULL;

	BYTE *lpBitmapBits = NULL; 

	int nWidth = GetSystemMetrics(SM_CXSCREEN);
	int nHeight = GetSystemMetrics(SM_CYSCREEN); 

	hMemDC = ::CreateCompatibleDC(hScrDC); 

	BITMAPINFO bi;
	ZeroMemory(&bi, sizeof(BITMAPINFO));
	bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bi.bmiHeader.biWidth = nWidth;
	bi.bmiHeader.biHeight = nHeight;
	bi.bmiHeader.biPlanes = 1;
	bi.bmiHeader.biBitCount = 24;

	HBITMAP bitmap = ::CreateDIBSection(hMemDC, &bi, DIB_RGB_COLORS, (LPVOID*)&lpBitmapBits, NULL, 0);
	HGDIOBJ oldbmp = ::SelectObject(hMemDC, bitmap); 

	::BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, 0, 0, SRCCOPY);

	BITMAPFILEHEADER bh;
	ZeroMemory(&bh, sizeof(BITMAPFILEHEADER));
	bh.bfType = 0x4d42; //bitmap
	bh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
	bh.bfSize = bh.bfOffBits + ((nWidth*nHeight)*3);

	FILE* file = _wfopen(szFileName,L"wb");
	if(file)
	{
		fwrite(&bh,1,sizeof(BITMAPFILEHEADER),file);
		fwrite(&(bi.bmiHeader),1,sizeof(BITMAPINFOHEADER),file);
		fwrite(lpBitmapBits,1,3 * nWidth * nHeight,file);
		fclose(file);
	}

	::SelectObject(hMemDC, oldbmp);
	::DeleteObject(bitmap);
	::DeleteObject(hMemDC);
	::ReleaseDC(NULL, hScrDC);
}
时间: 2024-10-22 00:41:48

[ATL/WTL]_[保存CBitmap到文件-保存屏幕内容到文件]的相关文章

[ATL/WTL]_[中级]_[保存CBitmap到文件-保存屏幕内容到文件]

场景: 1. 在做图片处理时,比方放大后或加特效后须要保存CBitmap(HBITMAP)到文件. 2.截取屏幕内容到文件时. 3.不须要增加第3方库时. 说明: 这段代码部分来自网上.第一次学atl/wtl.gdi不是非常熟悉.以后转换为wtl版本号吧. 当然wtl项目直接用也没问题. 如今想想wxWidgets的wxImage类对这类操作方便多了.仅仅须要调用一个SaveFile方法. 保存HBITMAP到文件: static bool SaveBitmapToFile(CBitmap& b

[ATL/WTL]_[中级]_[原生的复选框(checkbox button)和单选按钮(radio button)实现透明背景效果解决方案]

场景: 1. mfc,wtl的原生控件都是通过父窗口拦截 WM_CTLCOLORSTATIC 事件来修改子控件的颜色和背景色,CStatic可以通过返回HOLLOW_BRUSH来绘制透明背景: m_HollowBrush = AtlGetStockBrush(HOLLOW_BRUSH); 但是如果使用manifest文件使用最新 外观样式的话,返回HOLLOW_BRUSH对checkbox和radio button没有任何效果,原背景还是存在.虽然通过自绘一个checkbox和radio but

[ATL/WTL]_[初级]_[拖放文件到窗口]

场景: 1. 软件需要支持从桌面拖动文件到软件里,避免从文件打开窗口选择文件,这样效率快很多,这时就需要窗口支持拖放技术. drag and drop. 2. 软件需要复制文件到远程或设备里,支持拖放的话就很方便. 两种方案: 1. 如果是Windows 窗口程序, 可以使用监听WM_DROPFILES 消息来实现, 这里讲解第一种, 比较方便. http://blog.csdn.net/laogaoav/article/details/9152181 2. 如果不想监听 WM_DROPFILE

[ATL/WTL]_[CBitmap复制图片-截取图片-平铺图片]

场景: 1.当你需要截取图片部分区域作为某个控件的背景. 2.需要平铺图片到一个大区域让他自动放大时. 3.或者需要合并图片时. 代码: CDC sdc; CDC ddc; sdc.CreateCompatibleDC(NULL); ddc.CreateCompatibleDC(NULL); CBitmap destBmp; destBmp.CreateCompatibleBitmap(CClientDC(NULL),width,height); sdc.SelectBitmap(m_Bitma

[ATL/WTL]_[0基础]_[CBitmap复制图片-截取图片-平铺图片]

场景: 1.当你须要截取图片部分区域作为某个控件的背景. 2.须要平铺图片到一个大区域让他自己主动放大时. 3.或者须要合并图片时. 代码: CDC sdc; CDC ddc; sdc.CreateCompatibleDC(NULL); ddc.CreateCompatibleDC(NULL); CBitmap destBmp; destBmp.CreateCompatibleBitmap(CClientDC(NULL),width,height); sdc.SelectBitmap(m_Bit

[ATL/WTL]_[初级]_[常用的界面对象操作]

1. 获取指定大小字体 HFONT AppUtil::GetFont(int pixel,bool bold,const wchar_t* font_name) { LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); // zero out structure lf.lfHeight = pixel; // request a 8-pixel-height font if(bold) { lf.lfWeight = FW_BOLD; } lstrcpy(lf

[ATL/WTL]_[初级]_[Win32窗口自定义消息处理过程]

场景 有时候我们需要单独对某个窗口消息进行拦截,比如CEdit响应回车, 这时候就需要拦截窗口处理过程了. 当然MFC的界面可以重载: BOOL CXXXDlg::PreTranslateMessage(MSG* pMsg){ 但是WTL的CEdit并不支持这种方式,WTL如果想在 PreTranslateMessage 里拦截消息,必须继承 CMessageFilter 后还要把这个控件注册到消息循环里才行,也就是必须写子类 或者从父窗口拦截这个CEdit的消息. CMessageLoop*

[ATL/WTL]_[初级]_[窗口如何实现WM_MOUSELEAVE和WM_MOUSEHOVER]

场景: 1.  WTL的控件默认不支持进入和移出的 WM_MOUSEHOVER ,WM_MOUSELEAVE 事件, 即使写了映射也没用, 必须要使用函数 _TrackMouseEvent  添加监听. https://msdn.microsoft.com/en-us/library/windows/desktop/ms645615(v=vs.85).aspx 2. 默认的Window窗口如果有子窗口时, 当进入子窗口时, 会对父窗口调用WM_MOUSELEAVE, 因为子窗口默认会拦截消息,

[ATL/WTL]_[初级]_[转发消息让CStatic支持点击消息操作]

场景: 1. CStatic支持不定长的字符串长度,还可以支持图片背景,当然要父控件响应 WM_CTLCOLORSTATIC 消息. 2. 可以响应点击事件的Cstatic可以当作简单按钮来使用,不需要自定义绘制操作. 3. 普通创建的CStatic不能响应点击时间,需要加上 SS_NOTIFY的 style才可以, 注意AA_STATIC_CLICK是自定义事件ID. #ifndef __DH_STATIC #define __DH_STATIC #include "window/common