收藏 分享(赏)

High-speed Charting Control--MFC绘制图表(折线图、饼图、柱形图)控件.doc

上传人:精品资料 文档编号:8995636 上传时间:2019-07-19 格式:DOC 页数:24 大小:774KB
下载 相关 举报
High-speed Charting Control--MFC绘制图表(折线图、饼图、柱形图)控件.doc_第1页
第1页 / 共24页
High-speed Charting Control--MFC绘制图表(折线图、饼图、柱形图)控件.doc_第2页
第2页 / 共24页
High-speed Charting Control--MFC绘制图表(折线图、饼图、柱形图)控件.doc_第3页
第3页 / 共24页
High-speed Charting Control--MFC绘制图表(折线图、饼图、柱形图)控件.doc_第4页
第4页 / 共24页
High-speed Charting Control--MFC绘制图表(折线图、饼图、柱形图)控件.doc_第5页
第5页 / 共24页
点击查看更多>>
资源描述

1、High-speed Charting Control-MFC 绘制图表(折线图、饼图、柱形图)控件介绍对于我之前的一个项目,我需要在图表控件上显示连续的数据流。 我决定开发自己的控件,因为我找不到任何可以提供所需灵活性的自由软件控件。 其中一个主要的限制是,控件必须绘制大量的数据,并能够迅速显示它(在 Pocket PC 上) 。 控件能够通过仅绘制新的数据点而不是完整的数据序列来做到这一点并且图表还能够显示静态数据。 这种控件是我长时间工作的结果,而且费尽周折地为了提供足够的灵活性来供需要它的人使用。 对于使用者反馈我表示由衷的感谢:一个邮件,留言板中的一一句话或只是对本文评级。 当我不知

2、道是否还有人使用它时,我就没有必要维护这个控件了。免责声明这个控件是我花费很长时间的开发的结果,因此我对代码的使用放置一些小条件:该代码可以以编译的形式用于任何非商业和商业目的。代码可以被重新开发,只要它提供作者名字和完整的免责声明。 更改源代码需要得到作者的同意。此代码不提供任何安全保证。 我不会对使用此代码造成的损失负责。 使用它需要自己承担风险。This code may be used for any non-commercialand commercial purposes in a compiled form.The code may be redistributed as lon

3、g as it remainsunmodified and providing that the author nameand the disclaimer remain intact. The sourcescan be modified with the author consent only.This code is provided without any guarantees.I cannot be held responsible for the damage orthe loss of time it causes. Use it at your own risks.鉴于开发这个

4、控件所付出的努力,下面的要求并不过分: 如果你在在商业应用程序中使用这个控件,那么请给我发邮件让我知道。主要特点控件的主要特点是:高速绘图(轴固定时) ,允许快速绘制数据无限数量的数据序列(内存是限制)每个数据序列的数据量不受限制支持线图,点图,平面图,柱状图,K 线图 和甘特图系列最多四个轴(左,下,右和上轴)标准轴,对数轴或日期/时间轴自动伸缩的坐标轴, 翻转的坐标轴(相互独立)轴标签点标签平滑的曲线网格图例和标题交互性(在控件中发生特定事件时的通知)支持手动缩放和鼠标平移支持鼠标指针支持轴上的滚动条高度可定制(颜色,标题,标签,边缘,字体等)支持 UNICODE支持打印和保存到图像文件文

5、档结构本文通过一系列简短的教程来涵盖控件的大部分功能。 阅读本文后,您将能够快速地在自己的应用程序中使用本控件。我决定从文章中删除所有的类和函数的文档,因为它不是非常友好并且我很难维护。 此外,随着代码的增长,要记录的类和函数的列表变得过于广泛以至于不能将所有内容放在文章中。 作为替代,我提供了一个 doxygen 文档,您可以从本文中(文章的开头)下载:只需下载“Doxygen 文档”zip 文件,解压所有文件,双击“ Index.html”文件,进行查看。入门学习此图表控件允许您在屏幕上绘制一系列数据。 此控件可以添加几个不同类型数据序列并且最多可以使用四个轴。 添加到图表的数据序列与一个

6、水平轴(底部或顶部)和一个垂直轴(右侧或左侧)相关联。 这两个轴控制数据序列在图表上的显示方式。 为了能够在应用程序中使用次图表控件,您首先需要在自己的工程里添加源代码 zip 中包含的文件。注意:控件在内部使用动态转型,因此必须启用 RTTI(RunTime Type Information 运行时自动类型识别的机制) ,否则可能会发生崩溃。 默认情况下,VC6 没有启用 RTTI,因此要启用它打开项目设置 - “C / C +”选项卡 - “C +语言”类别,并确保“Enable Run-Time Type Information (RTTI) “选项已选中。在应用程序中使用图表控件有两种

7、方法:手动插入,或通过资源编辑器插入。手动插入1.#include “ChartCtrl“添加在对话框(Dialog )类的头文件中 2.在对话框类中添加变量 CChartCtrl:/AFX_DATA(CChartDemoDlg)/AFX_DATACChartCtrl m_ChartCtrl;3.在对话框类的 OnInitDialog 方法中添加这个控件的 Create 方法。使用资源管理器1.向对话框资源添加自定义控件,打开控件的属性,并为 Class 属性指定 ChartCtrl。 为了避免滚动条上的闪烁,必须设置 WS_CLIPCHILDREN 样式(0x02000000L) ,如图所示

8、。2.#include “ChartCtrl.h“添加在对话框(Dialog )类的头文件中 3.在对话框类中添加变量 CChartCtrl:/AFX_DATA(CChartDemoDlg)/AFX_DATACChartCtrl m_ChartCtrl;4.在 DoDataExchange 函数中添加 DDX_Control(不要忘了更改 ID 号和控件名字):Add a variable of type CChartCtrl in your dialog class: Hide Copy Code/AFX_DATA(CChartDemoDlg)/AFX_DATA操作数据序列几种类型的数据序列

9、可以添加到控制:点序列,线序列,曲面序列,柱状图序列,K线图序列或甘特图序列。 点的数据格式可能因序列而异(例如,K 线图和甘特图系列使用不同的点格式) 。一旦你选择了一种系列,你可以通过调用上表中列出的 CChartCtrl 类的辅助函数之一将其添加到图表中。 这些函数接受两个可选参数:两个布尔值来确定描述该系列是连接到副水平轴(顶轴)或者是连接大副垂直轴(右轴) 。 如果未指定参数,则数据系列将附加到主水平轴(底部轴)和主垂直轴(左轴) 。警告: 在将任何系列添加到图表之前,您需要创建该系列所连接的两个轴。 如果不这样做,将导致控件失效(assert) 。 有关详细信息,请参见 “操纵轴”

10、一节。一旦将系列添加到图表后,我们就可以使用数据填充该图表。 有两种方法:将数据放到一个单元中一起添加,或者逐点添加。 后者用于有动态数据时:每次调用函数时都会更新图表。 虽然这个调用是快速的(在某些特定条件下) ,但是最好尽可能地将数据放到一个单元中。 下面是一个简单代码示例,它在图表中创建两个系列,并用数据填充它们:一个系列在初始化时完全填充,另一个系列在调用 OnDataReceived 函数(仅存在于此示例的目的)时填充。 m_pLineSeries,m_pPointsSeries 和 m_ChartCtrl 是 CMyClass 类的成员变量。void CMyClass:Init()

11、/ SNIP: Creation of the axes in the chart. This MUST be done before.m_pLineSeries = m_ChartCtrl.CreateLineSerie();m_pPointsSeries = m_ChartCtrl.CreatePointsSerie();double YValues10;for (inti=0;iSetPoints(XValues,YValues,10);void CMyClass:OnDataReceived(double X, double Y)m_pPointsSeries-AddPoint(X,

12、Y);所有系列类继承自同一抽象基类:CChartSerie。该类处理所有系列通用的功能,但对具体的数据点没有任何处理功能。点的概念在子类 CChartSerieBase 中引入,它是一个模板类,模板参数是要操作为点的数据类型。这很重要,因为序列可能必须处理不同的数据类型:例如点序列操作具有 X 和 Y 值的点,但是 K 线图系列操纵具有 5 个值(打开,关闭,高,低和时间值)的点。其他系列继承自 CChartSerieBase 并提供他们操作的数据类型。 CChartSerieBase 类已经处理了大多数数据管理,并通过纯虚函数将渲染委托给子类。每个系列在创建时也会分配一个 Id。此标识可通过

13、 CChartSerie : GetSerieId()检索,并可用于从图表中删除该系列。该系列的一个重要特征是控制点的顺序:该系列中的所有点将根据它们的值重新排序。默认情况下,点是基于它们的 X 值排序的,但您可以通过对它们的 Y 值排序或不对它们进行排序来改变这种行为(在这种情况下,系列保持将点添加到系列中的顺序 ) 。 对点进行排序会对性能产生影响:如果点是有序的,则控件能够从完整系列中检索第一个和最后一个可见点,并且仅绘制两个点之间的点。 另一方面,你将不能绘制像椭圆形的曲线。 您可以通过调用 CChartSerieBase : SetSeriesOrdering 来更改点的顺序。控件中

14、的不同系列的功能通常是不言自明的。 然而,柱状图系列需要一些解释。柱状图系列这个系列有点特别,如果其中几个在同一个控件上绘制在一起,他们将互相影响。 目的是能够绘制多个条形图系列,而不会重叠:它们是彼此相邻绘制的。 为此,您需要指定每个所属的组(一个简单的整数标识符) 。 同一组的系列彼此相邻地绘制(或者对于水平条在彼此的顶部):参见两个图形的示例。 设置组 ID 是通过 SetGroupId 函数完成的。您还可以通过调用 SetInterSpace 静态函数来控制所有柱形图之间剩余的空间的宽度。 这将为所有系列设置以像素为单位的空间(因此,如果显示多于两个系列,则在任何位置使用相同的空间)

15、。 注意,您可以通过调用 SetBarWidth 单独设置柱状图系列的宽度。在点上添加标签一旦使用数据填充您的系列,您还可以在系列的特定点上添加标签:这个标签始终附加到特定点。 现在,只提供一种类型的标签,气泡标签:包含文本的圆角矩形并用线连接到特定点上。 当然,如果需要,您也可以提供自己的自定义标签(参见“扩展功能”一节)。 有两种方式创建文本标签:静态创建标签时,或动态注册一个对象,当标签请求时,它将提供文本。 第一种方法是最简单的,但也不太灵活。 下面是一个代码片段,显示如何做(假设 m_pSeries 已经创建并填充足够的数据):void CMyClass:Init()/ SNIP.m

16、_pSeries-CreateBalloonLabel(5,_T(“This is a simple label“);此调用将创建一个带有“This is a simple label”文本的标签,并将其附加到带索引为5 的点。该函数返回一个指向新创建的标签的指针,以便您可以修改其某些属性或存储以供以后使用。第二种方法有点复杂,但提供了更多的灵活性:例如,您可以以更方便的方式在标签中显示点属性(例如 X 值, Y 值,) 。 为此,您必须创建一个继承自CChartLabelProvider 的类,并在创建标签时提供此类的实例。 此类是模板类,模板参数是标签附加到的系列的点类型。 这个类是一个简

17、单的接口,你必须覆盖TChartString GetText(CChartSerieBase * pSerie,unsigned uPtIndex)方法。 此函数应返回必须在标签中显示的文本。 它接收指向标签所附加的系列和点索引的指针。 这里有一个这样的标签提供程序类的例子:class CCustomLabelProvider : public CChartLabelProviderpublic:TChartString GetText(CChartSerieBase* pSeries, unsigned uPtIndex)TChartStringStream ssText;SChartXYP

18、oint Point = pSeries-GetPoint(uPtIndex);ssText CreateBalloonLabel(5, m_pLabelProvider);控件不获取指针的所有权,因此,当你不再需要时,你有责任删除它。 在上面的例子中,它通常会在 CMyClass 析构函数中被删除。 在上面的示例中,您可以为所有要添加的标签地方重复使用相同的标签类, 这也带来另一个优点:如果你想在运行时改变标签的格式,你只需要在 CustomLabelProvider 中添加代码。 不需要遍历所有现有标签并更改其文本。 当然,在这种情况下,需要刷新控件,因为必须重新绘制标签。 还要注意TCh

19、artStringStream 类的用法, TChartStringStream 类是由控件提供的别名(类似于TChartString) 。 当 UNICODE 被定义时,它解析为 std : wstringstream,当未定义UNICODE 时,解析为 std : stringstream。对轴的操作轴是图表的一个重要特征,因为它们控制不同系列在控制中的显示方式。 控件中最多可使用四个轴:底部,顶部,左侧和右侧。 控件的每个系列必须和一个水平轴和一个垂直轴相连接。 在图表中添加系列时指定这些轴。 底部和左侧轴是主轴,顶部和右侧轴是辅助轴(您将在控件的某些功能中遇到此问题) 。 现在有三种类

20、型的轴供选择:标准轴,对数轴和日期/时间轴。 您可以在不同位置选用不同类型的轴。一旦您选择了在不同位置使用哪些轴,您需要先创建它们,然后才能向控件添加任何数据。 为此,通过指定轴附加在哪个位置,简单地调用CreateStandardAxis,CreateLogarithmicAxis 或 CreateDateTimeAxis。 如果已经在该位置创建了轴,则控件将销毁它并且用新的轴替换它。 这里有一个简单的代码片段,显示如何在底部创建日期/时间,在左侧创建一个标准轴:void CMyClass:Init()CChartStandardAxis* pBottomAxis =m_ChartCtrl.

21、CreateStandardAxis(CChartCtrl:BottomAxis);CChartLogarithmicAxis* pLeftAxis =m_ChartCtrl.CreateLogarithmicAxis(CChartCtrl:LeftAxis);一旦创建了这些轴,就可以对它们设置一些属性。 大多数属性在所有轴类型之间共享(例如自动模式,最小值和最大值,轴标签,) 。 轴可以设置为三种“自动”模式:全自动,屏幕自动和手动模式。全自动模式基于附加到该轴的所有系列计算轴最小值和最大值(所有系列的所有点的最小值用作轴的最小值,并使用所有系列的所有点的最大值 作为轴的最大值) 。屏幕自动

22、模式基于与该轴相关的所有系列的所有可见点计算轴最小值和最大值。 例如,如果图表仅显示连接到手动底部轴和屏幕自动左侧轴的一个系列,则左侧轴将自适应于当前可见的点,并且不考虑这些点有可能超过底轴的范围(在全自动模式下,底轴外部的点将被考虑) 。 警告:如果系列的两个轴都处于屏幕自动模式,则结果未定义。在手动模式下,轴最小和最大值由用户设置,不由控件计算。在使用自动轴模式下,如果将数据动态添加到控件,如果新的数据点位于轴的范围之外,那么控件将自动刷新。 这里是一个代码片段(继续前一个代码段) ,显示一个全自动轴(底部轴)和一个手动轴(左轴,它是一个对数轴):void CMyClass:Init()/

23、 SNIP .pBottomAxis-SetAutomaticMode(CChartAxis:FullAutomatic);/ The call to SetAutomaticMode(CChartAxis:NotAutomatic) is not/ really needed because this is the default.pLeftAxis-SetAutomaticMode(CChartAxis:NotAutomatic);pLeftAxis-SetMinMax(0.01,1000);处于离散模式下的轴轴有一个模式是离散模式(默认禁用 )。此模式指定轴不显示连续值,而只显示离散值,

24、这些值是轴上刻度指定的值,而轴将不显示其他的值。尝试绘制不同于显示的节拍值的值是不可能的。让我们举一个例子:假设你有一个底部标准轴,间隔为 1.0(所以,显示的蜱是 1,2,3 等等) 。尝试绘制 X 值为 0.5 的点将在相同位置显示该点,就好像它的值为1.0。事实上,你可以认为两个刻度之间的区域是一个常量值。这就是为什么刻度标签显示在两个刻度的中间,而不是刻度本身。这里有一个小代码片段,显示离散轴对系列显示方式的影响。代码片段下的两个图像显示启用离散模式(第一个图像)或禁用(第二个图像)的结果。void CMyClass:Init()CChartStandardAxis* pBottomA

25、xis =m_ChartCtrl.CreateStandardAxis(CChartCtrl:BottomAxis);pBottomAxis-SetMinMax(0, 10);CChartStandardAxis* pLeftAxis =m_ChartCtrl.CreateStandardAxis(CChartCtrl:LeftAxis);pLeftAxis-SetMinMax(0, 10);pBottomAxis-SetTickIncrement(false, 1.0);pBottomAxis-SetDiscrete(true);CChartLineSerie* pSeries = m_Ch

26、artCtrl.CreateLineSerie();double XVal20;double YVal20;for (int i=0; iSetPoints(XVal,YVal,20);使用日期/时间轴使用日期/时间轴有点特别,下面是如何利用这个功能的解释。要了解日期/ 时间轴的重要一点是它们在 COleDateTime 对象内部工作。原因很简单:COleDateTime 中有 DATE类型的类,DATE 类型是一个双精度型。由于图表中的点表示为双精度值,因此它非常适合:使用标准点(非日期/时间)和日期 /时间点之间没有差异,这使得后者的使用不太复杂。所有点仍然存储为双精度型,无论是否是日期/

27、时间。创建日期/时间轴后,可以在控件中填充数据。为此目的,没有改变:你必须从CChartSerie 类调用 void AddPoint(double X,double Y)或 void SetPoints(double * X,double * Y,int Count) 。 CChartCtrl 类提供了两个静态函数,让你从 COleDateTime 转换为双精度,反之亦然:double DateToValue(const COleDateTimeCOleDateTime maxValue(2007,12,31,0,0,0);pBottomAxis-SetMinMax(CChartCtrl:D

28、ateToValue(minValue),CChartCtrl:DateToValue(maxValue);/ Sets the tick increment to 4 months (disable automatic tick increment)pBottomAxis-SetTickIncrement(false, CChartDateTimeAxis:tiMonth, 4);/ Sets the tick label format for instance “Jan 2006“pBottomAxis-SetTickLabelFormat(false, _T(“%b %Y“);自定义外观

29、控件的外观方面可以根据不同的应用场景做出更改,比如控件的不同部分(图例,标题,背景,)都可以修改。 所有与这些对象的交互是通过 CChartCtrl 类来实现:一些将根据需要创建(例如 axes 或 series) ,一些在创建控件时创建(legend,titles ,) 。 一般来说,你永远不会自己创建这些对象,而是将该任务委派给 CChartCtrl 类。 唯一的例外是当您要使用自定义轴或自定义系列(请参阅“扩展功能”部分) 。 例如,下面是一个代码段,设置渐变背景,并将图例放在控件的底部:void CMyClass:Init()/ SNIP/ Disable the refresh of

30、 the controlm_ChartCtrl.EnableRefresh(false);/ Set the gradient for the backgroundm_ChartCtrl.SetBackGradient(RGB(255,255,255),RGB(125,125,255),gtVertical);/ Dock the legend at the bottomm_ChartCtrl.GetLegend()-DockLegend(CChartLegend:dsDockBottom);/ Specifies that the legend entries are horizontall

31、y stackedm_ChartCtrl.GetLegend()-SetHorizontalMode(true);/ Re-enable the refresh of the controlm_ChartCtrl.EnableRefresh(true);重要:从版本 1.4 的控件,每次调用控件上的一个属性将导致控件的完全刷新(即使像改变一些文本的字体或对象的颜色) 。 为了避免在没有必要时刷新控件(例如,当您同时更改多个属性时) ,应首先禁用刷新,更改属性,然后重新启用刷新,如上面的代码段所示 。自从 1.5 版的控件开始支持 UNICODE。 所有出现的 std : string 对象已被

32、TChartString 对象替换,这只是一个 typedef,如果未启用 UNICODE,则解析为 std : string,并在启用 UNICODE 时解析为 std : wstring。响应鼠标事件有时,应用程序需要响应用户鼠标操作。 例如,如果用户点击点,则程序可以显示关于被点击的点的信息,这一节将解释如何做到。虽然原理是有点不同,但是无论你想听在图表上的一般鼠标事件本身(点击轴,图例,)或你是否对特定系列的鼠标事件感兴趣。 这两种情况都很容易实现。响应图表上的鼠标事件你必须实现 CChartMouseListener 接口,覆盖你感兴趣的方法,并通过调用 CChartCtrl : R

33、egisterMouseListener(CChartMouseListener * pMouseListener)将该类的实例注册到图表控件。 根据鼠标事件发生在控件的哪个部分:标题,图例,轴或绘图区,调用该接口上的不同函数。 对于所有这些函数,总是传递两个参数:MouseEvent ,它是列出鼠标事件类型(鼠标移动,左键单击,)的枚举,以及一个 CPoint 对象,它包含的发生事件的点的屏幕坐标。 对于某些函数,需要时传递一些其他参数。 例如,当单击一个轴时,指向该轴的指针被传递给该函数。下面是 CChartMouseListener 的实现,它对轴的点击作出反应,并显示一个消息框:cla

34、ss CCustomMouseListener : public CChartMouseListenerpublic:void OnMouseEventAxis(MouseEvent mouseEvent, CPoint point,CChartAxis* pAxisClicked)if (mouseEvent = CChartMouseListener:LButtonDoubleClick)MessageBox(_T(“Axis clicked“), _T(“Info“), MB_OK);然后你必须创建一个这个类的实例并注册它:m_pMouseListener = new CCustomMo

35、useListener();m_ChartCtrl.RegisterMouseListener(m_pMouseListener);这里也需要自己删除指针。响应系列上的鼠标事件响应系列上的事件与响应一般事件非常相似,只是监听器是CChartSeriesMouseListener 的一个实例,它是一个模板类,模板参数是系列的点类型。 这是需要的,以避免当您要检索点的特定值时不必要的转型。 另一个区别是,您必须在系列本身上注册监听器,而不是在图表控件上注册。下面是 CChartSeriesMouseListener 的实现,它对系列的点击做出反应,如果点击发生在点上,它将显示一个带有点的 Y 值的

36、消息框:class CCustomMouseListener : public CChartSeriesMouseListenerpublic:void OnMouseEventSeries(MouseEvent mouseEvent, CPoint point,CChartSerieBase* pSerie, unsigned uPointIndex)if (mouseEvent = CChartMouseListener:LButtonDoubleClick SChartXYPoint Point = pSeries-GetPoint(uPointIndex);ssText Registe

37、rListener(pCursorListener);OnCursorMoved 函数接收一个 X 和 Y 值,但对于拖动光标,只使用这些值中的一个:如果光标与水平轴相关联,则使用 X 值,否则使用 Y 值。使用平移和缩放功能在版本 1.1 的控件中,缩放和平移功能已被添加到控件。 使用鼠标左键控制缩放,用鼠标右键控制平移。 要缩放图表的特定部分,只需左键单击图表(这将是缩放矩形的左上角) ,然后拖动到右下角。 将出现一个矩形。 一旦松开鼠标按钮,四个轴将自动调整到您选择的区域。 默认情况下启用缩放,但您可以通过调用 CChartCtrl : SetZoomEnabled(bool bEnab

38、led)来禁用缩放。 您还可以通过调用 CChartAxis : SetZoomLimit(double dLimit)为每个轴指定缩放限制。 它指定缩放时轴的最小范围。 默认值为 0.001。要平移控件,右键单击控件上的某处并移动鼠标。 鼠标下的点将“跟随”鼠标的移动(实际上,轴的最小和最大值将改变) 。 默认情况下启用平移,但您可以通过调用CChartCtrl : SetPanEnabled(bool bEnabled)来禁用它。如果您左键单击图表(例如开始缩放) ,但如果您移动到左上角,所有使用缩放和平移功能所做的修改将被取消(控制将处于它的状态 在使用平移和缩放操作之前) 。 最后,还

39、有一种方法通过调用 CChartAxis : SetPanZoomEnabled(bool bEnabled)禁用特定轴的平移和缩放功能。利用高速功能线和点系列允许以高速率绘制数据。 这通常在要绘制来自外部设备(例如,传感器)的数据时完成。 这是可能的,因为当您向此类系列添加点时,控件不会完全刷新,只会绘制最后一个点(或最后一个线段) ,这是非常有效的。 但是,如果希望控件能够足够快地绘制数据,则必须考虑几点。一个重要的事情是,使用自动轴可能会降低很多性能。这是因为如果一个点绘制在轴范围之外,则轴范围将被自动调整,这意味着控制将被完全刷新。因此,如果您使用自动底部轴线并具有“滚动”轨迹,则每个

40、新点都将位于轴的当前范围之外,并且将对每个点执行控制刷新。处理的更好的方法是使用固定轴并且每秒手动地增加轴的范围(或以合理的速率) 。另一个重要的点是,你不应该在向一个系列添加一个新点之后调用 RefreshCtrl。这当然会完全地刷新控件,但是应该避免这样做。最后,如果您需要同时应用几个修改或添加几个点到控件,您应该在 EnableRefresh(false )和 EnableRefresh(true)之间封装这些调用(请参阅“自定义外观”部分) 。扩展功能在某些特定情况下,您需要使用新功能扩展控件,例如新的系列类型。目前,您可以自定义四个组件:序列,轴,点标签和光标。要提供新轴,新标签或新

41、光标,您只需继承基类(CChartAxis,CChartLabel 或CChartCursor)并实现所需的虚拟函数。一旦完成,您可以通过调用不同函数的自定义版本(CChartCtrl : AttachCustomAxis,CChartCtrl : AttachCustomLabel 或 CChartCtrl : AttachCustomCursor)附加您的新对象。 CChartLabel 类是一个模板类。这个主题有点广泛,进入了很多细节,但最简单的方法是看看不同的现有类。如果你想提供新的系列,这有点不同:你首先要考虑你想要在你的系列中操纵的点的类型。如果你只需要使用 X 和 Y 值来操作点

42、,那么你可以继承 CChartXYSerie,它提供了很多功能来操作这些点。然后,您必须实现所需的虚拟函数。看看下面的系列:CChartLineSerie,CChartPointSerie ,CChartSurfaceSerie 和 CChartBarSerie 具体示例。如果你的系列操纵其他类型的点,那么你首先必须为点包含以下方法创建一个结构:double GetX(),double GetXMin(),double GetXMax(),double GetY(),double GetYMin()和double GetYMax()。一旦完成,您必须继承 CChartSerieBase 并将此

43、点作为模板参数。然后,您必须提供所需的虚拟功能。看看下面的系列具体例子:CChartCandlestickSerie 和CChartGanttSerie。Upgrading from Version 1.x to Version 2.0在版本 2.0 中,对控件进行重构,导致 API 的更改。 主要的可见变化是每个轴类型现在有其单独的类(CChartStandardAxis,CChartDateTimeAxis 和 CChartLogarithmicAxis) 。 这也意味着默认情况下没有创建轴,并且您必须在向图表添加系列之前自己创建轴(否则代码将断言) 。 这包括在“操纵轴”部分。另一个变化

44、是添加系列到图表的方式:AddSerie 已经在 CChartCtrl 类中删除,并已被帮助函数替代,以创建特定的系列类型(CreateLineSerie,CreatePointsSerie,) 。 这些函数返回确切的系列类型,因此不再需要铸造。 这在“操纵系列”一节中有详细描述。Upgrading from Version 2.x to Version 3.x版本 3.0.0 的主要变化是,系列基类现在已经作为模板类,模板参数是系列操作的点类型。如果您没有通过提供新的系列类型扩展控件,这将不会在您的代码中有所不同。如果你提供了一个新的系列类型,你的类必须继承 CCharSerieBase 并

45、提供它操作的点的类型。如果你的系列使用只有 X 和 Y 值的点,你可以简单地继承 CChartXYSerie。看看现有的系列更多的例子。另一个小的修改是标签提供程序现在也是模板类(出于同样的原因) 。并且监听系列中的鼠标事件现在从图表上的鼠标事件中分离出来。这两点在“在点上添加标签”部分和“鼠标事件通知”部分中有很好的解释。最后,CChartAxis : SetAutomatic 方法已被标记为已弃用,您应该使用 CChartAxis : SetAutomaticMode(已经引入了一个额外的自动模式) 。例子本节只是两个代码片段,显示了如何使用控件。 第一个片段再现了示波器示例的图像(参见本

46、文顶部) ,第二个示例再现了“2008 年收入”图像。 代码是文档化的,所以它不应该太难理解。Oscilloscope example:/ Disable the refresh of the control (avoid multiple refresh).m_ChartCtrl.EnableRefresh(false);/ Create a bottom and left axesCChartStandardAxis* pBottomAxis =m_ChartCtrl.CreateStandardAxis(CChartCtrl:BottomAxis);CChartStandardAxis*

47、 pLeftAxis =m_ChartCtrl.CreateStandardAxis(CChartCtrl:LeftAxis);/ Sets the min and max values of the bottom and left axis to -15 - 15pBottomAxis-SetMinMax(-15,15);pLeftAxis-SetMinMax(-15,15);/ Add a new series of type line to the control and add data to itCChartLineSerie* pLineSeries = m_ChartCtrl.C

48、reateLineSerie();/ Specifies that the points in the series are not ordered (needed to be able/ to draw an lipse).pLineSeries-SetSeriesOrdering(poNoOrdering);for (int i=0;iAddPoint(X,Y);/ Defines the different colors (back color, axes color, .)COLORREF BackColor = RGB(0,50,0);COLORREF GridColor = RGB

49、(0,180,0);COLORREF TextColor = RGB(0,180,0);COLORREF SerieColor = RGB(0,255,0);/ Specifies a sunken border for the controlm_ChartCtrl.SetEdgeType(EDGE_SUNKEN);/ Sets the color of the border and the back colorm_ChartCtrl.SetBorderColor(TextColor);m_ChartCtrl.SetBackColor(BackColor);/Sets the color of the different elements of the bottom axism_ChartCtrl.GetBottomAxis()-SetAxisColor(TextColor);m_ChartCtrl.GetBottomAxis()-SetTextColor(TextColor);m_Ch

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报