由於MFC的按鈕樣式過於古老,不做美化的話開發出來的軟件跟Windows98上的軟件一樣,所以有必要對MFC的CButton類進行擴展生繪。
先說下思路,要改CButton的外觀的話只要對DrawItem虛函數進行重寫就可以了。通過itemState可以判斷出按鈕的狀態,比如焦點、禁用、默認等等,鼠標進入和移出需要自己響應MouseMove消息。
具體實現代碼:
MyButton.h:
#pragma once
#include "afxwin.h"
class CMyButton : public CButton
{
//DECLARE_DYNAMIC(CMyButton)
private:
bool _isCustom;
COLORREF upBorderColor,downBorderColor,focusBorderColor,hoverBorderColor,diableBorderColor; //定義彈起、銨下、焦點、鼠標進入、禁用的邊框顏色
COLORREF disableBgColor;//定義禁用的背景顏色
int hoverBgColorR0,hoverBgColorG0,hoverBgColorB0,hoverBgColorR1,hoverBgColorG1,hoverBgColorB1;//分別定義鼠標進入的上邊RGB和下邊RGB顏色(實現漸變)
int upBgColorR0,upBgColorG0,upBgColorB0,upBgColorR1,upBgColorG1,upBgColorB1;
int downBgColorR0,downBgColorG0,downBgColorB0,downBgColorR1,downBgColorG1,downBgColorB1;//同上,鼠標銨下顏色
public:
CMyButton();
virtual ~CMyButton();
void SetDownColor(COLORREF color); //設置Button Down的背景顏色
void SetUpColor(COLORREF color);//設置彈起顏色
void SetFont(CFont* font);//設置字體
void SetFontColor(COLORREF color);//設置字體顏色
CWnd* cWndParent;
BOOL Attach(int nID, CWnd* pParent);//根據資源ID創建自定義按鈕
protected:
//必需重載的函數
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);//重案繪制函數
public:
WNDPROC OldWndProc;
CtoolTipCtrl m_Mytip;
BOOL m_bTracking;
LRESULT CALLBACK WindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
//三種顏色分別為文字,Button Down的背景顏色,Button Up的背景顏色
COLORREF m_TextColor, m_DownColor, m_UpColor,m_TempColor;
protected:
// Generated message map functions
//{{AFX_MSG(CMyButton)
//}}AFX_MSG
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);//鼠標離開事件
afx_msg LRESULT OnMouseHover(WPARAM wParam, LPARAM lParam);//鼠標進入事件
DECLARE_MESSAGE_MAP()
};
MyButton.cpp:
#include "StdAfx.h"
#include "MyButton.h"
BEGIN_MESSAGE_MAP(CMyButton, CButton)
//{{AFX_MSG_MAP(CMyButton)
ON_WM_MOUSEMOVE()
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)//鼠標離開
ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)//鼠標懸掛
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CMyButton::CMyButton(void)
{
m_TempColor=m_TextColor=m_DownColor = m_UpColor = RGB(0,0,0);
m_Mytip.Create(this);
m_bTracking=false;
_isCustom=false;
upBorderColor=RGB(172,172,172);
upBgColorR0=upBgColorG0=upBgColorB0=240;
upBgColorR1=upBgColorG1=upBgColorB1=229;
hoverBorderColor=RGB(126,180,234);
hoverBgColorR0=236;
hoverBgColorG0=244;
hoverBgColorB0=252;
hoverBgColorR1=220;
hoverBgColorG1=236;
hoverBgColorB1=252;
downBorderColor=RGB(86,157,229);
downBgColorR0=218;
downBgColorG0=232;
downBgColorB0=252;
downBgColorR1=196;
downBgColorG1=224;
downBgColorB1=252;
focusBorderColor=RGB(51,153,255);
diableBorderColor=RGB(217,217,217);
disableBgColor=RGB(239,239,239);
}
CMyButton::~CMyButton(void){
}
BOOL CMyButton::Attach(int nID, CWnd* pParent){
cWndParent=pParent->GetDlgItem(nID);
cWndParent->ModifyStyle(0,BS_OWNERDRAW,0);
if (!SubclassDlgItem(nID, pParent))
return FALSE;
return TRUE;
}
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){
// TODO: Add your code to draw the specified item
CDC dc;
dc.Attach(lpDrawItemStruct->hDC);//得到繪制的設備環境CDC
VERIFY(lpDrawItemStruct->CtlType==ODT_BUTTON);
const int bufSize = 512;
TCHAR buffer[bufSize];
GetWindowText(buffer, bufSize);//獲取按鈕上的文字
int size=strlen(buffer); //得到文字長度
SetBkMode(lpDrawItemStruct->hDC,TRANSPARENT); //設置背景透明
if (lpDrawItemStruct->itemState &ODS_SELECTED){ //當按下按鈕時的處理
CRect rect;
GetClientRect(&rect);//獲取按鈕區域
for(int i=0;i<rect.Height();i++){//處理漸變,如果是垂直方向則rect.Height(),下同
int r,g,b;
r = downBgColorR0 + (i * (downBgColorR1-downBgColorR0) / rect.Height());
g = downBgColorG0 + (i * (downBgColorG1-downBgColorG0) / rect.Height());
b = downBgColorB0 + (i * (downBgColorB1-downBgColorB0) / rect.Height());
dc.FillSolidRect(0,i,rect.Width(),1,RGB(r,g,b));//填充一條直線
}
DrawText(lpDrawItemStruct->hDC,buffer,size,&lpDrawItemStruct->rcItem,DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_TABSTOP);//繪制文字
SetBkMode(lpDrawItemStruct->hDC,TRANSPARENT);//設置背景透明
CBrush brush1(downBorderColor);//邊框顏色
dc.SetTextColor(RGB(0,0,0));//設置文字顏色
dc.FrameRect(&(lpDrawItemStruct->rcItem),&brush1);//
}
else if(lpDrawItemStruct->itemState &ODS_FOCUS||lpDrawItemStruct->itemState &ODS_CHECKED){//獲得焦點處理,同上
CRect rect;
GetClientRect(&rect);
for(int i=0;i<rect.Height();i++){ //如果是垂直方向則rect.Height(),下同
int r,g,b;
r = upBgColorR0 + (i * (upBgColorR1-upBgColorR0) / rect.Height());
g = upBgColorG0 + (i * (upBgColorG1-upBgColorG0) / rect.Height());
b = upBgColorB0 + (i * (upBgColorB1-upBgColorB0) / rect.Height());
dc.FillSolidRect(0,i,rect.Width(),1,RGB(r,g,b)););
} DrawText(lpDrawItemStruct->hDC,buffer,size,&lpDrawItemStruct->rcItem,DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_TABSTOP);
DrawFocusRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem);
SetBkMode(lpDrawItemStruct->hDC,TRANSPARENT);
CBrush brush1(focusBorderColor);//邊框顏色
dc.SetTextColor(RGB(0,0,0));//設置文字顏色
dc.FrameRect(&lpDrawItemStruct->rcItem,&brush1);//
}
else if(lpDrawItemStruct->itemState &ODS_DISABLED){//禁用處理,同上
CBrush brush(disableBgColor);//背景顏色
dc.FillRect(&(lpDrawItemStruct->rcItem),&brush);
dc.SetTextColor(RGB(131,131,131));//設置文字顏色
DrawText(lpDrawItemStruct->hDC,buffer,size,&lpDrawItemStruct->rcItem,DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_TABSTOP);
DrawFocusRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem);
SetBkMode(lpDrawItemStruct->hDC,TRANSPARENT);
CBrush brush1(diableBorderColor);//邊框顏色
dc.FrameRect(&lpDrawItemStruct->rcItem,&brush1);//
}
else{//當按鈕不操作或者彈起處理
CRect rect;
GetClientRect(&rect);
for(int i=0;i<rect.Height();i++){ //如果是垂直方向則rect.Height(),下同
int r,g,b;
r = upBgColorR0 + (i * (upBgColorR1-upBgColorR0) / rect.Height());
g = upBgColorG0 + (i * (upBgColorG1-upBgColorG0) / rect.Height());
b = upBgColorB0 + (i * (upBgColorB1-upBgColorB0) / rect.Height());
dc.FillSolidRect(0,i,rect.Width(),1,RGB(r,g,b));
}
DrawText(lpDrawItemStruct->hDC,buffer,size,&lpDrawItemStruct->rcItem,DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_TABSTOP);
SetBkMode(lpDrawItemStruct->hDC,TRANSPARENT);
CBrush brush1(upBorderColor);//邊框顏色
dc.SetTextColor(RGB(0,0,0));//設置文字顏色
dc.FrameRect(&lpDrawItemStruct->rcItem,&brush1);//
}
dc.Detach();
}
void CMyButton::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_bTracking)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 10;
m_bTracking = _TrackMouseEvent(&tme);
}
}
LRESULT CMyButton::OnMouseLeave(WPARAM wParam, LPARAM lParam){
m_bTracking=false;
if(!_isCustom){
upBorderColor=RGB(172,172,172);;
upBgColorR0=upBgColorG0=upBgColorB0=240;
upBgColorR1=upBgColorG1=upBgColorB1=229;
}
else{
m_UpColor=m_TempColor;
//m_TextColor=RGB(255,255,0);
}
Invalidate(); //重繪按鈕
return 0;
}
LRESULT CMyButton::OnMouseHover(WPARAM wParam, LPARAM lParam){
if(!_isCustom){
upBorderColor=hoverBorderColor;
// upBgColor=hoverBgColor;
upBgColorR0=hoverBgColorR0;
upBgColorG0=hoverBgColorG0;
upBgColorB0=hoverBgColorB0;
upBgColorR1=hoverBgColorR1;
upBgColorG1=hoverBgColorG1;
upBgColorB1=hoverBgColorB1;
}
else{
//m_TextColor=RGB(255,0,255);
m_UpColor=m_DownColor;
}
Invalidate(); //重繪按鈕
return 0;
}
使用:
在窗體的頭文件中添加引用:
#include "MyButton.h"
並創建CmyButton對象:
CMyButton myBtnSubmit;
在窗體的OnInitDialog()事件中添加如下代碼
myBtnSubmit.Attach(btnSubmit,this);
最終效果圖:

