[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-12-26 06:21:39

[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& bitma

[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]_[中级]_[使用GDIPlus剪切和缩放图片]

场景: 1. 缩放图片,不用多说,就是需要缩略图和画在界面上这类. 2. 剪切,不用多说,就是剪切一部分图片用于绘制控件背景之类. 3. wxWidget的wxImage都是自带这些功能的直接方法的. Gdiplus::Bitmap* CutImage(Gdiplus::Image* source,int x,int y,int width,int height) { Gdiplus::Rect zoomRect(0, 0, width,height); Gdiplus::Bitmap* pIm

[C/C++]_[中级]_[数据地址对齐]

场景: 1. 有些频繁使用的指针变量地址不对齐的话运行效率和对齐后的运行效率差别很大,所以在创建堆空间时,有必要对内存地址对齐提高运行效率. 2. 有些音视频处理的代码或者说自定义的malloc基本都是地址对齐的. 3. 使用原子访问的互锁函数时,InterlockedExchangeAdd都需要地址对齐. 4. 主要还是宏APR_ALIGN, 这个说是Apache源码里,就借用一下吧. 解决方案: 1. 其实就是让地址值对对齐量求模为0, 地址值最多增加n-1个偏移地址就可就可以整出n.  &

[Windows]_[中级]_[界面程序打开控制台输出-转发输出到控制台]

场景: 1. 开发Windows界面程序时,需要打印输出,断点在调试多线程程序有局限性,就是会干扰线程的优先顺序,看不到正确的结果,往往就是断点就没事, 没断点程序就不能正常运行了. 2. 使用动态库(静态库)时,出现问题时在Dll里写std::cout输出信息是必不可少的调试方法,特别对于多线程程序,谁先谁后暂停后的结果就会不一样了. 有时候没有动态库的代码时,也没法对动态库打断点. 3.  打开控制台窗口后只能看到WIndows程序的输出而无法看到Dll的输出? 4. 直接改配置属性->链接

[Windows]_[中级]_[使用命令行工具dumpbin分析文件]

dumpbin(vs自带) 1. 导出lib文件的函数符号(symbols) dumpbin /exports zlib1.lib Microsoft (R) COFF/PE Dumper Version 10.00.40219.01 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file zlib1.lib File Type: LIBRARY Exports ordinal name 1 [email pr

[C/C++]_[中级]_[使用智能指针的方式释放malloc出来的堆空间]

场景: 1. 使用auto_ptr 的方式可以wrap类对象,  之后在方法结束后可以自动释放对象, 参考:这样在有条件判断的语句时可以省掉free语句或CloseHandle. http://blog.csdn.net/infoworld/article/details/9008911 2.C++的特性之一就是类对象(非返回值的对象)在方法结束后会自动调用析构函数,这样在析构函数里可以放一些释放资源的操作. 3. 这里实现了一个类似auto_ptr的类的实用Wrap类,可以参考根据自己需要自定

[C/C++]_[中级]_[delete 类对象指针的注意事项]

场景:1. C++类有构造和析构函数,析构函数是在类对象被delete时(或局部变量自动销毁时)调用来释放资源. 2. C++类对象指针很多情况下需要赋值给void*通用指针来达到传输对象的目的,但是往往这种void*指针就是造成内存泄漏或程序错误的根源, 这就是为什么C++存在泛型的目的,它也是为了在编译时刻消除这种对象不确定性,避免delete或使用时的错误. 好了,看代码,以下代码有什么问题? // test_class.cpp : 定义控制台应用程序的入口点. // #include "

使用C#+EmguCV处理图像入门(图像读取_显示_保存)二

上个随笔已经介绍EmguCV的一些常用库和程序安装以及环境变量的配置,这次写的是如何使用这个类库对图像进行操作. EmguCV图像处理系统组成(个人见解): 图像的基本操作: 贴个代码: using Emgu.CV; //使用命名空间 using Emgu.CV.Structure; using Emgu.CV.CvEnum; using Emgu.Util; static void Main(string[] args) { Mat srcImg = CvInvoke.Imread("1.jp