分享

如何设置自定义按钮的样式

 菱静 2012-02-16
MFC编程中系统提供的一些样式,一般都比较难看,所以有的时候为了美观,需要自己定义些样式,现那Button按钮来举例.
首先新建一名为XPButton的MFC Application的对话框应用程序,在Class View中新增加一个自定义样式的MFC Class类,类名为CNewButton,基类为CButton.
NewButton.h的代码如下:
class CNewButton : public CButton
{    public:
          CNewButton();
protected:
          CPen m_BoundryPen; //按钮的外边框
//鼠标指针置于按钮之上时按钮的内边框
          CPen m_InsideBoundryPenLeft;
          CPen m_InsideBoundryPenRight;
          CPen m_InsideBoundryPenTop;
          CPen m_InsideBoundryPenBottom;
          //按钮获得焦点时按钮的内边框
          CPen m_InsideBoundryPenLeftSel;
          CPen m_InsideBoundryPenRightSel;
          CPen m_InsideBoundryPenTopSel;
          CPen m_InsideBoundryPenBottomSel;
          //按钮的底色,包括有效和无效两种状态
          CBrush m_FillActive;
          CBrush m_FillInactive;
          //按钮的状态
          BOOL m_bOver//鼠标位于按钮之上时该值为true,反之为flase
          BOOL m_bTracking//在鼠标按下没有释放时该值为true
          BOOL m_bSelected//按钮被按下是该值为true
          BOOL m_bFocus;     //按钮为当前焦点所在时该值为true
public:
protected:
     virtual voidPreSubclassWindow();
     public:
     virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
     virtual void DoGradientFill(CDC *pDC, CRect* rect);
     virtual void DrawInsideBorder(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
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_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(CNewButtonCButton)
     ON_WM_MOUSEMOVE()
     ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
     ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
END_MESSAGE_MAP()
 
//添加Owner Draw属性
void CNewButton::PreSubclassWindow()
{
     CButton::PreSubclassWindow();
     ModifyStyle(0, BS_OWNERDRAW);
}
void CNewButton::OnMouseMove(UINT nFlagsCPoint point)
{
if (!m_bTracking)
     {
         TRACKMOUSEEVENT tme;
         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(NULLFALSE);
     return 0;
}
LRESULT CNewButton::OnMouseHover(WPARAM wParam, LPARAM lParam)
{
     m_bOver = TRUE;
     InvalidateRect(NULL);
     return 0;
}
void CNewButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
     //从lpDrawItemStruct获取控件的相关信息
     CRect rect = lpDrawItemStruct->rcItem;
     CDC *pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
     int nSaveDC=pDC->SaveDC();
     UINT state = lpDrawItemStruct->itemState;
     POINT pt ;
     TCHAR strText[MAX_PATH + 1];
     ::GetWindowText(m_hWndstrTextMAX_PATH);
 
     //画按钮的外边框,它是一个半径为5的圆角矩形
     pt.x =5;
     pt.y =5;
     CPenhOldPen = pDC->SelectObject(&m_BoundryPen);
     pDC->RoundRect(&rectpt);
     //获取按钮的状态
     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)));
     //根据按钮的状态填充按钮的底色
     CBrushpOldBrush;
     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)
     {
         CFonthFont = GetFont();
         CFonthOldFont = pDC->SelectObject(hFont);
         CSize szExtent = pDC->GetTextExtent(strTextlstrlen(strText));
     CPoint ptrect.CenterPoint().x - szExtent.cx / 2, rect.CenterPoint().y - szExtent.cy / 2);
         if (state & ODS_SELECTED)
              pt.Offset(1, 1);
         int nMode = pDC->SetBkMode(TRANSPARENT);
         if (state & ODS_DISABLED)
              pDC->DrawState(ptszExtentstrTextDSS_DISABLEDTRUE, 0, (HBRUSH)NULL);
         else
              pDC->DrawState(ptszExtentstrTextDSS_NORMALTRUE, 0, (HBRUSH)NULL);
         pDC->SelectObject(hOldFont);
         pDC->SetBkMode(nMode);
     }
     pDC->RestoreDC(nSaveDC);
}
//绘制按钮的底色
void CNewButton::DoGradientFill(CDC *pDCCRectrect)
{
     CBrush brBk[64];
     int nWidth = rect->Width();
     int nHeight = rect->Height();
     CRect rct;
     for (int i = 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->topi <= nHeight + 2; i ++)
     {
         rct.SetRect(rect->leftinWidth + 2, i + 1);
         pDC->FillRect(&rct, &brBk[((i * 63) / nHeight)]);
     }
     for (i = 0; i < 64; i ++)
         brBk[i].DeleteObject();
}
//绘制按钮的内边框
void CNewButton::DrawInsideBorder(CDC *pDCCRectrect)
{
     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;
     }
     CPoint oldPoint = pDC->MoveTo(rect->leftrect->bottom - 1);
     CPenpOldPen = pDC->SelectObject(pLeft);
     pDC->LineTo(rect->leftrect->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->leftrect->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.编译运行,就可以看到自己定义的按钮.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多