編寫一個簡單的透明位圖類,有時候可以為程序潤色不少,下面是我寫的一個程序的UI,個人覺得蠻有意思的。
圖一 外觀
這個類可以插入到任何一個程序當中,它提供一個統一的接口,接口函數接收圖象的資源索引號、長、寬3個參數。當然,你也可以加上一個父窗口的指針參數,用來決定該類對象Create行為,便於指定該圖象代表的窗口應該依附在哪個父窗口之上。
編寫這個類需要熟悉對CRgn類的運用。如成員函數CombineRgn和SetWindowRgn,具體信息請查閱msdn。
那麼好,下面我們來一步步創建這個類。
一、首先要准備一幅用來展示在UI上的圖象,自己定義一種透明色,用該色來填充透明部分,這裡要注意的是,透明色應該是該圖象中顏色最少的色,還要注意的是透明和非透明的交界處一定要求清晰,不能存在過渡色。這裡我使用的是RGB(255, 0,255)。如下:
圖二 透明位圖
二、使用MFC AppWizard創建一個對話框程序,在資源選項卡中把上一步的圖象添加進來,創建一個新的窗口類CMyWnd,派生自generic CWnd。
為該類添加3個私有成員:
private:
為該類添加WM_CREATE和WM_ERASEBKGND2個消息處理函數:
CRect m_rtWnd;
CBitmap m_bitmap;
BITMAP m_bmp;
int CMyWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
COLORREF crl;
GetWindowRect(&m_rtWnd);
CRgn wndRgn, rgnTemp;
CDC* pDC = GetWindowDC();
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC);
CBitmap* pOldBitmap = dcCompatible.SelectObject(&m_bitmap);
wndRgn.CreateRectRgn(0,0,m_rtWnd.Width(),m_rtWnd.Height());
for(int x=0; x<m_rtWnd.Width(); x++)
{
for(int y=0; y<m_rtWnd.Height(); y++)
{
crl = dcCompatible.GetPixel(x, y);
if(crl == TRANSCOLOR)
{
rgnTemp.CreateRectRgn(x, y, x+1, y+1);
//裁減掉透明色區域
wndRgn.CombineRgn(&wndRgn,&rgnTemp, RGN_XOR);
rgnTemp.DeleteObject();
}
}
}
//設置最終的窗口范圍
SetWindowRgn((HRGN)wndRgn,TRUE);
dcCompatible.SelectObject(pOldBitmap);
ReleaseDC(pDC);
ReleaseDC(&dcCompatible);
return 0;
}
BOOL CMyWnd::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC);
CBitmap* pOldBitmap = dcCompatible.SelectObject(&m_bitmap);
pDC->StretchBlt(0, 0, m_bmp.bmWidth, m_bmp.bmHeight,
&dcCompatible, 0, 0, m_bmp.bmWidth,
m_bmp.bmHeight, SRCCOPY);
dcCompatible.SelectObject(pOldBitmap);
ReleaseDC(&dcCompatible);
return TRUE;
}
為該類添加一個供外部調用的函數SetPic:
void CMyWnd::SetPic(UINT nIDPic, int nLeft, int nTop)
{
if(NULL != m_bitmap.m_hObject)
{
m_bitmap.DeleteObject();
}
m_bitmap.LoadBitmap(nIDPic);
m_bitmap.GetBitmap(&m_bmp);
int nRight = m_bmp.bmWidth + nLeft;
int nBottom = m_bmp.bmHeight + nTop;
Create(NULL, NULL, WS_CHILD, CRect(nLeft, nTop, nRight, nBottom),
AfxGetApp()->m_pMainWnd, nIDPic);
ShowWindow(SW_SHOWNORMAL);
}
最後別忘了在MyWnd.cpp文件的前面加上:
#define TRANSCOLOR RGB(255,0,255)
這是定義的用作透明色的紫色,這樣,透明位圖類就寫完了。
現在在對話框XXXDlg.h頭文件中加上一個CmyWnd m_wnd,用來做裁減圖象的承載窗口對象,並在BOOL CTransBMPDlg::OnInitDialog()函數中加上一條代碼:
m_wnd.SetPic(IDB_BITMAP1, 10, 10);
這樣就大功告成啦,還簡單吧^_^。
編程環境:Visual C++6.0 & MFC
本文配套源碼