上面,我簡單的說了對話方塊介面的設計與實現,下面將介紹按鈕控制項重繪的實現:
在MFC下編程,很多時候對於標準的按鈕控制項不是很滿意,想要弄的美觀些。這就需要按鈕重繪。重繪按鈕一般的實現方法就是重寫CButton類。
首先給工程添加一個自繪按鈕類MyDrawButton,基類為CButton。要想讓按鈕具備自繪功能,就要為按鈕添加BS_OWNERDRAW屬性。為類CButton重載PreSubclassWindow虛函數。在該函數中添加如下一行代碼:
SetButtonStyle(GetButtonStyle() | BS_OWNERDRAW);
當按鈕控制項具有了自繪功能之後,每次控制項狀態改變都會觸發DrawItem函數,在該函數中來繪製按鈕的形態外觀,所以第二步就要重載DrawItem虛函數。在這個函數中就可以自由發揮了,比如繪製背景,底色,按鈕標題,繪製文本字型樣式等等。
一般都會為按鈕定義幾種不同狀態時的外觀,比如游標滑過時的狀態,按鈕按下時的狀態,按鈕禁用時的狀態,以及按鈕的正常狀態等等。這就要為新的按鈕添加幾種重要的訊息響應。比如WM_MOUSELEAVE訊息,WM_MOUSEHOVER訊息和WM_MOUSEMOVE訊息等等,值得一提的是前兩個訊息的響應函數需要自己手動添加,微軟提供了一個TrackMouseEvent函數在游標離開一個視窗時投遞WM_MOUSELEAVE訊息,游標滑過視窗時投遞WM_MOUSEHOVER訊息。一般來說可以在WM_MOUSEMOVE訊息響應函數中調用TrackMouseEvent函數來投遞WM_MOUSELEAVE訊息和WM_MOUSEHOVER訊息。然後在WM_MOUSELEAVE訊息的響應函數中標記“游標已經離開按鈕”,然後調用InvalidateRect函數讓按鈕重繪。在WM_MOUSEHOVER訊息的響應函數中標記“游標正在按鈕上方”,並調用InvalidateRect函數讓按鈕重繪。
在本文中,重繪按鈕分為3個部分。
(1)繪製按鈕背景樣式,即繪製背景bmp位元影像,使得按鈕具有自訂的樣式,同時在繪製按鈕背景的輸出位元影像時採用TransparentBlt()函數,該函數的作用是使表單上顯示位元影像的背景與表單背景色融為一體,不僅可以顯示按鈕bmp位元影像樣式,而且還可以使背景透明。
(2)就是繪製按鈕上的文本。主要繪製按鈕上文本的樣式,包括字型大小,字型樣式,字型顏色等屬性。
(3)實現不同狀態下的按鈕的外觀樣式,主要包括WM_MOUSEMOVE和WM_MOUSELEAVE兩個訊息的訊息處理函數。分別實現滑鼠在按鈕地區上和不在按鈕地區上的狀態。為了標記滑鼠移動到按鈕地區內停留,需要用到一個定時器來標記滑鼠是否還在按鈕地區內停留。在WM_MOUSEMOVE內啟動定時器,觸發WM_MOUSELEAVE訊息時結束定時器即銷毀定時器。定時器的主要代碼如下:
void MyDrawButton::OnTimer(UINT_PTR nIDEvent){ // TODO: 在此添加訊息處理常式代碼和/或調用預設值 if(nIDEvent != 24) return; CPoint point; CRect rect; GetWindowRect(&rect); GetCursorPos(&point); // 如果滑鼠離開按鈕地區,重繪按鈕 if (!rect.PtInRect(point) && m_bMove) { KillTimer (24); m_DrawState=ST_MOVEOUT; m_bMove=FALSE; Draw(); } CButton::OnTimer(nIDEvent);}
重繪按鈕類MyDrawButton的主要實現代碼如下:
定義的一些重繪用到的變數:
#define ST_MOVEIN 0//繪製狀態—在按鈕地區上#define ST_MOVEOUT 1 //繪製狀態—不在按鈕地區上int m_DrawState;//繪製狀態 int m_nBmpID;//當前顯示的背景bmp位元影像的資源ID bool m_bMove;//滑鼠是否進入按鈕地區 COLORREF m_clText;//當前文本顏色 COLORREF m_clActiveText;//滑鼠進入按鈕地區時文本顏色 COLORREF m_clNormalText;//滑鼠離開按鈕地區時文本顏色
訊息處理函數和定義的函數以及實現:
void MyDrawButton::PreSubclassWindow(){ SetButtonStyle(GetButtonStyle() | BS_OWNERDRAW);}void MyDrawButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){ Draw();//繪製按鈕}void MyDrawButton::Draw()//繪製按鈕{ DrawBackground();//繪製按鈕bmp位元影像,並使背景透明化 DrawText();//繪製按鈕上的文本}void MyDrawButton::DrawText(){//繪製按鈕上的文本的字型大小、樣式等 CString itemString; CRect clientRect; CClientDC dc(this); GetClientRect(&clientRect); GetWindowText(itemString); if(itemString) { CSize size=dc.GetTextExtent (itemString);//獲得所選字型中指定字串的高度和寬度 int rectwidth=clientRect.Width(); int rectheight=clientRect.Height(); int textwidth=size.cx ; int textheight=size.cy ; int x,y; // 文本的位置 // 計算文本的輸出位置 x=(rectwidth-textwidth)/2;//水平置中 y=(rectheight-textheight)/2;//垂直置中 switch(m_DrawState) { case ST_MOVEIN://滑鼠進入按鈕地區 m_clText=m_clActiveText; break; case ST_MOVEOUT://滑鼠離開按鈕地區 m_clText=m_clNormalText; break; default: m_clText=m_clNormalText; break; } dc.SetTextColor(m_clText); dc.SetBkMode(TRANSPARENT); CFont *font ; font =new CFont(); int fontSize = 14; font->CreateFont(fontSize,0,0,0,FW_BOLD,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_SWISS,_T("宋體")); dc.SelectObject(font); dc.TextOut (x,y,itemString); }}void MyDrawButton::SetBkBmp(int nBmpID){//設定按鈕bmp位元影像樣式 m_nBmpID = nBmpID;}void MyDrawButton::DrawBackground(){//繪製按鈕bmp位元影像,並使背景透明化 CRect winRC; CDC* pDC=GetWindowDC(); CDC memDC; memDC.CreateCompatibleDC(pDC); BITMAPINFO bmpInfo; CBitmap bmp; GetWindowRect(&winRC); bmp.LoadBitmap(m_nBmpID); bmp.GetObject(sizeof(BITMAPINFO),&bmpInfo); int nBmpCX = bmpInfo.bmiHeader.biWidth; int nBmpCY = bmpInfo.bmiHeader.biHeight; memDC.SelectObject(bmp); pDC->TransparentBlt(0,0,nBmpCX,nBmpCY,&memDC,0,0, nBmpCX,nBmpCY,RGB(14,94,157));//在視窗中繪製位元影像,RGB(14,94,157)是透明色 bmp.DeleteObject(); ReleaseDC(pDC); }
到此,按鈕的自訂重繪完成了,接下來就可以使用自己重繪的按鈕類MyDrawButton了。首先往對話方塊中添加一個按鈕控制項(以立即掃描按鈕為例),假設它的ID值為IDC_TEST。進入類嚮導(Class Wizard)的成員變數屬性頁面,為IDC_ BEGIN添加一個變數m_btnBegin。如下:
MyDrawButton m_btnBegin;
然後就可以調用MyDrawButton的方法來設定按鈕的樣式了。如下:
m_btnBegin.SetBkBmp(IDB_BTN210x95,IDB_BTN210x95_3);//IDB_BTN210x95,IDB_BTN210x95分別為預設位元影像和滑鼠在按鈕地區時的位元影像。
到現在為止,按鈕類的重繪完成了,可以隨意定義自己喜歡的樣式的按鈕了。現在相對完善成形的一個垃圾清理工具軟體就開發完了。
最後軟體的主要成果介面如下:
軟體開啟準備就緒介面
正在運行截面圖
掃描完成介面圖:
清理完成介面圖
原始碼:http://download.csdn.net/detail/jczmdeveloper/4998982