欢迎来到我的博客https://www.cnblogs.com/veis/

https://www.cnblogs.com/veis/p/14182037.html

分享一个MFC的内存DC封装类

1.什么是内存DC?

  要使应用程序能够将输出放在内存中,而不是将其发送到实际的设备,请为位图操作使用一个称为内存设备上下文的特殊设备上下文内存DC使系统能够将内存的一部分作为虚拟设备处理。它是内存中的一个位数组,应用程序可以临时使用它来存储在普通绘图表面上创建的位图的颜色数据。由于位图与设备兼容,内存DC有时也称为兼容设备上下文。

2.为什么要封装内存DC?

  由于使用自带的方法进行构建步骤比较多,一步出错,就有可能导致位图输出失败,所以目的在于把步骤封装成类,日常使用的步骤如下所示:

 

// 创建内存DC
CDC mMemDc;
mMemDc.CreateCompatibleDC( &dc );
// 创建兼容位图
CBitmap bmpMemBmp;
bmpMemBmp.CreateCompatibleBitmap( &mMemDc, 100, 100 );
CBitmap* pOldBmp = mMemDc.SelectObject( &bmpMemBmp );

// 在内存DC上绘图
BOOL bRet = mMemDc.Ellipse( 0, 0, 100, 100 );

// 从内存DC上拷贝至显示DC
dc.BitBlt( 0, 0, 100, 100, &mMemDc, 0, 0, SRCCOPY );

 

  

 

3.内存DC的源码

 3.1.头文件

#pragma once
#include <afxwin.h>

class CMemoryDC :
	public CDC
{
	CSize m_size;
public:
	// 非压缩输出
	void BitTrans(
		int nXDest,		// 目标起点X
		int nYDest,		// 目标起点Y
		int nWidthDest,	// 目标宽度
		int nHeightDest,// 目标高度
		CDC* pDC,		// 目标DC
		int nXSrc,		// 来源起点X
		int nYSrc,		// 来源起点Y
		COLORREF crTrans// 透明色
	);

	// 压缩输出
	void StretchTrans(
		int nXDest,			// 目标起点X
		int nYDest,			// 目标起点Y
		int nWidthDest,     // 目标宽度
		int nHeightDest,    // 目标高度
		CDC* pDC,			// 目标DC
		int nXSrc,			// 来源起点X
		int nYSrc,			// 来源起点Y
		int nWidthSrc,		// 来源宽度
		int nHeightSrc,		// 来源高度
		COLORREF crTrans	// 透明色
	);

	BOOL LoadBitmap(UINT nIDResource, CDC* pDC = NULL); // 通过内部资源ID加载
	BOOL LoadBitmap(LPCTSTR lpszResourceName, CDC* pDC = NULL); // 通过外部文件加载
	BOOL DeleteDC(); // 删除DC
	BOOL Create(int cx, int cy, CDC* pDC = NULL); // 创建一张空白内存画布

	CMemoryDC(int cx, int cy, CDC* pDC = NULL) // 空白DC构造
	{
		Create(cx, cy, pDC);
	}

	CMemoryDC() // 无参构造
	{
		m_size.cx = m_size.cy = 0;
	}

	CMemoryDC(UINT nIDResource, CDC* pDC = NULL) // 资源ID构造
	{
		LoadBitmap(nIDResource, pDC);
	}

	CMemoryDC(LPCTSTR lpszResourceName, CDC* pDC = NULL) // 资源路径构造
	{
		LoadBitmap(lpszResourceName, pDC);
	}

	~CMemoryDC() // 析构函数
	{
		DeleteDC();
	}

	inline int GetWidth() const // 获取图片宽度
	{
		return m_size.cx;
	}

	inline int GetHeight() const // 获取图片高度
	{
		return m_size.cy;
	}

};

  

 3.2.源文件

#include "pch.h"
#include "CMemoryDC.h"

void CMemoryDC::BitTrans(int nXDest, int nYDest, int nWidthDest, 
	int nHeightDest, CDC* pDC, int nXSrc, int nYSrc, COLORREF crTrans)
{
	CMemoryDC dcImage(nWidthDest, nHeightDest, pDC);//临时DC
	CBitmap bmpMask;
	bmpMask.CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);            // 创建单色掩码位图
	CDC dcMask;//掩码DC 
	dcMask.CreateCompatibleDC(pDC);
	dcMask.SelectObject(bmpMask);
	//将载入位图的内存DC中的位图,拷贝到临时DC中
	dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, this, nXSrc, nYSrc, SRCCOPY);

	// 设置临时DC的透明色
	dcImage.SetBkColor(crTrans);
	//掩码DC的透明区域为白色其它区域为黑色
	dcMask.BitBlt(0, 0, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCCOPY);

	//临时DC透明区域为黑色,其它区域保持不变
	dcImage.SetBkColor(RGB(0, 0, 0));
	dcImage.SetTextColor(RGB(255, 255, 255));
	dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);

	// 目标DC透明部分保持屏幕不变,其它部分变成黑色
	pDC->SetBkColor(RGB(255, 255, 255));
	pDC->SetTextColor(RGB(0, 0, 0));
	pDC->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);
	pDC->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCPAINT);
}

void CMemoryDC::StretchTrans(int nXDest, int nYDest, int nWidthDest, 
	int nHeightDest, CDC* pDC, int nXSrc, int nYSrc, 
	int nWidthSrc, int nHeightSrc, COLORREF crTrans)
{
	CMemoryDC dcImage(nWidthDest, nHeightDest, pDC);// 临时DC
	CBitmap bmpMask;
	// 创建单色掩码位图
	bmpMask.CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);
	CDC dcMask;
	dcMask.CreateCompatibleDC(pDC);
	dcMask.SelectObject(bmpMask);

	// 将载入位图的内存DC中的位图,拷贝到临时DC中
	if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc)
		dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, this, nXSrc, nYSrc, SRCCOPY);
	else
		dcImage.StretchBlt(0, 0, nWidthDest, nHeightDest,
			this, nXSrc, nYSrc, nWidthSrc, nHeightSrc, SRCCOPY);

	// 设置临时DC的透明色
	dcImage.SetBkColor(crTrans);
	//掩码DC的透明区域为白色其它区域为黑色
	dcMask.BitBlt(0, 0, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCCOPY);

	// 临时DC透明区域为黑色,其它区域保持不变
	dcImage.SetBkColor(RGB(0, 0, 0));
	dcImage.SetTextColor(RGB(255, 255, 255));
	dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);

	// 目标DC透明部分保持屏幕不变,其它部分变成黑色
	pDC->SetBkColor(RGB(255, 255, 255));
	pDC->SetTextColor(RGB(0, 0, 0));
	pDC->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);
	pDC->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCPAINT);
}

BOOL CMemoryDC::LoadBitmap(UINT nIDResource, CDC* pDC)
{
	CBitmap bitmap;
	if (!bitmap.LoadBitmap(nIDResource))
	{
		m_size.cx = m_size.cy = 0;
		return FALSE;
	}
	BITMAP bm;
	bitmap.GetBitmap(&bm);
	m_size.SetSize(bm.bmWidth, bm.bmHeight);
	CreateCompatibleDC(pDC);
	SelectObject(bitmap);
	return TRUE;
}

BOOL CMemoryDC::LoadBitmap(LPCTSTR lpszResourceName, CDC* pDC)
{
	BITMAP bitmap;
	HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, lpszResourceName,
		IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
	if (!hBitmap)
	{
		m_size.cx = m_size.cy = 0;
		return FALSE;
	}
	::GetObject(hBitmap, sizeof(bitmap), &bitmap);
	m_size.SetSize(bitmap.bmWidth, bitmap.bmHeight);
	CreateCompatibleDC(pDC);
	SelectObject(hBitmap);
	return TRUE;
}

BOOL CMemoryDC::DeleteDC()
{
	if (!GetSafeHdc())
		return TRUE;
	CBitmap* pBitmap = GetCurrentBitmap();
	pBitmap->DeleteObject();
	return CDC::DeleteDC();
}

BOOL CMemoryDC::Create(int cx, int cy, CDC* pDC)
{
	CreateCompatibleDC(pDC);
	CBitmap bitmap;
	if (pDC)
		bitmap.CreateCompatibleBitmap(pDC, cx, cy);
	else
		bitmap.CreateCompatibleBitmap(&CClientDC(NULL), cx, cy);
	m_size.cx = cx;
	m_size.cy = cy;
	SelectObject(bitmap);
	return TRUE;
}

  

posted @ 2020-05-10 14:42  veis  阅读(396)  评论(0编辑  收藏  举报