⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bmpproc.cpp

📁 用VC写的监控中心后台程序。 代码全
💻 CPP
📖 第 1 页 / 共 5 页
字号:
///////////////////////////////////////////////////////////////////////
/*
  目的:BMP位图处理类。(源代码文件)
*/
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
/*
  注释:

  # 类中的位图都是兼容于当前显示器颜色格式的DDB位图
  # 如果读入的位图格式与当前显示器的颜色格式不同,则读入函数会先将其转换
    为兼容于当前显示器颜色格式的位图之后才放入类中
  # 对于所有BOOL型返回的函数,TRUE表示成功,FALSE表示失败


*/
///////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <math.h>
#include <io.h>
#include <errno.h>
#include <direct.h>

#include "BmpProc.h"


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



// 用于调试目的计数变量,它表示程序中构造的CBmpProc类实例个数
// 可以用类中static DWORD GetObjectCount()成员函数访问该变量
// 注意:该变量和访问它的函数都只是在调试模式下才会有效,如果
//		 转换为发布模式,它们都会失效。所以在使用GetObjectCount()
//		 这个成员函数时,应加入#ifdef _DEBUG .... #endif语句块
#ifdef _DEBUG
	DWORD CBmpProc::m_ObjectCount = 0;
#endif




/*************************************************************************
 * 构造函数。初始化类为空。
*************************************************************************/


CBmpProc::CBmpProc()
{
	// 初始化核心数据为空
	m_mark = FALSE;			// 有效标志。(TRUE-有有效位图,否则为FALSE)
	m_type = IT_NULL;		// 图像类型。
	m_addInfo = 0;			// 附加信息。
	m_cFileName.Empty();	// 文件路径。
	m_pInfo = NULL;			// DIB信息结构
	m_hObject = NULL;		// 清除核心DDB位图句柄。(基类成员)

#ifdef _DEBUG
	CBmpProc::m_ObjectCount++;
#endif
}



/************************************************************************
 * 调试用函数,获取进程中CBmpProc类目标的个数。
*************************************************************************
#ifdef _DEBUG
DWORD CBmpProc::GetObjectCount()
{
	return m_ObjectCount;
}
#endif
*************************************************************************/


/*************************************************************************
 * 析构函数。如果类不为空则清空它。
*************************************************************************/


CBmpProc::~CBmpProc()
{
	Clear();

#ifdef _DEBUG
	CBmpProc::m_ObjectCount--;
#endif
}




/*************************************************************************
 *
 * operator=()
 *
 * 参数说明:
 * 
 * const CBmpProc& ds		- 源位图类
 * 
 * 返回值:
 * 
 * CBmpProc&				- 类自身引用
 * 
 * 描述:
 *
 * 复制取指定的位图类
 * 
 * 如果函数成功,则类中原来的位图(如果有的话)将被删除,如果不成功,它保留
 * 原位图。执行本函数之后,可调用该类的IsValid()函数判断是否成功复制(这种
 * 情况只使用于没有图像的类,如果复制前类中就存在图像,可用==操作符判断该类
 * 与源位图类是否相同,如果相同则表示复制成功,不同就说明失败)
 * 
 ************************************************************************/


CBmpProc& CBmpProc::operator=(const CBmpProc& ds)
{
	// 如果类中没有图像,直接返回
	if (!ds.IsValid())
		return *this;

	ASSERT(ds.m_pInfo);
	ASSERT(ds.m_pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));

	// 复制源图信息块
	LPBITMAPINFO pInfo = (LPBITMAPINFO)CreateMemoryBlockFromAddress(
		(LPVOID)ds.m_pInfo);
	if (!pInfo)
		return *this;

	// 复制源图
	CBitmap		tempBmp;
	HBITMAP		hBmp;

	HWND hWnd = ::GetDesktopWindow();
	ASSERT(hWnd);
	HDC hDC = ::GetDC(hWnd);
	CDC dc;
	dc.Attach(hDC);

	if (tempBmp.CreateCompatibleBitmap(&dc, ds.Width(), ds.Height()))
	{
		CDC			compDC, compDC2;
		CBitmap		*pOldBmp, *pOldBmp2;

		// 创建与当前显示设备兼容的内存设备描述表
		compDC.CreateCompatibleDC(NULL);
		compDC2.CreateCompatibleDC(NULL);

		pOldBmp	= compDC.SelectObject((CBitmap*)&tempBmp);
		pOldBmp2= compDC2.SelectObject((CBitmap*)&ds);

		// 复制指定尺寸的源位图到目标位图
		compDC.BitBlt(0, 0, ds.Width(), ds.Height(), 
					&compDC2, 0, 0, SRCCOPY);

		compDC2.SelectObject(pOldBmp2);
		compDC.SelectObject(pOldBmp);

		hBmp = (HBITMAP)tempBmp.Detach();
		// 如果分离操作失败,返回FALSE
		ASSERT(hBmp);
		if (!hBmp)
		{
			::ReleaseDC(hWnd, dc.Detach());
			::free((void*)pInfo);
			return *this;;
		}
		::ReleaseDC(hWnd, dc.Detach());

		// 删除原来的图像,并且设置新的位图
		if (!ClearAndSetData(IT_MEMORY,0,(LPCTSTR)"",pInfo,hBmp))
		{
			::free((void*)pInfo);
			::DeleteObject(hBmp);
			return *this;
		}
		return *this;
	}
	else
	{
		::ReleaseDC(hWnd, dc.Detach());
		::free((void*)pInfo);

		return *this;;
	}
}



/*************************************************************************
 *
 * operator=()
 *
 * 参数说明:
 * 
 * const HBITMAP sou		- 源位图句柄
 * 
 * 返回值:
 * 
 * CBmpProc&				- 类自身引用
 * 
 * 描述:
 *
 * 复制取指定的位图
 * 
 * 如果函数成功,则类中原来的位图(如果有的话)将被删除,如果不成功,它保留
 * 原位图。执行本函数之后,可调用该类的IsValid()函数判断是否成功复制(这种
 * 情况只使用于没有图像的类,如果复制前类中就存在图像,可用==操作符判断该类
 * 与源位图类是否相同,如果相同则表示复制成功,不同就说明失败)
 * 如果入口参数指定的位图句柄无效,则函数失败。
 * 
 ************************************************************************/


CBmpProc& CBmpProc::operator=(const HBITMAP sou)
{
	// 入口检测
	if (!sou)
		return *this;

	CBmpProc tmp;

	if (!tmp.Attach(sou))
		return *this;

	ASSERT(sou == (HBITMAP)tmp);

	// 调用类赋值操作符函数
	*this = tmp;
	// 分离源位图,防止析构函数将其删除
	tmp.Detach();

	return *this;
}



/*************************************************************************
 *
 * operator==()
 *
 * 参数说明:
 * 
 * const CBmpProc& ds		- 源位图类
 * 
 * 返回值:
 * 
 * BOOL						- 如果相同返回TRUE,不同返回FALSE
 * 
 * 描述:
 *
 * 判断源位图类与本身类是否相同
 * 
 * 该函数通过比较两个类的位图来判定它们是否具有相同的图像。
 * 
 * 注:# 如果两个类都是空的(即都没有图像),则该函数将视它们是不相同的
 *
 ************************************************************************/


BOOL CBmpProc::operator==(const CBmpProc& ds)
{
	// 如果两个类中有一个或都是空的(即都没有图像),则该函数将视它们
	// 是不相同的
	if ((ds.IsValid()==FALSE)||(IsValid()==FALSE))
		return FALSE;

	// 如果是与自身比较,则直接返回TRUE
	if (this == &ds)
		return TRUE;

	ASSERT(m_pInfo);
	ASSERT(ds.m_pInfo);
	ASSERT(m_pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
	ASSERT(ds.m_pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));

	// 信息块长度比较
	if (::_msize(m_pInfo) != ::_msize(ds.m_pInfo))
		return FALSE;

	// 信息块内容比较
	if (::memcmp((const void*)m_pInfo, \
		(const void*)ds.m_pInfo,::_msize(m_pInfo)))
		return FALSE;

	// 创建存放DIB位数据的缓冲区
	LPSTR pBits1 = (LPSTR)CreateMemoryBlockFromAddress((LPVOID)NULL, 
		CalculateDIBitsSize((LPBITMAPINFOHEADER)m_pInfo));
	if (!pBits1)
		return FALSE;

	LPSTR pBits2 = (LPSTR)CreateMemoryBlockFromAddress((LPVOID)NULL, 
		CalculateDIBitsSize((LPBITMAPINFOHEADER)m_pInfo));
	if (!pBits2)
	{
		::free((void*)pBits1);
		return FALSE;
	}

	// 复制位图信息块,因为GetDIBits()函数有可能会改变颜色表数据
	LPBITMAPINFO pInfo = (LPBITMAPINFO)CreateMemoryBlockFromAddress(
		(LPVOID)m_pInfo);
	if (!pInfo)
	{
		::free((void*)pBits1);
		::free((void*)pBits2);
		return FALSE;
	}

	ASSERT(pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));

	HWND hWnd = ::GetDesktopWindow();
	ASSERT(hWnd);
	HDC hDC;

	// 获取位图的DIB位数据
	hDC = ::GetDC(hWnd);
	ASSERT(m_hObject);
	ASSERT(ds.m_hObject);
	if (!::GetDIBits(hDC,(HBITMAP)m_hObject,0,pInfo->bmiHeader.biHeight, \
			(LPVOID)pBits1,pInfo,DIB_RGB_COLORS))
	{
		::free((void*)pBits1);
		::free((void*)pBits2);
		::free((void*)pInfo);
		::ReleaseDC(hWnd, hDC);
		return FALSE;
	}
	if (!::GetDIBits(hDC,(HBITMAP)ds.m_hObject,0,pInfo->bmiHeader.biHeight, \
			(LPVOID)pBits2,pInfo,DIB_RGB_COLORS))
	{
		::free((void*)pBits1);
		::free((void*)pBits2);
		::free((void*)pInfo);
		::ReleaseDC(hWnd, hDC);
		return FALSE;
	}
	::ReleaseDC(hWnd, hDC);
	::free((void*)pInfo);

	// 位内容比较
	LONG leng = (LONG)CalculateDIBitsSize((LPBITMAPINFOHEADER)m_pInfo)/4;
	LPDWORD lp1 = (LPDWORD)pBits1;	// DIB位数据是DWORD对齐的
	LPDWORD lp2 = (LPDWORD)pBits2;

	// 因为不清楚memcmp()函数是否可以比较大于64K的数据,所以才采用这种
	// 老笨的方法。
	while(leng--)
	{
		if (*lp1 != *lp2) break;
		lp1++; lp2++;
	}

	// 比较完之后,位数据已无用,释放
	::free((void*)pBits1);
	::free((void*)pBits2);
	
	if (leng != -1L)
		return FALSE;	// 位数据不同返回FALSE

	return TRUE;
}



/*************************************************************************
 *
 * operator!=()
 *
 * 参数说明:
 * 
 * const CBmpProc& ds		- 源位图类
 * 
 * 返回值:
 * 
 * BOOL						- 如果不同返回TRUE,相同返回FALSE
 * 
 * 描述:
 *
 * 判断源位图类是否与本身类不同
 * 
 * 该函数通过比较两个类的位图来判定它们是否具有相同的图像。
 * 
 * 注:# 如果两个类都是空的(即都没有图像),则该函数将视它们是不相同的
 *
 ************************************************************************/


BOOL CBmpProc::operator!=(const CBmpProc& ds)
{
	return ((*this) == ds) ? FALSE:TRUE;
}



/*************************************************************************
 *
 * Draw()
 *
 * 参数说明:
 *
 * CDC& dc					- 显示位图的设备描述表
 * const CRect* rcDst		- 目标矩形
 * const CRect* rcSrc		- 源矩形
 * 
 * 返回值:
 *
 * BOOL						- 如果成功返回TRUE,否则返回FALSE
 * 
 * 描述:
 *
 * 将类中指定区域的图像绘入目标设备描述表的指定区域,如果源区域(即矩形)
 * 和目标区域不同,将产生拉伸或压缩动作
 * 
 * 如果源矩形和目标矩形是NULL,则函数将视这两个矩形都等于类中图像的尺寸
 * 
 * 如果类中没有图像,它什么也不作,直接返回
 * 如果待绘制的图像不在当前剪贴区域内,则直接返回
 * 
 ************************************************************************/


BOOL CBmpProc::Draw(CDC& dc, const CRect* rcDst, const CRect* rcSrc)
{
	// 如果类中没有图像,直接返回
	if (!IsValid())
		return TRUE;

	ASSERT(m_hObject);

	// 缺省矩形等于图像尺寸
	CRect DCRect(Rect());			// 目标位置数据
	CRect DibRect(Rect());			// 源位置数据

	if (rcDst)
		DCRect = *rcDst;
	if (rcSrc)
		DibRect = *rcSrc;

	// 如果待绘制的图像不在当前剪贴区域内,则直接返回
	if (!dc.RectVisible(&DCRect))
		return TRUE;

	CDC			compDC;
	CBitmap		*pOldBmp;

	compDC.CreateCompatibleDC(NULL);
	pOldBmp	= compDC.SelectObject((CBitmap*)this);

	/* 设置目标DC的拉伸模式为STRETCH_DELETESCANS,也就是不显示拉伸掉的图像 */
	int srlold = dc.SetStretchBltMode(STRETCH_DELETESCANS);

	// 显示位图
	dc.StretchBlt(DCRect.left, DCRect.top, DCRect.Width(), DCRect.Height(), 
					&compDC, DibRect.left, DibRect.top, 
					DibRect.Width(), DibRect.Height(), SRCCOPY);
	
	// 恢复设备描述表原来的设置
	dc.SetStretchBltMode(srlold);
	compDC.SelectObject(pOldBmp);

	return TRUE;
}



/*************************************************************************
 *
 * DrawTile()
 *
 * 参数说明:
 *
 * CDC& dc					- 显示位图的设备描述表
 * CRect* crArea			- 铺设范围(矩形坐标)
 * 
 * 返回值:
 *
 * BOOL						- 如果成功返回TRUE,否则返回FALSE
 * 
 * 描述:
 *
 * 将类中的图像以平铺方式排满指定区域
 * 
 * 如果入口参数crArea是NULL,则函数返回FALSE,如果矩形坐标不符合规范(比如
 * 左边的坐标大于右边的坐标)则函数将自动将其规范化。如果矩形坐标的宽度
 * 或高度是0,则函数将返回FALSE
 * 
 * 如果类中没有图像,它什么也不作,直接返回
 * 
 ************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -