📄 bmpproc.cpp
字号:
* 或高度是0,则函数将返回FALSE
*
* 如果类中没有图像,它什么也不作,直接返回
*
************************************************************************/
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句柄
*
************************************************************************/
UINT mpack::m_Number=0;
UINT mpack::m_OldID=0;
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -