当前位置:文档之家› High-speed Charting Control--MFC绘制图表(折线图、饼图、柱形图)控件

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

High-speed Charting Control--MFC绘制图表(折线图、饼图、柱形图)控件介绍对于我之前的一个项目,我需要在图表控件上显示连续的数据流。

我决定开发自己的控件,因为我找不到任何可以提供所需灵活性的自由软件控件。

其中一个主要的限制是,控件必须绘制大量的数据,并能够迅速显示它(在Pocket PC上)。

控件能够通过仅绘制新的数据点而不是完整的数据序列来做到这一点并且图表还能够显示静态数据。

这种控件是我长时间工作的结果,而且费尽周折地为了提供足够的灵活性来供需要它的人使用。

对于使用者反馈我表示由衷的感谢:一个邮件,留言板中的一一句话或只是对本文评级。

当我不知道是否还有人使用它时,我就没有必要维护这个控件了。

免责声明这个控件是我花费很长时间的开发的结果,因此我对代码的使用放置一些小条件:该代码可以以编译的形式用于任何非商业和商业目的。

代码可以被重新开发,只要它提供作者名字和完整的免责声明。

更改源代码需要得到作者的同意。

此代码不提供任何安全保证。

我不会对使用此代码造成的损失负责。

使用它需要自己承担风险。

This code may be used for any non-commercialand commercial purposes in a compiled form.The code may be redistributed as long 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.鉴于开发这个控件所付出的努力,下面的要求并不过分:如果你在在商业应用程序中使用这个控件,那么请给我发邮件让我知道。

主要特点控件的主要特点是:高速绘图(轴固定时),允许快速绘制数据无限数量的数据序列(内存是限制)每个数据序列的数据量不受限制支持线图,点图,平面图,柱状图,K线图和甘特图系列最多四个轴(左,下,右和上轴)标准轴,对数轴或日期/时间轴自动伸缩的坐标轴, 翻转的坐标轴(相互独立)轴标签点标签平滑的曲线网格图例和标题交互性(在控件中发生特定事件时的通知)支持手动缩放和鼠标平移支持鼠标指针支持轴上的滚动条高度可定制(颜色,标题,标签,边缘,字体等)支持UNICODE支持打印和保存到图像文件文档结构本文通过一系列简短的教程来涵盖控件的大部分功能。

阅读本文后,您将能够快速地在自己的应用程序中使用本控件。

我决定从文章中删除所有的类和函数的文档,因为它不是非常友好并且我很难维护。

此外,随着代码的增长,要记录的类和函数的列表变得过于广泛以至于不能将所有内容放在文章中。

作为替代,我提供了一个doxygen文档,您可以从本文中(文章的开头)下载:只需下载“Doxygen文档”zip文件,解压所有文件,双击“Index.html”文件,进行查看。

入门学习此图表控件允许您在屏幕上绘制一系列数据。

此控件可以添加几个不同类型数据序列并且最多可以使用四个轴。

添加到图表的数据序列与一个水平轴(底部或顶部)和一个垂直轴(右侧或左侧)相关联。

这两个轴控制数据序列在图表上的显示方式。

为了能够在应用程序中使用次图表控件,您首先需要在自己的工程里添加源代码zip中包含的文件。

注意:控件在内部使用动态转型,因此必须启用RTTI(RunTime Type Information 运行时自动类型识别的机制),否则可能会发生崩溃。

默认情况下,VC6没有启用RTTI,因此要启用它打开项目设置- >“C / C ++”选项卡- >“C ++语言”类别,并确保“Enable Run-Time Type Information (RTTI) “选项已选中。

在应用程序中使用图表控件有两种方法:手动插入,或通过资源编辑器插入。

手动插入1.#include "ChartCtrl"添加在对话框(Dialog)类的头文件中2.在对话框类中添加变量CChartCtrl://{{AFX_DATA(CChartDemoDlg)//}}AFX_DATACChartCtrl m_ChartCtrl;3.在对话框类的OnInitDialog方法中添加这个控件的Create方法。

使用资源管理器1.向对话框资源添加自定义控件,打开控件的属性,并为Class属性指定ChartCtrl。

为了避免滚动条上的闪烁,必须设置WS_CLIPCHILDREN样式(0x02000000L),如图所示。

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操作数据序列几种类型的数据序列可以添加到控制:点序列,线序列,曲面序列,柱状图序列,K 线图序列或甘特图序列。

点的数据格式可能因序列而异(例如,K线图和甘特图系列使用不同的点格式)。

一旦你选择了一种系列,你可以通过调用上表中列出的CChartCtrl类的辅助函数之一将其添加到图表中。

这些函数接受两个可选参数:两个布尔值来确定描述该系列是连接到副水平轴(顶轴)或者是连接大副垂直轴(右轴)。

如果未指定参数,则数据系列将附加到主水平轴(底部轴)和主垂直轴(左轴)。

警告: 在将任何系列添加到图表之前,您需要创建该系列所连接的两个轴。

如果不这样做,将导致控件失效(assert)。

有关详细信息,请参见“操纵轴”一节。

一旦将系列添加到图表后,我们就可以使用数据填充该图表。

有两种方法:将数据放到一个单元中一起添加,或者逐点添加。

后者用于有动态数据时:每次调用函数时都会更新图表。

虽然这个调用是快速的(在某些特定条件下),但是最好尽可能地将数据放到一个单元中。

下面是一个简单代码示例,它在图表中创建两个系列,并用数据填充它们:一个系列在初始化时完全填充,另一个系列在调用OnDataReceived函数(仅存在于此示例的目的)时填充。

m_pLineSeries,m_pPointsSeries和m_ChartCtrl是CMyClass类的成员变量。

void CMyClass::Init(){.... // SNIP: Creation of the axes in the chart. This MUST be done before.m_pLineSeries = m_ChartCtrl.CreateLineSerie();m_pPointsSeries = m_ChartCtrl.CreatePointsSerie();double YValues[10];for (inti=0;i<10;i++)XValues[i] = YValues[i] = i;m_pLineSerie->SetPoints(XValues,YValues,10);}void CMyClass::OnDataReceived(double X, double Y){m_pPointsSeries->AddPoint(X, Y);}所有系列类继承自同一抽象基类:CChartSerie。

该类处理所有系列通用的功能,但对具体的数据点没有任何处理功能。

点的概念在子类CChartSerieBase中引入,它是一个模板类,模板参数是要操作为点的数据类型。

这很重要,因为序列可能必须处理不同的数据类型:例如点序列操作具有X和Y值的点,但是K线图系列操纵具有5个值(打开,关闭,高,低和时间值)的点。

其他系列继承自CChartSerieBase并提供他们操作的数据类型。

CChartSerieBase类已经处理了大多数数据管理,并通过纯虚函数将渲染委托给子类。

每个系列在创建时也会分配一个Id。

此标识可通过CChartSerie :: GetSerieId()检索,并可用于从图表中删除该系列。

该系列的一个重要特征是控制点的顺序:该系列中的所有点将根据它们的值重新排序。

默认情况下,点是基于它们的X值排序的,但您可以通过对它们的Y值排序或不对它们进行排序来改变这种行为(在这种情况下,系列保持将点添加到系列中的顺序)。

对点进行排序会对性能产生影响:如果点是有序的,则控件能够从完整系列中检索第一个和最后一个可见点,并且仅绘制两个点之间的点。

另一方面,你将不能绘制像椭圆形的曲线。

您可以通过调用CChartSerieBase :: SetSeriesOrdering来更改点的顺序。

控件中的不同系列的功能通常是不言自明的。

然而,柱状图系列需要一些解释。

柱状图系列这个系列有点特别,如果其中几个在同一个控件上绘制在一起,他们将互相影响。

目的是能够绘制多个条形图系列,而不会重叠:它们是彼此相邻绘制的。

为此,您需要指定每个所属的组(一个简单的整数标识符)。

同一组的系列彼此相邻地绘制(或者对于水平条在彼此的顶部):参见两个图形的示例。

设置组ID是通过SetGroupId函数完成的。

您还可以通过调用SetInterSpace静态函数来控制所有柱形图之间剩余的空间的宽度。

这将为所有系列设置以像素为单位的空间(因此,如果显示多于两个系列,则在任何位置使用相同的空间)。

注意,您可以通过调用SetBarWidth单独设置柱状图系列的宽度。

在点上添加标签一旦使用数据填充您的系列,您还可以在系列的特定点上添加标签:这个标签始终附加到特定点。

现在,只提供一种类型的标签,气泡标签:包含文本的圆角矩形并用线连接到特定点上。

当然,如果需要,您也可以提供自己的自定义标签(参见“扩展功能”一节)。

有两种方式创建文本标签:静态创建标签时,或动态注册一个对象,当标签请求时,它将提供文本。

第一种方法是最简单的,但也不太灵活。

相关主题