MFC编程中系统提供的一些样式,一般都比较难看,所以有的时候为了美观,需要自己定义些样式,现那Button按钮来举例.
首先新建一名为XPButton的MFC Application的对话框应用程序,在Class View中新增加一个自定义样式的MFC Class类,类名为CNewButton,基类为CButton.
NewButton.h的代码如下:
classCNewButton:publicCButton
{public:
CNewButton();
protected:
CPenm_BoundryPen;//按钮的外边框
//鼠标指针置于按钮之上时按钮的内边框
CPenm_InsideBoundryPenLeft;
CPenm_InsideBoundryPenRight;
CPenm_InsideBoundryPenTop;
CPenm_InsideBoundryPenBottom;
//按钮获得焦点时按钮的内边框
CPenm_InsideBoundryPenLeftSel;
CPenm_InsideBoundryPenRightSel;
CPenm_InsideBoundryPenTopSel;
CPenm_InsideBoundryPenBottomSel;
//按钮的底色,包括有效和无效两种状态
CBrushm_FillActive;
CBrushm_FillInactive;
//按钮的状态
BOOLm_bOver;//鼠标位于按钮之上时该值为true,反之为flase
BOOLm_bTracking;//在鼠标按下没有释放时该值为true
BOOLm_bSelected;//按钮被按下是该值为true
BOOLm_bFocus;//按钮为当前焦点所在时该值为true
public:
protected:
virtual voidPreSubclassWindow();
public:
virtualvoidDrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
virtualvoidDoGradientFill(CDC *pDC, CRect* rect);
virtualvoidDrawInsideBorder(CDC *pDC, CRect* rect);
virtual~CNewButton();
protected:
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()
};
NewButton.cpp的代码如下:
#include"stdafx.h"
#include"NewButton.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[] =__FILE__;
#endif
CNewButton::CNewButton()//构造函数
{
m_BoundryPen.CreatePen(PS_INSIDEFRAME|PS_SOLID, 1,RGB(0, 0, 0));//按钮的外边框画笔
m_InsideBoundryPenLeft.CreatePen(PS_INSIDEFRAME|PS_SOLID, 3,RGB(61, 97, 88));m_InsideBoundryPenRight.CreatePen(PS_INSIDEFRAME|PS_SOLID, 3,RGB(61, 137, 106));
m_InsideBoundryPenTop.CreatePen(PS_INSIDEFRAME|PS_SOLID, 2,RGB(102, 167, 114));m_InsideBoundryPenBottom.CreatePen(PS_INSIDEFRAME|PS_SOLID, 2,RGB(102, 167, 114));
//按钮的背景色
m_FillActive.CreateSolidBrush(RGB(223, 222, 236));
m_FillInactive.CreateSolidBrush(RGB(222, 223, 236));
m_InsideBoundryPenLeftSel.CreatePen(PS_INSIDEFRAME|PS_SOLID, 3,RGB(139, 189, 157));
m_InsideBoundryPenTopSel.CreatePen(PS_INSIDEFRAME|PS_SOLID, 2,RGB(162, 201, 255));
m_InsideBoundryPenRightSel.CreatePen(PS_INSIDEFRAME|PS_SOLID, 3,RGB(162, 189, 252));
m_InsideBoundryPenBottomSel.CreatePen(PS_INSIDEFRAME|PS_SOLID, 2,RGB(162, 201, 255));
m_bOver=m_bSelected=m_bTracking=m_bFocus=FALSE;
}
CNewButton::~CNewButton()
{
m_BoundryPen.DeleteObject();
m_InsideBoundryPenLeft.DeleteObject();
m_InsideBoundryPenRight.DeleteObject();
m_InsideBoundryPenTop.DeleteObject();
m_InsideBoundryPenBottom.DeleteObject();
m_FillActive.DeleteObject();
m_FillInactive.DeleteObject();
m_InsideBoundryPenLeftSel.DeleteObject();
m_InsideBoundryPenTopSel.DeleteObject();
m_InsideBoundryPenRightSel.DeleteObject();
m_InsideBoundryPenBottomSel.DeleteObject();
}
BEGIN_MESSAGE_MAP(CNewButton,CButton)
ON_WM_MOUSEMOVE()
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
END_MESSAGE_MAP()
//添加Owner Draw属性
voidCNewButton::PreSubclassWindow()
{
CButton::PreSubclassWindow();
ModifyStyle(0,BS_OWNERDRAW);
}
void CNewButton::OnMouseMove(UINTnFlags,CPointpoint)
{
if(!m_bTracking)
{
TRACKMOUSEEVENTtme;
tme.cbSize=sizeof(tme);
tme.hwndTrack=m_hWnd;
tme.dwFlags=TME_LEAVE|TME_HOVER;
tme.dwHoverTime= 1;
m_bTracking=_TrackMouseEvent(&tme);
}
CButton::OnMouseMove(nFlags, point);
}
LRESULT CNewButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
m_bOver=FALSE;
m_bTracking=FALSE;
InvalidateRect(NULL,FALSE);
return0;
}
LRESULT CNewButton::OnMouseHover(WPARAM wParam, LPARAM lParam)
{
m_bOver=TRUE;
InvalidateRect(NULL);
return0;
}
void CNewButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
//从lpDrawItemStruct获取控件的相关信息
CRectrect=lpDrawItemStruct->rcItem;
CDC*pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
intnSaveDC=pDC->SaveDC();
UINTstate=lpDrawItemStruct->itemState;
POINTpt;
TCHARstrText[MAX_PATH+ 1];
::GetWindowText(m_hWnd,strText,MAX_PATH);
//画按钮的外边框,它是一个半径为5的圆角矩形
pt.x=5;
pt.y=5;
CPen*hOldPen=pDC->SelectObject(&m_BoundryPen);
pDC->RoundRect(&rect,pt);
//获取按钮的状态
if(state&ODS_FOCUS)
{
m_bFocus=TRUE;m_bSelected=TRUE;
}
else
{
m_bFocus=FALSE;m_bSelected=FALSE;
}
if(state&ODS_SELECTED||state&ODS_DEFAULT)
{
m_bFocus=TRUE;
}
pDC->SelectObject(hOldPen);
rect.DeflateRect(CSize(GetSystemMetrics(SM_CXEDGE),GetSystemMetrics(SM_CYEDGE)));
//根据按钮的状态填充按钮的底色
CBrush*pOldBrush;
if(m_bOver)
{
pOldBrush=pDC->SelectObject(&m_FillActive);
DoGradientFill(pDC, &rect);
}
else
{
pOldBrush=pDC->SelectObject(&m_FillInactive);
DoGradientFill(pDC, &rect);
}
//根据按钮的状态绘制内边框
if(m_bOver||m_bSelected)
DrawInsideBorder(pDC, &rect);
pDC->SelectObject(pOldBrush);
//显示按钮的文本
if(strText!=NULL)
{
CFont*hFont=GetFont();
CFont*hOldFont=pDC->SelectObject(hFont);
CSizeszExtent=pDC->GetTextExtent(strText,lstrlen(strText));
CPointpt(rect.CenterPoint().x-szExtent.cx/ 2,rect.CenterPoint().y-szExtent.cy/ 2);
if(state&ODS_SELECTED)
pt.Offset(1, 1);
intnMode=pDC->SetBkMode(TRANSPARENT);
if(state&ODS_DISABLED)
pDC->DrawState(pt,szExtent,strText,DSS_DISABLED,TRUE, 0, (HBRUSH)NULL);
else
pDC->DrawState(pt,szExtent,strText,DSS_NORMAL,TRUE, 0, (HBRUSH)NULL);
pDC->SelectObject(hOldFont);
pDC->SetBkMode(nMode);
}
pDC->RestoreDC(nSaveDC);
}
//绘制按钮的底色
voidCNewButton::DoGradientFill(CDC*pDC,CRect*rect)
{
CBrushbrBk[64];
intnWidth=rect->Width();
intnHeight=rect->Height();
CRectrct;
for(inti= 0;i< 64;i++)
{
if(m_bOver)
{
if(m_bFocus)
brBk[i].CreateSolidBrush(RGB(255 - (i/ 4), 255 - (i/ 4), 255 - (i/ 3)));
else
brBk[i].CreateSolidBrush(RGB(255 - (i/ 4), 255 - (i/ 4), 255 - (i/ 5)));
}
else
{
if(m_bFocus)
brBk[i].CreateSolidBrush(RGB(255 - (i/ 3), 255 - (i/ 3), 255 - (i/ 4)));
else
brBk[i].CreateSolidBrush(RGB(255 - (i/ 3), 255 - (i/ 3), 255 - (i/ 5)));
}
}
for(i=rect->top;i<=nHeight+ 2;i++)
{
rct.SetRect(rect->left,i,nWidth+ 2,i+ 1);
pDC->FillRect(&rct, &brBk[((i* 63) /nHeight)]);
}
for(i= 0;i< 64;i++)
brBk[i].DeleteObject();
}
//绘制按钮的内边框
voidCNewButton::DrawInsideBorder(CDC*pDC,CRect*rect)
{
CPen*pLeft, *pRight, *pTop, *pBottom;
if(m_bSelected&& !m_bOver)
{
pLeft= &m_InsideBoundryPenLeftSel;
pRight= &m_InsideBoundryPenRightSel;
pTop= &m_InsideBoundryPenTopSel;
pBottom= &m_InsideBoundryPenBottomSel;
}
else
{
pLeft= &m_InsideBoundryPenLeft;
pRight= &m_InsideBoundryPenRight;
pTop= &m_InsideBoundryPenTop;
pBottom= &m_InsideBoundryPenBottom;
}
CPointoldPoint=pDC->MoveTo(rect->left,rect->bottom- 1);
CPen*pOldPen=pDC->SelectObject(pLeft);
pDC->LineTo(rect->left,rect->top+ 1);
pDC->SelectObject(pRight);
pDC->MoveTo(rect->right- 1,rect->bottom- 1);
pDC->LineTo(rect->right- 1,rect->top);
pDC->SelectObject(pTop);
pDC->MoveTo(rect->left- 1,rect->top);
pDC->LineTo(rect->right- 1,rect->top);
pDC->SelectObject(pBottom);
pDC->MoveTo(rect->left,rect->bottom);
pDC->LineTo(rect->right- 1,rect->bottom);
pDC->SelectObject(pOldPen);
pDC->MoveTo(oldPoint);
if(m_bSelected&& !m_bOver)
DrawFocusRect(pDC->m_hDC,rect);
}
3.设置某个按钮为上面所定义的样式,只需右键点击该按钮,添加变量,变量的类型CNewButton,变量名为m_Button.编译运行,就可以看到自己定义的按钮.