首先,做一些简单的铺垫,目前针对ChartCtrl源码的剖析只针对V.15版本。名义上说是剖析,倒不如说是记录下自己针对该控件的理解,非常感谢Cedric Moonen大神,一切的功劳与掌声都该赠予给他。Code Project项目地址:https://www.codeproject.com/Articles/14075/High-speed-Charting-Control。剖析以源码注释加额外说明为主,有记录不妥的地方,欢迎各路大神拍砖,交流与沟通是大家各自进步的基石。
先概览一下该源码的关键类之间的关系图,做到阅读源码的时候心中有数。

CChartObject类的头文件。
#if !defined(AFX_CHARTOBJECT_H__6ED024F2_00D9_45D5_AB83_258EF0075288__INCLUDED_) #define AFX_CHARTOBJECT_H__6ED024F2_00D9_45D5_AB83_258EF0075288__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include <afx.h> #include <afxwin.h> // CChartCtrl类的前置声明 class CChartCtrl; class CChartObject { friend CChartCtrl; public: CChartObject(CChartCtrl* pOwner); virtual ~CChartObject(); void SetVisible(bool bVisible); bool IsVisible() const { return m_bIsVisible; } COLORREF GetColor() const { return m_ObjectColor; } void SetColor(COLORREF NewColor); COLORREF GetShadowColor() const { return m_ShadowColor; } void SetShadowColor(COLORREF NewColor); void EnableShadow(bool bEnable); void SetShadowDepth(int Depth); bool Clip(int& dX, int& dY) const { bool bResult = true; if (dX>m_ObjectRect.right) { dX = m_ObjectRect.right; bResult = false; } if (dX<m_ObjectRect.left) { dX = m_ObjectRect.left; bResult = false; } if (dY>m_ObjectRect.bottom) { dY = m_ObjectRect.bottom; bResult = false; } if (dY<m_ObjectRect.top) { dY = m_ObjectRect.top; bResult = false; } return bResult; } protected: void SetRect(CRect NewTect) { m_ObjectRect = NewTect; } CRect m_ObjectRect; // Size of the object COLORREF m_ObjectColor; // Color of the objet CChartCtrl* m_pParent; // Owner of the object bool m_bIsVisible; bool m_bShadow; // Specifies if the object generate a shadow. // This is not supported for all objects. COLORREF m_ShadowColor; int m_iShadowDepth; private: virtual void Draw(CDC* pDC) = 0; }; #endif // !defined(AFX_CHARTOBJECT_H__6ED024F2_00D9_45D5_AB83_258EF0075288__INCLUDED_)
CChartObject类的源文件。
#include "stdafx.h" #include "ChartCtrl.h" CChartObject::CChartObject(CChartCtrl* pOwner) { m_ObjectRect.left = m_ObjectRect.right = 0; m_ObjectRect.top = m_ObjectRect.bottom = 0; m_ObjectColor = RGB(0,0,0); m_pParent = pOwner; m_bIsVisible = true; m_bShadow = false; m_ShadowColor = RGB(150,150,150); m_iShadowDepth = 2; } CChartObject::~CChartObject() { } void CChartObject::SetVisible(bool bVisible) { m_bIsVisible = bVisible; m_pParent->RefreshCtrl(); } void CChartObject::SetColor(COLORREF NewColor) { m_ObjectColor = NewColor; m_pParent->RefreshCtrl(); } void CChartObject::SetShadowColor(COLORREF NewColor) { m_ShadowColor = NewColor; m_pParent->RefreshCtrl(); } void CChartObject::EnableShadow(bool bEnable) { m_bShadow = bEnable; m_pParent->RefreshCtrl(); } void CChartObject::SetShadowDepth(int Depth) { m_iShadowDepth = Depth; m_pParent->RefreshCtrl(); }
在这份源码中没什么特别难懂且复杂的地方,简单说几个自己觉得值得记录的知识点。
- 头文件中的#if !defined(……) …… #endif是为了避免当前头文件被二次包含,起到类似功能的还有#ifndef …… #endif。
- _MSC_VER为Microsoft的C编译器版本,微软不同时期,编译器有不同的版本:
-
- Visual C++ 2005 MS VC++8.0 _MSC_VER = 1400
- Visual C++ 2008 MS VC++9.0 _MSC_VER = 1500
- Visual C++ 2010 MS VC++10.0 _MSC_VER = 1600
- 在程序中加入_MSC_VER宏可以根据编译器版本让不同版本的编译器选择性地编译一段程序。查看编译的版本信息,可以在开发工具对应的Command line里敲 cl /?
- Clip函数用来将函数参数中的位置约束在m_ObjectRect矩形空间内,当该位置在m_ObjectRect矩形空间的时候函数返回值为True;否则,返回False。