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/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 如果文中有什么错误,欢迎指出。以免更多的人被误导。 |