自定义XP按钮(2)

#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 window

class 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

/////////////////////////////////////////////////////////////////////////////
// CXPButton

CXPButton::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);
}


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);
}

#ifndef _BTNST_H #define _BTNST_H // Uncomment the following line to enable support for sound effects #define BTNST_USE_SOUND #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 // Return values #ifndef BTNST_OK #define BTNST_OK 0 #endif #ifndef BTNST_INVALIDRESOURCE #define BTNST_INVALIDRESOURCE 1 #endif #ifndef BTNST_FAILEDMASK #define BTNST_FAILEDMASK 2 #endif #ifndef BTNST_INVALIDINDEX #define BTNST_INVALIDINDEX 3 #endif #ifndef BTNST_INVALIDALIGN #define BTNST_INVALIDALIGN 4 #endif #ifndef BTNST_BADPARAM #define BTNST_BADPARAM 5 #endif #ifndef BTNST_INVALIDPRESSEDSTYLE #define BTNST_INVALIDPRESSEDSTYLE 6 #endif // Dummy identifier for grayscale icon #ifndef BTNST_AUTO_GRAY #define BTNST_AUTO_GRAY (HICON)(0xffffffff - 1L) #endif class CXPButton : public CButton { public: CXPButton(); ~CXPButton(); enum { ST_ALIGN_HORIZ = 0, // Icon/bitmap on the left, text on the right ST_ALIGN_VERT, // Icon/bitmap on the top, text on the bottom ST_ALIGN_HORIZ_RIGHT, // Icon/bitmap on the right, text on the left ST_ALIGN_OVERLAP // Icon/bitmap on the same space as text }; enum { BTNST_COLOR_BK_IN = 0, // Background color when mouse is INside BTNST_COLOR_FG_IN, // Text color when mouse is INside BTNST_COLOR_BK_OUT, // Background color when mouse is OUTside BTNST_COLOR_FG_OUT, // Text color when mouse is OUTside BTNST_COLOR_BK_FOCUS, // Background color when the button is focused BTNST_COLOR_FG_FOCUS, // Text color when the button is focused BTNST_MAX_COLORS }; enum { BTNST_PRESSED_LEFTRIGHT = 0, // Pressed style from left to right (as usual) BTNST_PRESSED_TOPBOTTOM // Pressed style from top to bottom }; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CXPButton) public: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); virtual BOOL PreTranslateMessage(MSG* pMsg); protected: virtual void PreSubclassWindow(); //}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值