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

📄 bmpproc.cpp

📁 用VC写的监控中心后台程序。 代码全
💻 CPP
📖 第 1 页 / 共 5 页
字号:

BOOL CBmpProc::DrawTile(CDC& dc, CRect* crArea)
{
	if (!crArea)
		return FALSE;

	// 如果类中没有图像,直接返回
	if (!IsValid())
		return TRUE;

	CRect rect = *crArea;
	CRect tprc;

	// 矩形坐标规范化
	rect.NormalizeRect();

	if ((rect.Width()==0)||(rect.Height()==0))
		return FALSE;

	ASSERT(m_pInfo);
	ASSERT(m_hObject);

	// 因为下面的代码将改变设备描述表中剪贴区域的设置,所以先将其保存
	int savedc = dc.SaveDC();

	CRgn newrgn;
	newrgn.CreateRectRgnIndirect(&rect);
	// 只显示指定矩形中可见的部分(用AND操作)
	dc.SelectClipRgn(&newrgn, RGN_AND);

	for (int y=rect.top;y<rect.bottom;y+=Height())
	{
		for (int x=rect.left;x<rect.right;x+=Width())
		{
			// 以瓦片方式重复显示图像
			tprc.SetRect(x,y,x+Width(),y+Height());
			Draw(dc, &tprc);
		}
	}

	dc.RestoreDC(savedc);
	// 恢复设备描述表的内容之后,将区域的句柄显示的删除
	// (微软在文档中特意注明要用CGdiObject::DeleteObject()
	//   函数显示的删除区域句柄,不知是什么原因)
	newrgn.CGdiObject::DeleteObject();

	return TRUE;
}



/*************************************************************************
 *
 * DrawCenter()
 *
 * 参数说明:
 *
 * CDC& dc					- 显示位图的设备描述表
 * CRect* crArea			- 显示范围(矩形坐标)
 * 
 * 返回值:
 *
 * BOOL						- 如果成功返回TRUE,否则返回FALSE
 * 
 * 描述:
 *
 * 将类中图像绘入目标设备描述表的指定区域(矩形)的中央,即图像中点与矩
 * 形中点重合
 * 
 * 如果矩形的尺寸小于图像尺寸,则图像的四周部分会不可见
 * 如果入口参数crArea是NULL,函数将返回FALSE
 * 如果类中没有图像,它什么也不作,直接返回
 * 如果矩形坐标不符合规范(比如左边的坐标大于右边的坐标)则函数将自动将
 * 其规范化。如果矩形坐标的宽度或高度是0,则函数将返回FALSE
 * 
 ************************************************************************/


BOOL CBmpProc::DrawCenter(CDC& dc, CRect* crArea)
{
	if (!crArea)
		return FALSE;

	// 如果类中没有图像,直接返回
	if (!IsValid())
		return TRUE;

	CRect rect = *crArea;

	// 矩形坐标规范化
	rect.NormalizeRect();

	if ((rect.Width()==0)||(rect.Height()==0))
		return FALSE;

	ASSERT(m_pInfo);
	ASSERT(m_hObject);

	// 取指定矩形的中点坐标
	CPoint cpce = rect.CenterPoint();
	CRect  tprc(CPoint(cpce.x-Width()/2,cpce.y-Height()/2), Size());

	// 因为下面的代码将改变设备描述表中剪贴区域的设置,所以先将其保存
	int savedc = dc.SaveDC();

	CRgn newrgn;
	newrgn.CreateRectRgnIndirect(&rect);
	// 只显示指定矩形中可见的部分(用AND操作)
	dc.SelectClipRgn(&newrgn, RGN_AND);

	Draw(dc, &tprc);

	dc.RestoreDC(savedc);
	newrgn.CGdiObject::DeleteObject();

	return TRUE;
}



/*************************************************************************
 *
 * DrawTranCenter()
 *
 * 参数说明:
 *
 * CDC& dc					- 显示位图的设备描述表
 * CRect* crArea			- 显示范围(矩形坐标)
 * COLORREF crColour		- 要滤掉或保留的颜色(缺省值是白色)
 * int mode					- 如果是0则将不显示指定的颜色,如果是1则保留指定
 *						      的颜色(缺省值为0)
 * 
 * 返回值:
 *
 * BOOL						- 如果成功返回TRUE,否则返回FALSE
 * 
 * 描述:
 *
 * 将类中图像透明的绘入目标设备描述表的指定区域(矩形)的中央,即图像中点
 * 与矩形中点重合
 * 
 * 如果矩形的尺寸小于图像尺寸,则超出矩形的图像部分会不可见
 * 如果入口参数crArea是NULL,函数将返回FALSE
 * 如果类中没有图像,它什么也不作,直接返回
 * 如果矩形坐标不符合规范(比如左边的坐标大于右边的坐标)则函数将自动将
 * 其规范化。如果矩形坐标的宽度或高度是0,则函数将返回FALSE
 * 
 ************************************************************************/


BOOL CBmpProc::DrawTranCenter(CDC& dc, 
							  CRect* crArea, 
							  COLORREF crColour, 
							  int mode)
{
	if (!crArea)
		return FALSE;

	// 如果类中没有图像,直接返回
	if (!IsValid())
		return TRUE;

	CRect rect = *crArea;

	// 矩形坐标规范化
	rect.NormalizeRect();

	if ((rect.Width()==0)||(rect.Height()==0))
		return FALSE;

	ASSERT(m_pInfo);
	ASSERT(m_hObject);

	// 取指定矩形的中点坐标
	CPoint cpce = rect.CenterPoint();
	CRect  tprc(CPoint(cpce.x-Width()/2,cpce.y-Height()/2), Size());

	// 因为下面的代码将改变设备描述表中剪贴区域的设置,所以先将其保存
	int savedc = dc.SaveDC();

	CRgn newrgn;
	newrgn.CreateRectRgnIndirect(&rect);
	// 只显示指定矩形中可见的部分(用AND操作)
	dc.SelectClipRgn(&newrgn, RGN_AND);

	DrawTransparentInRect(dc, crColour, &tprc, NULL, mode);	// 显示透明图像

	dc.RestoreDC(savedc);
	newrgn.CGdiObject::DeleteObject();

	return TRUE;
}



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


BOOL CBmpProc::DrawTranTile(CDC& dc, 
							CRect* crArea, 
							COLORREF crColour, 
							int mode)
{
	if (!crArea)
		return FALSE;

	// 如果类中没有图像,直接返回
	if (!IsValid())
		return TRUE;

	CRect rect = *crArea;
	CRect tprc;

	// 矩形坐标规范化
	rect.NormalizeRect();

	if ((rect.Width()==0)||(rect.Height()==0))
		return FALSE;

	ASSERT(m_pInfo);
	ASSERT(m_hObject);

	// 因为下面的代码将改变设备描述表中剪贴区域的设置,所以先将其保存
	int savedc = dc.SaveDC();

	CRgn newrgn;
	newrgn.CreateRectRgnIndirect(&rect);
	// 只显示指定矩形中可见的部分(用AND操作)
	dc.SelectClipRgn(&newrgn, RGN_AND);

	for (int y=rect.top;y<rect.bottom;y+=Height())
	{
		for (int x=rect.left;x<rect.right;x+=Width())
		{
			// 以瓦片方式重复显示图像
			tprc.SetRect(x,y,x+Width(),y+Height());
			// 显示透明图像
			DrawTransparentInRect(dc, crColour, &tprc, NULL, mode);
		}
	}

	dc.RestoreDC(savedc);
	newrgn.CGdiObject::DeleteObject();

	return TRUE;
}



/*************************************************************************
 *
 * Clear()
 *
 * 参数说明:无
 *
 *
 * 返回值:无
 *
 *
 * 描述:
 *
 * 清除类中的图像
 * 
 * 这个函数将删除类中的位图句柄,并清除类中的描述变量
 * 
 * 如果类中没有图像,它什么也不作,直接返回
 * 
 ************************************************************************/


void CBmpProc::Clear()
{
	// 如果本类中没有有效的BMP,则直接返回
	if (m_mark == FALSE)
	{
		ASSERT(m_type == IT_NULL);
		ASSERT(m_pInfo == NULL);
		ASSERT(m_hObject == NULL);
		return;
	}

	switch(m_type)
	{
	case	IT_NULL:
		ASSERT(FALSE);	// 此时m_type不应该是IT_NULL
		break;
	case	IT_DISKFILE:
		ASSERT(!m_cFileName.IsEmpty());	// 文件来源的位图应该有文件名
	case	IT_RESOURCE:
	case	IT_MEMORY:
	case	IT_CLIP:
	case	IT_CREATE:
		m_cFileName.Empty();

		ASSERT(m_pInfo);
		::free((void*)m_pInfo);
		m_pInfo = NULL;

		// 先分离出原来的BMP句柄,然后删除
		ASSERT((HBITMAP)m_hObject);
		::DeleteObject(CGdiObject::Detach());
		m_hObject = NULL;

		m_addInfo = 0;
		m_type = IT_NULL;
		m_mark = FALSE;
		break;
	default:
		ASSERT(FALSE);
		break;
	}
}



/*************************************************************************
 *
 * Attach()
 *
 * 参数说明:
 * 
 * HBITMAP hBmp				- 待粘贴的位图句柄
 * 
 * 返回值:
 * 
 * BOOL						- 如果成功返回TRUE,否则返回FALSE
 * 
 * 描述:
 *
 * 将指定的位图贴入本身类中。
 * 
 * 注:
 * 
 * # 如果hBmp是一个无效的句柄或是NULL,函数返回FALSE
 * # 如果本身类中原来存在图像,则调用函数成功之后,原来的图像将被删除
 * # hBmp必须是一个兼容于当前显示器颜色格式的DDB位图句柄
 * # 如果函数执行成功后,调用它的程序不应再使用hBmp句柄,因为它已被贴入类中
 * # 如果函数失败,调用它的程序仍可以正常使用hBmp句柄
 * 
 ************************************************************************/


BOOL CBmpProc::Attach(HBITMAP hBmp)
{
	ASSERT(hBmp);
	// 如果hBmp是NULL,则立即返回
	if (!hBmp)
		return FALSE;

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

	// 获取给定位图的宽度、高度及颜色格式信息
	if (::GetObject(hBmp, sizeof(BITMAP), (LPVOID)&bmp) != sizeof(BITMAP))
		return FALSE;

	// 创建临时位图信息块(不带颜色表)
	LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)CreateMemoryBlockFromAddress(
		(LPVOID)NULL, sizeof(BITMAPINFOHEADER));
	if (!lpbi)
		return FALSE;

	// 设置DIB信息块内容
	lpbi->biSize = sizeof(BITMAPINFOHEADER);
	lpbi->biWidth = bmp.bmWidth;
	lpbi->biHeight = bmp.bmHeight;
	lpbi->biPlanes = 1;
	// 在16色系统中,平面数是4,而位数是1,但这在DIB中是不允许的
	lpbi->biBitCount = max(bmp.bmPlanes, bmp.bmBitsPixel);
	if ((lpbi->biBitCount==16)||(lpbi->biBitCount==32))
		lpbi->biCompression = BI_BITFIELDS;
	else
		lpbi->biCompression = BI_RGB;

	// 计算设备分辩率
	hDC = ::GetDC(hWnd);
	lpbi->biXPelsPerMeter = \
		(GetDeviceCaps(hDC,HORZRES)*1000)/GetDeviceCaps(hDC,HORZSIZE);
	lpbi->biYPelsPerMeter = \
		(GetDeviceCaps(hDC,VERTRES)*1000)/GetDeviceCaps(hDC,VERTSIZE);
	::ReleaseDC(hWnd, hDC);

	lpbi->biClrUsed = 0;
	lpbi->biClrImportant = 0;
	lpbi->biSizeImage = CalculateDIBitsSize(lpbi);

	// 计算颜色表的尺寸
	WORD wPalSize = PaletteSize(lpbi);

	// 创建带颜色表的信息块,并复制lpbi信息块中的内容
	LPBITMAPINFO pInfo = (LPBITMAPINFO)CreateMemoryBlockFromAddress(
		(LPVOID)lpbi, sizeof(BITMAPINFOHEADER)+wPalSize);
	if (!pInfo)
	{
		::free((void*)lpbi);
		return FALSE;
	}

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

	// 此时该结构已经无用,释放
	::free((void*)lpbi);

	// 创建存放DIB位数据的缓冲区
	LPSTR pBits = (LPSTR)CreateMemoryBlockFromAddress((LPVOID)NULL, 
		pInfo->bmiHeader.biSizeImage);
	if (!pBits)
	{
		::free((void*)pInfo);
		return FALSE;
	}

	// 下面的代码并不是要获取位图的DIB位数据,而是要取得位图的颜色表
	// 颜色表数据在函数(GetDIBits())调用成功后被填写在pInfo结构中
	hDC = ::GetDC(hWnd);
	if (!::GetDIBits(hDC,hBmp,0,pInfo->bmiHeader.biHeight, \
			(LPVOID)pBits,pInfo,DIB_RGB_COLORS))
	{
		::free((void*)pBits);
		::free((void*)pInfo);
		::ReleaseDC(hWnd, hDC);
		return FALSE;
	}
	::ReleaseDC(hWnd, hDC);

	// 此时并不需要DIB位数据,释放
	::free((void*)pBits);

	// 删除原来的图像,并且设置新的位图
	if (!ClearAndSetData(IT_MEMORY,0,(LPCTSTR)"",pInfo,hBmp))
	{
		::free((void*)pInfo);
		// hBmp指定的位图并不删除
		return FALSE;
	}

	return TRUE;
}



/*************************************************************************
 *
 * Detach()
 *
 * 参数说明:无
 * 
 * 
 * 返回值:
 * 
 * HBITMAP					- 如果成功,返回分离出的位图句柄,否则返回NULL
 * 
 * 描述:
 *
 * 将本身类中的位图分离出来。
 * 
 * 注:
 * 
 * # 如果本身类中原来存在位图,函数成功调用之后,本身类将被清空
 * # 如果本身类中原来没有位图,函数返回NULL
 * 
 ************************************************************************/


HBITMAP CBmpProc::Detach()
{
	if (!IsValid())
		return NULL;

	ASSERT(m_pInfo);
	ASSERT(m_hObject);

	HBITMAP hBmp = (HBITMAP)CGdiObject::Detach();
	ASSERT(hBmp);
	if (!hBmp)
		return NULL;

⌨️ 快捷键说明

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