改写的CBitmap类,加入了保存显示功能,新加入载入图片功能

本文详细介绍了XMFCBMP类的使用方法,包括如何创建、加载、保存位图,以及获取位图的高度和宽度。通过实例演示了如何在内存中创建位图、从文件路径加载位图,并提供了保存位图到文件的实现。

// XMFCBMP.h: interface for the XMFCBMP class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_XMFCBMP_H__329A4A70_251F_42DB_9B9A_1BB13646B3D4__INCLUDED_)
#define AFX_XMFCBMP_H__329A4A70_251F_42DB_9B9A_1BB13646B3D4__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class XMFCBMP : public CBitmap  
{
public:
	void createFromHBITMAP(HBITMAP *hBMP);
	void createFromCBitmap(CBitmap *srcBMP);
	XMFCBMP();
	virtual ~XMFCBMP();
	void createBMP(int nWidth, int nHeight, UINT nPlanes, UINT nBitcount, const void* lpBits );
	bool loadBMP(const CString strBmpPat);
	CDC* getMemDC(){return &dcMem;}
	BOOL saveBMP(char* filePath);
	int getHeight();
	int getWidth();
private:
	CDC dcMem;
	CBitmap *pOldBitmap ;
};

#endif // !defined(AFX_XMFCBMP_H__329A4A70_251F_42DB_9B9A_1BB13646B3D4__INCLUDED_)

/********************************************************************
	created:	2014/04/02
	created:	2:4:2014   10:36
	filename: 	F:\Projects\DrawInMem\XMFCBMP.cpp
	file path:	F:\Projects\DrawInMem
	file base:	XMFCBMP
	file ext:	cpp
	author:		XinQ
	
	purpose:	
*********************************************************************/
// XMFCBMP.cpp: implementation of the XMFCBMP class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DrawInMem.h"
#include "XMFCBMP.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

XMFCBMP::XMFCBMP()
{
	dcMem.CreateCompatibleDC(NULL);//这里我们就在内存中虚拟建造了DC 
	pOldBitmap = dcMem.SelectObject(this);
}

XMFCBMP::~XMFCBMP()
{
	dcMem.SelectObject(pOldBitmap);
	dcMem.DeleteDC();//create出来的dc需要delete
	//get到的dc需要release
}

//************************************
// Method:    createBMP
// FullName:  XMFCBMP::createBMP
// Access:    public 
// Returns:   void
// Qualifier:
// Parameter: int nWidth
// Parameter: int nHeight
// Parameter: UINT nPlanes
// Parameter: UINT nBitcount
// Parameter: const void * lpBits
//************************************
void XMFCBMP::createBMP(int nWidth, int nHeight, UINT nPlanes, UINT nBitcount, const void* lpBits )
{
	DeleteObject(); 
	CreateBitmap(nWidth, nHeight, nPlanes, nBitcount, lpBits);
	dcMem.SelectObject(this);
}

//************************************
// Method:    saveBMP
// FullName:  XMFCBMP::saveBMP
// Access:    public 
// Returns:   BOOL
// Qualifier:
// Parameter: char * filePath
//************************************
BOOL  XMFCBMP::saveBMP(char* filePath)   
{   
	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 = (HBITMAP)*this;  
	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 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(filePath, 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;
} 

//************************************
// Method:    loadBMP
// FullName:  XMFCBMP::loadBMP
// Access:    public 
// Returns:   bool
// Qualifier:
// Parameter: const CString strBmpPath
//************************************
bool XMFCBMP::loadBMP(const CString strBmpPath)
{
	HBITMAP  bitmap;
	try
	{
		this->DeleteObject();
		//从文件路径加载图片
		bitmap =(HBITMAP)::LoadImage(NULL,strBmpPath, IMAGE_BITMAP, 0, 0,
			LR_CREATEDIBSECTION|LR_LOADFROMFILE|LR_DEFAULTSIZE);
		
		if(this->Attach(bitmap))
		{
			dcMem.SelectObject(this);
			return true;
		}
	}
	catch(...)
	{
		return false;
	}
	return true;
}

int XMFCBMP::getHeight()
{
	BITMAP bm;
	this->GetObject(sizeof(BITMAP),&bm);
    return bm.bmHeight;
}

int XMFCBMP::getWidth()
{
	BITMAP bm;
	this->GetObject(sizeof(BITMAP),&bm);
    return bm.bmWidth;
}

//************************************
// Method:    createFromCBitmap
// FullName:  XMFCBMP::createFromCBitmap
// Access:    public 
// Returns:   void
// Qualifier:
// Parameter: CBitmap * srcBMP
//************************************
void XMFCBMP::createFromCBitmap(CBitmap *srcBMP)
{
	BITMAP bm;
	srcBMP->GetBitmap(&bm);
	DeleteObject();
	CreateBitmapIndirect(&bm);//创建一样尺寸的CBitmap
	dcMem.SelectObject(this);

	//把内容拷贝进来
	CDC srcDC;
	CBitmap *pBitmap;
	srcDC.CreateCompatibleDC(&dcMem);
	pBitmap = srcDC.SelectObject(srcBMP);

	dcMem.BitBlt(0, 0, getWidth(), getHeight(), &srcDC, 0, 0, SRCCOPY);
	//删除srcdc
	srcDC.SelectObject(pBitmap);
	DeleteDC(srcDC);
}

//************************************
// Method:    createFromHBITMAP
// FullName:  XMFCBMP::createFromHBITMAP
// Access:    public 
// Returns:   void
// Qualifier:
// Parameter: HBITMAP * hBMP
//************************************
void XMFCBMP::createFromHBITMAP(HBITMAP *hBMP)
{
	CBitmap *pBmp = CBitmap::FromHandle(*hBMP);
	createFromCBitmap(pBmp);
}

使用方法:

	CDC *dlgDC = GetDC();
	//m_bmp.createBMP(200, 200, 1, 32, NULL);//创建BMP或载入bmp
	m_bmp.loadBMP("1.bmp");
	CDC *pDC = m_bmp.getMemDC();

	//绘图
	pDC->FillSolidRect(0,0,100,100,RGB(255,255,255));//这些时绘图操作,随便你^_^ 
	char str[30];
	sprintf(str, "H%d*W%d", m_bmp.getHeight(), m_bmp.getWidth());
	pDC->TextOut(0, 0, str); 
	pDC->Rectangle(20,20,40,40); 
	pDC->FillSolidRect(40,40,50,50,RGB(255,0,0));

	//显示
	dlgDC->BitBlt(0,0,m_bmp.getWidth(),m_bmp.getHeight(),pDC,0,0,SRCCOPY);//第一次拷贝到屏幕 
	m_bmp.saveBMP("123.bmp");//保存到文件


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值