修改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即屬性中所有者繪製