zoukankan      html  css  js  c++  java
  • CXPButton类(VC按钮自绘)

    发表时间:2007-7-3 17:11:00

    XPButton.h
    ===================================================
    #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
    ===============================================================
    // 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, #000000);
     m_InsideBoundryPenLeft.CreatePen(PS_INSIDEFRAME | PS_SOLID, 3, #fac458);
     m_InsideBoundryPenRight.CreatePen(PS_INSIDEFRAME | PS_SOLID, 3, #fbca6a);
     m_InsideBoundryPenTop.CreatePen(PS_INSIDEFRAME | PS_SOLID, 2, #fcd279);
     m_InsideBoundryPenBottom.CreatePen(PS_INSIDEFRAME | PS_SOLID, 2, #e59700);
     
     m_FillActive.CreateSolidBrush(#dfdeec);
     m_FillInactive.CreateSolidBrush(#dedfec);
     
     m_InsideBoundryPenLeftSel.CreatePen(PS_INSIDEFRAME | PS_SOLID, 3, #99c6fc);
     m_InsideBoundryPenTopSel.CreatePen(PS_INSIDEFRAME | PS_SOLID, 2, #a2c9ff);
     m_InsideBoundryPenRightSel.CreatePen(PS_INSIDEFRAME | PS_SOLID, 3, #a2bdfc);
     m_InsideBoundryPenBottomSel.CreatePen(PS_INSIDEFRAME | PS_SOLID, 2, #a2c9ff);
     
     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)));
     //rect.DeflateRect(1, 1);
     
     //根据按钮的状态填充按钮的底色
     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 (int i = rect->top; i <= nHeight + 2; i ++)
     {
      rct.SetRect(rect->left, i, nWidth + 2, i + 1);
      pDC->FillRect(&rct, &brBk[((i * 63) / nHeight)]);
     }
     
     for (int 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);
    }

  • 相关阅读:
    sqlserver数据库的备份与还原——完整备份与还原
    sqlserver中为节约存储空间的收缩数据库机制
    sqlserver数据库的分离与附加
    sqlserver的数据库状态——脱机与联机
    sqlserver打开对象资源管理器管理的帮助文档的快捷键
    sqlserver使用SQL语句创建数据库登录对象、数据库用户以及对为该用户赋予操作权限
    sqlserver window身份验证时切换账户的快捷键
    向现有数据库中添加文件组和数据文件
    使用SQL语句创建数据库2——创建多个数据库文件和多个日志文件
    Java中怎样判断一个字符串是否是数字?
  • 原文地址:https://www.cnblogs.com/yuanxiaoping_21cn_com/p/1446271.html
Copyright © 2011-2022 走看看