zoukankan      html  css  js  c++  java
  • ChartCtrl源码剖析之——CChartScrollBar类

    CChartScrollBar类用来针对每个轴的数据进行滚动,将那些不在当前区域内的数据通过滚动展示出来。

    CChartScrollBar类的头文件。

    #pragma once
    class CChartAxis;
    class CChartScrollBar : public CScrollBar
    {
    public:
        CChartScrollBar(CChartAxis* pParentAxis);
        ~CChartScrollBar();
        void CreateScrollBar(const CRect& PlottingRect);
        void OnHScroll(UINT nSBCode, UINT nPos);
        void OnVScroll(UINT nSBCode, UINT nPos);
        void Refresh();
        void SetEnabled(bool bEnabled)  { m_bEnabled = bEnabled; }
        bool GetEnabled() const            { return m_bEnabled; }
        void SetAutoHide(bool bAutoHide)  { m_bAutoHide = bAutoHide; }
        bool GetAutoHide() const          { return m_bAutoHide; }
        void OnMouseEnter();
        void OnMouseLeave();
    private:
        bool IsScrollInverted() const;
        void MoveAxisToPos(int PreviousPos, int CurPos);
        CChartAxis* m_pParentAxis;
        bool m_bEnabled;
        bool m_bAutoHide;
    };

    CChartScrollBar类的源文件。

    #include "stdafx.h"
    #include "ChartScrollBar.h"
    #include "ChartAxis.h"
    #include "ChartCtrl.h"
    #include "math.h"
    CChartScrollBar::CChartScrollBar(CChartAxis* pParentAxis)
    : CScrollBar(), m_pParentAxis(pParentAxis), m_bEnabled(false),
       m_bAutoHide(true)
    {
    }
    CChartScrollBar::~CChartScrollBar()
    {
    }
    void CChartScrollBar::CreateScrollBar(const CRect& PlottingRect)
    {
        CRect Temp = PlottingRect;
        Temp.top++; Temp.left++;
        DWORD dwStyle = SBS_HORZ | WS_CHILD;
        if (m_pParentAxis->IsHorizontal())
        {
            if (m_pParentAxis->m_bIsSecondary)
                dwStyle |= SBS_TOPALIGN;
            else
                dwStyle += SBS_BOTTOMALIGN;
        }
        else
        {
            if (m_pParentAxis->m_bIsSecondary)
                dwStyle |= SBS_VERT | SBS_RIGHTALIGN;
            else
                dwStyle += SBS_VERT | SBS_LEFTALIGN;
        }
        CScrollBar::Create(dwStyle, Temp, m_pParentAxis->m_pParent,100);
        SCROLLINFO info;
        info.cbSize = sizeof(SCROLLINFO);    
        info.fMask = SIF_ALL;     
        info.nMin = 1;     
        info.nMax = 1;
        info.nPage = 1;
        info.nPos = 1;   
        CScrollBar::SetScrollInfo(&info);
    }
    bool CChartScrollBar::IsScrollInverted() const
    {
        bool bInverted = false;
        if (m_pParentAxis->IsInverted() && m_pParentAxis->m_bIsHorizontal)
            bInverted = true;
        if (!m_pParentAxis->IsInverted() && !m_pParentAxis->m_bIsHorizontal)
            bInverted = true;
        return bInverted;
    }
    void CChartScrollBar::Refresh()
    {
        double AxisMin=0, AxisMax=0;
        double SeriesMin=0, SeriesMax=0;
        m_pParentAxis->GetMinMax(AxisMin,AxisMax);
        m_pParentAxis->GetSeriesMinMax(SeriesMin,SeriesMax);
        double dStep = 0;
        int iTotalSteps = 0;
        int iCurrentStep = 0;
        if (m_pParentAxis->IsLogarithmic())
        {
            // TODO: do something if the series has 0 in it
            dStep = pow(AxisMax/AxisMin,0.1);
            iTotalSteps = (int)ceil(log(SeriesMax/SeriesMin)/log(dStep));
            iCurrentStep = (int)(log(AxisMin/SeriesMin)/log(dStep));
        }
        else
        {
            dStep = (AxisMax - AxisMin) / 10.0;
            iTotalSteps = (int)ceil((SeriesMax - SeriesMin)/dStep);
            iCurrentStep = (int)(iTotalSteps * ((AxisMin - SeriesMin)/(SeriesMax-SeriesMin)));
        }
        SCROLLINFO info;
        info.cbSize = sizeof(SCROLLINFO);    
        info.fMask = SIF_ALL;     
        if ( (AxisMax-AxisMin) == 0 || (SeriesMax-SeriesMin)==0 )
        {
            info.nMin = 1;     
            info.nMax = 1;
            info.nPage = 1;
            info.nPos = 1;   
        }
        else
        {
            info.nMin = 1;     
            info.nMax = iTotalSteps;
            info.nPage = 10;
            info.nPos = iCurrentStep;   
            if (IsScrollInverted())
                info.nPos = iTotalSteps - 9 - iCurrentStep;
            else
                info.nPos = iCurrentStep;   
        }
        CScrollBar::SetScrollInfo(&info);
    }
    void CChartScrollBar::OnHScroll(UINT nSBCode, UINT nPos)
    {
        int MinPos;
        int MaxPos;
        int PreviousPos = CScrollBar::GetScrollPos();
        CScrollBar::GetScrollRange(&MinPos, &MaxPos);
        int CurPos = PreviousPos;
        bool bUpdate = true;
        switch (nSBCode)
        {
        case SB_LEFT:      
            CurPos = 0;
            break;
        case SB_RIGHT:      
            CurPos = MaxPos;
            break;
        case SB_ENDSCROLL:  
            bUpdate = false;
            break;
        case SB_LINELEFT:  
            if (CurPos > MinPos)
                CurPos--;
            break;
        case SB_LINERIGHT:   
            if (CurPos < MaxPos-9)
                CurPos++;
            break;
        case SB_PAGELEFT:    
            if (CurPos > MinPos)
                CurPos = max(MinPos, CurPos - 10);
            break;
        case SB_PAGERIGHT:     
            if (CurPos < MaxPos-9)
                CurPos = min(MaxPos, CurPos + 10);
            break;
        case SB_THUMBPOSITION:
                CurPos = nPos;
            break;
        case SB_THUMBTRACK:   
                CurPos = nPos;
            break;
        }
        if (bUpdate)
        {
            // Set the new position of the thumb (scroll box).
            CScrollBar::SetScrollPos(CurPos);
            MoveAxisToPos(PreviousPos,CurPos);
        }
    }
    void CChartScrollBar::OnVScroll(UINT nSBCode, UINT nPos)
    {
        int MinPos;
        int MaxPos;
        int PreviousPos = CScrollBar::GetScrollPos();
        CScrollBar::GetScrollRange(&MinPos, &MaxPos);
        int CurPos = PreviousPos;
        bool bUpdate = true;
        switch (nSBCode)
        {
        case SB_BOTTOM:      
            CurPos = MaxPos;
            break;
        case SB_TOP:      
            CurPos = 0;
            break;
        case SB_ENDSCROLL:   
            bUpdate = false;
            break;
        case SB_LINEDOWN:  
            if (CurPos < MaxPos-9)
                CurPos++;
            break;
        case SB_LINEUP:   
            if (CurPos > MinPos)
                CurPos--;
            break;
        case SB_PAGEUP:    
            if (CurPos > MinPos)
                CurPos = max(MinPos, CurPos - 10);
            break;
        case SB_PAGEDOWN:     
            if (CurPos < MaxPos-9)
                CurPos = min(MaxPos, CurPos + 10);
            break;
        case SB_THUMBPOSITION:
            CurPos = nPos;
            break;
        case SB_THUMBTRACK:   
            CurPos = nPos;
            break;
        }
        if (bUpdate)
        {
            // Set the new position of the thumb (scroll box).
            CScrollBar::SetScrollPos(CurPos);
            MoveAxisToPos(PreviousPos,CurPos);
        }
    }
    void CChartScrollBar::MoveAxisToPos(int PreviousPos, int CurPos)
    {
        double AxisMin=0, AxisMax=0;
        double SeriesMin=0, SeriesMax=0;
        m_pParentAxis->GetMinMax(AxisMin,AxisMax);
        m_pParentAxis->GetSeriesMinMax(SeriesMin,SeriesMax);
        if (m_pParentAxis->IsLogarithmic())
        {
            double dStep = pow(AxisMax/AxisMin,0.1);
            double dFactor = pow(dStep,(CurPos - PreviousPos));
            if (IsScrollInverted())
                m_pParentAxis->SetZoomMinMax(AxisMin/dFactor,AxisMax/dFactor);
            else
                m_pParentAxis->SetZoomMinMax(AxisMin*dFactor,AxisMax*dFactor);
        }
        else
        {
            double dStep = (AxisMax - AxisMin) / 10.0;
            double dOffset = (CurPos - PreviousPos) * dStep;
            if (IsScrollInverted())
                m_pParentAxis->SetZoomMinMax(AxisMin-dOffset,AxisMax-dOffset);
            else
                m_pParentAxis->SetZoomMinMax(AxisMin+dOffset,AxisMax+dOffset);
        }
    }
    void CChartScrollBar::OnMouseEnter()
    {
        if (m_bEnabled && m_bAutoHide)
            ShowWindow(SW_SHOW);
    }
    void CChartScrollBar::OnMouseLeave()
    {
        if (m_bEnabled && m_bAutoHide)
            ShowWindow(SW_HIDE);
    }
    这份源码一开始读的时候在info.nPage产生了理解偏差,再一次读的时候又在这个地方纠结了很久,现在把这个参数的意义再捋一遍,它的英文解释如下:
    nPage 
    Specifies the page size. A scroll bar uses this value to determine the appropriate size of the proportional scroll box. 
    该值表示页尺寸,同时表示比例滚动框的大小。将这个理解清楚之后,后面OnHScroll函数和OnVScroll函数里面的加减10与加减9就相对比较好理解。
    作者:常想一二
    出处:http://www.cnblogs.com/wolfmvp/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    如果文中有什么错误,欢迎指出。以免更多的人被误导。
  • 相关阅读:
    【线程间通信:代码示例:分析问题原因:修正代码】
    【死锁问题】
    【解决线程安全问题:通过Lock锁对象】
    【解决线程安全问题:同步方法】
    【解决线程安全问题:同步代码块】
    【线程实现的两种方式及区别】
    小阳的贝壳
    小石的妹子
    SPFA模板+dfs版检测负环
    逆序对模板
  • 原文地址:https://www.cnblogs.com/wolfmvp/p/7218667.html
Copyright © 2011-2022 走看看