在evc中怎样实现圆角矩形按钮?

解决方案 »

  1.   

    下面是画xp按钮的代码,当然也是圆角的
    #if !defined(AFX_XPBUTTON_H__44CD5B2A_756E_4939_9261_E0034E0F2DEF__INCLUDED_)
    #define AFX_XPBUTTON_H__44CD5B2A_756E_4939_9261_E0034E0F2DEF__INCLUDED_#if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // XPButton.h : header file
    ///////////////////////////////////////////////////////////////////////////////
    // CXPButton windowclass CXPButton : public CButton
    {
    // Construction
    public:
    CXPButton(); // Attributes
    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// Operations
    public:// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CXPButton)
    protected:
    virtual void PreSubclassWindow();
    //}}AFX_VIRTUAL// Implementation
    public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    virtual void DoGradientFill(CDC *pDC, CRect* rect);
    virtual void DrawInsideBorder(CDC *pDC, CRect* rect);
    virtual ~CXPButton(); // Generated message map functions
    protected:
    //{{AFX_MSG(CXPButton)
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
    afx_msg LRESULT OnMouseHover(WPARAM wParam, LPARAM lParam);

    //}}AFX_MSG DECLARE_MESSAGE_MAP()
    };///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_XPBUTTON_H__44CD5B2A_756E_4939_9261_E0034E0F2DEF__INCLUDED_)
    // XPButton.cpp : implementation file
    //#include "stdafx.h"
    #include "XPButton.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif/////////////////////////////////////////////////////////////////////////////
    // CXPButtonCXPButton::CXPButton()
    {
    m_BoundryPen.CreatePen(PS_INSIDEFRAME | PS_SOLID, 1, RGB(0, 0, 0));
    m_InsideBoundryPenLeft.CreatePen(PS_INSIDEFRAME | PS_SOLID, 3, RGB(250, 196, 88)); 
    m_InsideBoundryPenRight.CreatePen(PS_INSIDEFRAME | PS_SOLID, 3, RGB(251, 202, 106));
    m_InsideBoundryPenTop.CreatePen(PS_INSIDEFRAME | PS_SOLID, 2, RGB(252, 210, 121));
    m_InsideBoundryPenBottom.CreatePen(PS_INSIDEFRAME | PS_SOLID, 2, RGB(229, 151, 0));

    m_FillActive.CreateSolidBrush(RGB(223, 222, 236));
    m_FillInactive.CreateSolidBrush(RGB(222, 223, 236));

    m_InsideBoundryPenLeftSel.CreatePen(PS_INSIDEFRAME | PS_SOLID, 3, RGB(153, 198, 252)); 
    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;

    }CXPButton::~CXPButton()
    {
    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(CXPButton, CButton)
    //{{AFX_MSG_MAP(CXPButton)
    ON_WM_MOUSEMOVE()
    ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
    ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
    // CXPButton message handlers//添加Owner Draw属性
    void CXPButton::PreSubclassWindow() 
    {
    // TODO: Add your specialized code here and/or call the base class

    CButton::PreSubclassWindow();
    ModifyStyle(0, BS_OWNERDRAW);
    }void CXPButton::OnMouseMove(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
    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);
    }
      

  2.   

    LRESULT CXPButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)
    {
    m_bOver = FALSE;
    m_bTracking = FALSE;
    InvalidateRect(NULL, FALSE);
    return 0;
    }LRESULT CXPButton::OnMouseHover(WPARAM wParam, LPARAM lParam)
    {
    m_bOver = TRUE;
    InvalidateRect(NULL);
    return 0;
    }
    void CXPButton::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_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);
    CSize szExtent = pDC->GetTextExtent(strText, lstrlen(strText));
    CPoint pt( rect.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(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);
    }//绘制按钮的底色
    void CXPButton::DoGradientFill(CDC *pDC, CRect* rect)
    {
    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->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();
    }
    //绘制按钮的内边框
    void CXPButton::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;
    }

    CPoint oldPoint = 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);
    }