1. 程式人生 > >修改CButton類按鈕背景顏色和文字顏色

修改CButton類按鈕背景顏色和文字顏色

要想修改CButton類按鈕背景顏色和文字顏色,必須利用自繪方法對按鈕進行重新繪製。這可以通過定義一個以CButton為基類的新按鈕類來實現。以下為具體的實現方法:

方法一:

加入一個新類,類名: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新增下列訊息函式:

PreSubclassWindow();
DrawItem();
onMouseMove();
OnLButtonDown();
OnLButtonUp();

在各函式內加入程式碼:

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()函式。

這裡我做了三項工作:獲取按鈕尺寸、獲取按鈕文字、繪製按鈕。其中繪製工作在自定義函式DrawButton()中完成。以下就是繪製過程:

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。之後,可以用該變數呼叫介面函式設定按鈕顏色和字型。

以上測試過,太複雜。又生一類。

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

方法二:

新增dlg類的WM_DRAWITEM訊息處理函式

void CBtncolorDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
// TODO: Add your message handler code here and/or call default
if(nIDCtl==IDC_BUTTON1)         //checking for the button 
    {
    CDC dc;
    RECT rect;
    dc.Attach(lpDrawItemStruct ->hDC);   // Get the Button DC to CDC
    
    rect = lpDrawItemStruct->rcItem;     //Store the Button rect to our local rect.
    
    dc.Draw3dRect(&rect,RGB(255,255,255),RGB(0,0,0)); 

    dc.FillSolidRect(&rect,RGB(100,100,255));//Here you can define the required color to appear on the Button.

    UINT state=lpDrawItemStruct->itemState; //This defines the state of the Push button either pressed or not. 

    if((state & ODS_SELECTED))
    {
        dc.DrawEdge(&rect,EDGE_SUNKEN,BF_RECT);

    }
    else
    {
        dc.DrawEdge(&rect,EDGE_RAISED,BF_RECT);
    }

    dc.SetBkColor(RGB(100,100,255));   //Setting the Text Background color
    dc.SetTextColor(RGB(255,0,0));     //Setting the Text Color


    TCHAR buffer[MAX_PATH];           //To store the Caption of the button.
    ZeroMemory(buffer,MAX_PATH );     //Intializing the buffer to zero
        ::GetWindowText(lpDrawItemStruct->hwndItem,buffer,MAX_PATH); //Get the Caption of Button Window 
    
    dc.DrawText(buffer,&rect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);//Redraw the Caption of Button Window 
    
    dc.Detach(); // Detach the Button DC
    }                
    CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);

}

把要定義的按鈕設定為Owner Draw即屬性中所有者繪製