?? bmpproc.cpp
字號:
// 如果類中沒有圖像,直接返回
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;
m_hObject = NULL;
switch(m_type)
{
case IT_NULL:
ASSERT(FALSE); // 此時m_type不應該是IT_NULL
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -