zoukankan      html  css  js  c++  java
  • 重写MFC的CSliderCtrl 控件

    需要的控件演示效果

    默认的光标是蓝色
    当鼠标悬浮在slider或者拖动的时候则是白色
    整个控件的显示效果具体如图1-1,描述了整个控件需要的UI效果

    1-1. Slider 演示效果

    实现原理

    MFC自带的CSliderCtrl控件UI个人觉得比较不美观,为了实现个性化的slider控件绘制,用户常常需要自己重写slider控件,其中也有很多种不同的写法,下面我就将自己的一种实现写出来,若是有不当的地方则请指出,我一定会好好修改。为了更清楚地知道重写需要重写哪些函数以及CSliderCtrl的一些接口,需要查看相关的MSDN文档,这是我自己当时重写的查看的官方文档链接,CSliderCtrl官方参考文档

    定义控件需要的颜色

    控件的颜色设置在控件演示效果中已经说明了,默认的光标是蓝色,其他时候则是灰白色,所以我会预先定义这两种颜色,分别是蓝色灰白色,具体的颜色定义如下所示:

    #define      G_BASE_CCCCCC				                    RGB(204,204,204)
    #define      G_BASE_0078D6				                    RGB(0, 120, 214)
    #define      TRACK_HOVERTHUMB_COLOR		                    G_BASE_CCCCCC
    #define      TRACK_DEGAULTTHUMB_COLOR	                    G_BASE_0078D6
    

    重写CSliderCtrl类

    为了实现自己定制的Slider控件效果,需要继承CSliderCtrl类,并且改写其中的几个方法,在这个类中我分别定义了2个笔刷和2个画笔对象,用于绘制图形时指定颜色。为了其中可以实现鼠标拖动和鼠标移开以及初始形状设置,我重写了OnPaintOnMouseMoveOnMouseLeave以及OnEraseBkgnd方法。具体的头文件定义如下:

    class MySlider: public CSliderCtrl
    {
        DECLARE_DYNCREATE(MySlider)
    public:
        MySlider();
        virtual ~MySlider();
        virtual void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult);
        
    protected:
        afx_msg void OnPaint();
        afx_msg void OnMouseMove(UINT nFlags, CPoint point);
        afx_msg void OnMouseLeave();
        afx_msg BOOL OnEraseBkgnd(CDC* pDC);
        DECLARE_MESSAGE_MAP()
        
    private:
        bool         m_bHoverThumb;
        CBrush     m_hoverBrush;
        Cpen        m_hoverPen;
        CBrush     m__defaultBrush;
        CPen        m_defaultPen;
    }
    

    上面是关于slider控件的实现定义,下面则是实现这些方法,代码不多,也很方便阅读^^。

    BEGIN_MESSAGE_MAP(MySlider, CSliderCtrl)
    ON_WM_PAINT()
    ON_WM_ERASEBKGND()
    ON_WM_MOUSEMOVE()
    ON_WM_MOUSELEAVE()
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
    END_MESSAGE_MAP()
    
    IMPLEMENT_DYNCREATE(MySlider, CSliderCtrl);
    
    MySlider::MySlider(): m_hoverBrush(TRACK_HOVERTHUMB_COLOR),m_hoverPen(PS_SOLID, 1,       TRACK_HOVERTHUMB_COLOR), m_defaultBrush(TRACK_DEGAULTTHUMB_COLOR), m_defaultPen(PS_SOLID, 1, TRACK_DEGAULTTHUMB_COLOR){
    m_bHoverThumb = FALSE;
    }
    
    MySlider::~MySlider(){}
    
    void MySlider::OnPaint()
    {
        CClientDC dc(this);
        CSliderCtrl::OnPaint();
        
        // 这里分别绘制thumb左边和右边,两边分开绘制
    
        CRect rect,rectaimL,rectaimR;
        GetChannelRect(&rect);
        rectaimL = rect;
        rectaimR = rect;
        GetThumbRect(&rect);
        rectaimL.top = rect.top;
        rectaimL.bottom = rect.bottom;
        rectaimL.right = rect.left;
        rectaimR.top = rect.top;
        rectaimR.bottom = rect.bottom;
        rectaimR.left = rect.right;
        CBrush brush(G_EDIT_OPT_BK);
        dc.FillRect(rectaimL,&brush);
        dc.FillRect(rectaimR,&brush);
    
        CBrush brushS(G_BASE_WHITE);
        int rectaimH = rect.Height()/3;
        rectaimL.top += rectaimH;
        rectaimL.bottom -= rectaimH;
        rectaimR.top += rectaimH;
        rectaimR.bottom -= rectaimH;
        dc.FillRect(rectaimL,&brushS);
        dc.FillRect(rectaimR,&brushS);
    }
    
    
    
    void MySlider::OnCustomDraw(NMHDR * pNMHDR, LRESULT *pResult)
    {
        NMCUSTOMDRAW nmcd = *(LPNMCUSTOMDRAW)pNMHDR;
        if ( nmcd.dwDrawStage == CDDS_PREPAINT )
        {
             // return CDRF_NOTIFYITEMDRAW so that we will get subsequent 
            // CDDS_ITEMPREPAINT notifications
            *pResult = CDRF_NOTIFYITEMDRAW ;
             return;
        }
       else if (nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
        {
            if ( nmcd.dwItemSpec == TBCD_THUMB )
            {
    		    *pResult = CDRF_DODEFAULT;
    		    CBrush* pBrush = NULL;
    		    CPen* pPen = NULL;
    		    switch(nmcd.uItemState)
    		    {
    		        case 0:
    			        if(m_bHoverThumb && IsWindowEnabled())
    			        {
    				        pBrush = &m_hoverBrush;
    				        pPen = &m_hoverPen;
    			        }
    			        else if(IsWindowEnabled())
    			        {
    				        pBrush = &m_defaultBrush;
    				        pPen = &m_defaultPen;
    			        }
    			       else 
    			        {
    				        pBrush = &m_hoverBrush;
    				        pPen = &m_hoverPen;
    			        }
    			    break;
    		        case CDIS_SELECTED:
    			            pBrush = &m_hoverBrush;
    			            pPen = &m_hoverPen;
    			            break;
    		        default:
    			            pBrush = &m_defaultBrush;
    			            pPen = &m_defaultPen;
    			            break;
    		  }
    				
    		    CDC *pdc = CDC::FromHandle(nmcd.hdc);
    		    CBrush * pOldBrush = pdc->SelectObject(pBrush);
    		    CPen* pOldPen = pdc->SelectObject(pPen);
    		    CRect rcThumb,rcChannel,rcPaint;
    		    GetThumbRect(&rcThumb);
    		    GetChannelRect(rcChannel);
    		    rcPaint = rcThumb;
    		    rcPaint.bottom = rcChannel.bottom + 1;
    		    pdc->Rectangle(rcPaint);
    		    pdc->BeginPath();
    		    pdc->MoveTo(rcPaint.right, rcPaint.bottom);
    		    pdc->LineTo(rcPaint.left, rcPaint.bottom);
    		    pdc->LineTo(rcPaint.CenterPoint().x, rcThumb.bottom - 1);
    		    pdc->LineTo(rcPaint.right, rcPaint.bottom);
    		    pdc->EndPath();
    		    pdc->FillPath();
    		    pdc->SelectObject(pOldBrush);
    		    pdc->SelectObject(pOldPen);
    		    *pResult = CDRF_SKIPDEFAULT;
            }
        } 
    }
    
    
    void MySlider::OnMouseMove(UINT nFlags, CPoint point)
    {
        CRect rc;
        GetThumbRect(&rc);
        if(rc.PtInRect(point))
    	    m_bHoverThumb = TRUE;
        else
    	    m_bHoverThumb = FALSE;
        CSliderCtrl::OnMouseMove(nFlags, point);
    }
    
    void MySlider::OnMouseLeave()
    {
        m_bHoverThumb = FALSE;
        CSliderCtrl::OnMouseLeave();
    }
    
    BOOL MySlider::OnEraseBkgnd(CDC* pDC)
    {
        CRect rect,rectaim;
        GetClientRect(&rect);
        rectaim =  rect;
    
        GetThumbRect(&rect);
        rectaim.top = rect.top;
        rectaim.bottom = rect.bottom;
        CBrush brush(G_EDIT_OPT_BK);
        pDC->FillRect(rectaim,&brush);
        return TRUE;
    }
    

    重绘结束

    到这里Slider重绘就结束了,自己重绘的控件的使用方法和CSliderCtrl控件使用方法是一样的,都需要注意setbuddy,不然会没法绑定数据,从而导致滑动thumb的时候没法改变其他数据;若是有描述不当的地方,请告诉我哦!

  • 相关阅读:
    jdbc连接2(不可以注入)
    大白dmeo (转的)
    管家婆系统
    RMQ求最值
    Codeforces 837E Vasya's Function 数论 找规律
    Codeforces 837D
    poj 1655 找树的重心
    HDU 4055 Number String 计数DP
    Summer training round2 #7 (Training #23)
    Summer training round2 #6 (Training #22)
  • 原文地址:https://www.cnblogs.com/zuixime0515/p/12166101.html
Copyright © 2011-2022 走看看