如下爲具體的實現方法:web
加入一個新類,類名:CMyButton,基類:CButton。數組
在頭文件 MyButton.h 中加入如下變量和函數定義:函數
private: int m_Style; //按鈕形狀(0-正常,1-當前,2-按下,3-鎖定) BOOL b_InRect; //鼠標進入標誌 CString m_strText; //按鈕文字 COLORREF m_ForeColor; //文本顏色 COLORREF m_BackColor; //背景色 COLORREF m_LockForeColor; //鎖定按鈕的文字顏色 CRect m_ButRect; //按鈕尺寸 CFont* p_Font; //字體 void DrawButton(CDC *pDC); //畫正常的按鈕 // 接口函數 public: void SetText(CString str); void SetForeColor(COLORREF color); //設置文本顏色 void SetBkColor(COLORREF color); //設置背景顏色 void SetTextFont(int FontHight,LPCTSTR FontName); //設置字體 |
在 MyButton.cpp 的構造函數中初始化變量:字體
CMyButton::CMyButton() { m_Style = 0; //按鈕形狀風格 b_InRect = false; //鼠標進入標誌 m_strText = _T(""); //按鈕文字(使用默認文字) m_ForeColor = RGB(0,0,0); //文字顏色(黑色) m_BackColor = RGB(243,243,243); //背景色(灰白色) m_LockForeColor = GetSysColor(COLOR_GRAYTEXT); //鎖定按鈕的文字顏色 p_Font = NULL; //字體指針 } |
用ClassWizard添加下列消息函數:this
PreSubclassWindow();
DrawItem();
OnMouseMove();
OnLButtonDown();
OnLButtonUp();spa
在各函數內加入代碼:.net
void CMyButton::PreSubclassWindow() { ModifyStyle( 0, BS_OWNERDRAW ); //設置按鈕屬性爲自畫式 CButton::PreSubclassWindow(); } |
PreSubclassWindow()在按鈕建立前自動執行,因此咱們能夠在其中作一些初始工做。這裏我只作了一項工做,就是爲按鈕設置屬性爲「自繪」式,這樣,用戶在添加按鈕後,就不需設置「Owner draw」屬性了。指針
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDC *pDC = CDC::FromHandle( lpDrawItemStruct->hDC ); m_ButRect = lpDrawItemStruct->rcItem; //獲取按鈕尺寸 if( m_strText.IsEmpty() ) GetWindowText( m_strText ); //獲取按鈕文本 int nSavedDC = pDC->SaveDC(); VERIFY( pDC ); DrawButton( pDC ); //繪製按鈕 pDC->RestoreDC( nSavedDC ); } |
DrawItem()函數是一個關鍵函數,按鈕的繪製工做就在這裏進行,它的做用至關於對話框中的OnPaint()函數和視圖中的OnDraw()函數。code
這裏我作了三項工做:獲取按鈕尺寸、獲取按鈕文本、繪製按鈕。其中繪製工做在自定義函數DrawButton()中完成。如下就是繪製過程:orm
void CMyButton::DrawButton(CDC *pDC) { //調整狀態 if( m_Style==3 ) m_Style = 0; if( GetStyle() & WS_DISABLED ) m_Style = 3; //禁止狀態 //根據狀態調整邊框顏色和文字顏色 COLORREF bColor, fColor; //bColor爲邊框顏色,fColor爲文字顏色 switch( m_Style ) { case 0: bColor = RGB(192,192,192); fColor = m_ForeColor; break; //正常按鈕 case 1: bColor = RGB(255,255,255); fColor = m_ForeColor; break; //鼠標進入時按鈕 case 2: bColor = RGB(192,192,192); fColor = m_ForeColor; break; //按下的按鈕 case 3: bColor = m_BackColor; fColor = m_LockForeColor; break; //鎖定的按鈕 } //繪製按鈕背景 CBrush Brush; Brush.CreateSolidBrush( m_BackColor ); //背景刷 pDC->SelectObject( &Brush ); CPen Pen; Pen.CreatePen(PS_SOLID, 1, bColor ); pDC->SelectObject( &Pen ); pDC->RoundRect(&m_ButRect,CPoint(5,5)); //畫圓角矩形 //繪製按鈕按下時的邊框 if( m_Style!=2 ) { CRect Rect; Rect.SetRect( m_ButRect.left+2, m_ButRect.top+1, m_ButRect.right, m_ButRect.bottom ); pDC->DrawEdge( &Rect, BDR_RAISEDINNER, BF_RECT ); //畫邊框 } //繪製按鈕文字 pDC->SetTextColor( fColor ); //畫文字 pDC->SetBkMode( TRANSPARENT ); pDC->DrawText( m_strText, &m_ButRect, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS); //繪製擁有焦點按鈕的虛線框 if( GetFocus()==this ) { CRect Rect; Rect.SetRect( m_ButRect.left+3, m_ButRect.top+2, m_ButRect.right-3, m_ButRect.bottom-2 ); pDC->DrawFocusRect( &Rect ); //畫擁有焦點的虛線框 } } |
變量 m_Style 表徵當前按鈕狀態,它的取值爲:0-正常,1-當前,2-按下,3-鎖定。不一樣狀態下按鈕的邊框顏色和文字顏色有所不一樣。m_Style 的值在鼠標響應函數中進行修改。
繪製工做主要利用CDC類的繪圖函數完成,主要注意在 m_Style 不一樣取值下表現出來的差異。
void CMyButton::OnMouseMove(UINT nFlags, CPoint point) { if( !b_InRect || GetCapture()!=this ) //鼠標進入按鈕 { b_InRect = true; //設置進入標誌 SetCapture(); //捕獲鼠標 m_Style = 1; //設置按鈕狀態 Invalidate(); //重繪按鈕 } else { if ( !m_ButRect.PtInRect(point) ) //鼠標離開按鈕 { b_InRect = false; //清除進入標誌 ReleaseCapture(); //釋放捕獲的鼠標 m_Style = 0; //設置按鈕狀態 Invalidate(); //重繪按鈕 } } CButton::OnMouseMove(nFlags, point); } |
OnMouseMove()函數是鼠標移動消息函數,用於斷定當前鼠標指針是否在按鈕上。b_InRect是個標誌,爲true表示鼠標指針進入了按鈕區域,此時要捕獲鼠標,讓鼠標命令傳送給按鈕。當鼠標指針離開按鈕時,要清除b_InRect標誌,而且釋放捕獲的鼠標,讓其它窗口能夠接收鼠標命令。
Invalidate()函數用於更新按鈕,它會自動調用DrawItem()函數從新繪製按鈕。
設置條件的目的是僅在鼠標指針進入按鈕和離開按鈕時更新按鈕,這樣能夠防止鼠標在按鈕上移動時發生閃爍。
void CMyButton::OnLButtonDown(UINT nFlags, CPoint point) { m_Style = 2; Invalidate(); //重繪按鈕 CButton::OnLButtonDown(nFlags, point); } |
OnLButtonDown()函數是單擊鼠標左鍵時的消息函數。這裏只是從新繪製按鈕,具體的單擊響應應該在擁有按鈕的對話框或視圖中進行。
void CMyButton::OnLButtonUp(UINT nFlags, CPoint point) { m_Style = 1; Invalidate(); //重繪按鈕 CButton::OnLButtonUp(nFlags, point); } |
OnLButtonUp()函數是單擊鼠標左鍵後彈起時的消息函數。這裏也只是重繪按鈕,這樣能使按鈕在按下和彈起時有所不一樣,使按鈕看上去有動態效果。
接口函數是用 CMyButton類 定義的按鈕修改顏色、字體和按鈕文字的接口,由如下函數組成:
//設置按鈕文本 void CMyButton::SetText(CString str) { m_strText = _T(""); SetWindowText(str); } |
//設置文本顏色 void CMyButton::SetForeColor(COLORREF color) { m_ForeColor = color; Invalidate(); } |
//設置背景顏色 void CMyButton::SetBkColor(COLORREF color) { m_BackColor = color; Invalidate(); } |
//設置字體(字體高度、字體名) void CMyButton::SetTextFont(int FontHight,LPCTSTR FontName) { if ( p_Font ) delete p_Font; //刪除舊字體 p_Font = new CFont; p_Font->CreatePointFont( FontHight, FontName ); //建立新字體 SetFont( p_Font ); //設置字體 } |
因爲新字體由 new 生成,必須顯式回收,這項工做能夠在 CMyButton類 的析構函數中進行:
CMyButton::~CMyButton() { if ( p_Font ) delete p_Font; //刪除字體 } |
這樣一個可設置顏色、字體的按鈕類就作好了。使用時,先在對話框中放置好按鈕,再用 ClassWizard 爲按鈕添加控制變量,而且將變量的類型設置爲 CMyButton。以後,能夠用該變量調用接口函數設置按鈕顏色和字體。具體狀況能夠參考示例程序。