范围之外,则轴范围将被自动调整,这意味着控制将被完全刷新。因此,如果您使用自动底部轴线并具有“滚动”轨迹,则每个新点都将位于轴的当前范围之外,并且将对每个点执行控制刷新。处理的更好的方法是使用固定轴并且每秒手动地增加轴的范围(或以合理的速率)。
另一个重要的点是,你不应该在向一个系列添加一个新点之后调用RefreshCtrl。这当然会完全地刷新控件,但是应该避免这样做。最后,如果您需要同时应用几个修改或添加几个点到控件,您应该在EnableRefresh(false)和EnableRefresh(true)之间封装这些调用(请参阅“自定义外观”部分)。
扩展功能
在某些特定情况下,您需要使用新功能扩展控件,例如新的系列类型。目前,您可以自定义四个组件:序列,轴,点标签和光标。
要提供新轴,新标签或新光标,您只需继承基类(CChartAxis,CChartLabel或CChartCursor)并实现所需的虚拟函数。一旦完成,您可以通过调用不同函数的自定义版本(CChartCtrl :: AttachCustomAxis,CChartCtrl :: AttachCustomLabel或CChartCtrl :: AttachCustomCursor)附加您的新对象。 CChartLabel类是一个模板类。这个主题有点广泛,进入了很多细节,但最简单的方法是看看不同的现有类。
如果你想提供新的系列,这有点不同:你首先要考虑你想要在你的系列中操纵的点的类型。如果你只需要使用X和Y值来操作点,那么你可以继承CChartXYSerie,它提供了很多功能来操作这些点。然后,您必须实现所需的虚拟函数。看看下面的系列:CChartLineSerie,CChartPointSerie,CChartSurfaceSerie和CChartBarSerie具体示例。
如果你的系列操纵其他类型的点,那么你首先必须为点包含以下方法创建一个结构:double GetX(),double GetXMin(),double GetXMax(),double GetY(),double GetYMin()和double GetYMax()。一旦完成,您必须继承CChartSerieBase并将此点作为模板参数。然后,您必须提供所需的虚拟功能。看看下面的系列具体例子:CChartCandlestickSerie和CChartGanttSerie。
Upgrading from Version 1.x to Version 2.0
在版本2.0中,对控件进行重构,导致API的更改。 主要的可见变化是每个轴类型现在有其单独的类(CChartStandardAxis,CChartDateTimeAxis和CChartLogarithmicAxis)。 这也意味着默认情况下没有创建轴,并且您必须在向图表添加系列之前自己创建轴(否则代码将断言)。 这包括在“操纵轴”部分。
另一个变化是添加系列到图表的方式:AddSerie已经在CChartCtrl类中删除,并已被帮助函数替代,以创建特定的系列类型(CreateLineSerie,CreatePointsSerie,?)。 这些函数返回确切的系列类型,因此不再需要铸造。 这在“操纵系列”一节中有详细描述。
Upgrading from Version 2.x to Version 3.x
版本3.0.0的主要变化是,系列基类现在已经作为模板类,模板参数是系列操作的点类型。如果您没有通过提供新的系列类型扩展控件,这将不会在您的代码中有所不同。如果你提供了一个新的系列类型,你的类必须继承CCharSerieBase并提供它操作的点的类型。如果你的系列使用只有X和Y值的点,你可以简单地继承CChartXYSerie。看看现有的系列更多的例子。
另一个小的修改是标签提供程序现在也是模板类(出于同样的原因)。并且监听系列中的鼠标事件现在从图表上的鼠标事件中分离出来。这两点在“在点上添加标签”部分和“鼠标事件通知”部分中有很好的解释。
最后,CChartAxis :: SetAutomatic方法已被标记为已弃用,您应该使用CChartAxis :: SetAutomaticMode(已经引入了一个额外的自动模式)。
例子
本节只是两个代码片段,显示了如何使用控件。 第一个片段再现了示波器示例的图像(参见本文顶部),第二个示例再现了“2008年收入”图像。 代码是文档化的,所以它不应该太难理解。
Oscilloscope example:
// Disable the refresh of the control (avoid multiple refresh). m_ChartCtrl.EnableRefresh(false); // Create a bottom and left axes
CChartStandardAxis* pBottomAxis =
m_ChartCtrl.CreateStandardAxis(CChartCtrl::BottomAxis); CChartStandardAxis* pLeftAxis =
m_ChartCtrl.CreateStandardAxis(CChartCtrl::LeftAxis);
// Sets the min and max values of the bottom and left axis to -15 -> 15 pBottomAxis->SetMinMax(-15,15); pLeftAxis->SetMinMax(-15,15);
// Add a new series of type line to the control and add data to it CChartLineSerie* pLineSeries = m_ChartCtrl.CreateLineSerie();
// Specifies that the points in the series are not ordered (needed to be able // to draw an elwww.shanxiwang.netlipse).
pLineSeries->SetSeriesOrdering(poNoOrdering); for (int i=0;i<361;i++) {
double X = 10 * sin(i/360.0 * 2 * 3.141592);
double Y = 10 * cos( (i-60)/360.0 * 2 * 3.141592);
pLineSeries->AddPoint(X,Y);
}
// Defines the different colors (back color, axes color, ...) COLORREF BackColor = RGB(0,50,0); COLORREF GridColor = RGB(0,180,0); COLORREF TextColor = RGB(0,180,0); COLORREF SerieColor = RGB(0,255,0);
// Specifies a sunken border for the control m_ChartCtrl.SetEdgeType(EDGE_SUNKEN);
// Sets the color of the border and the back color m_ChartCtrl.SetBorderColor(TextColor); m_ChartCtrl.SetBackColor(BackColor);
//Sets the color of the different elements of the bottom axis m_ChartCtrl.GetBottomAxis()->SetAxisColor(TextColor); m_ChartCtrl.GetBottomAxis()->SetTextColor(TextColor);
m_ChartCtrl.GetBottomAxis()->GetGrid()->SetColor(GridColor);
// Sets the color of the different elements of the left axis m_ChartCtrl.GetLeftAxis()->SetAxisColor(TextColor); m_ChartCtrl.GetLeftAxis()->SetTextColor(TextColor);
m_ChartCtrl.GetLeftAxis()->GetGrid()->SetColor(GridColor);
// Sets the color of the title, change the font to Times New Roman // and add a string
m_ChartCtrl.GetTitle()->SetColor(TextColor);
m_ChartCtrl.GetTitle()->SetFont(140,_T(\
m_ChartCtrl.GetTitle()->AddString(_T(\
// Change the color of the line series pLineSeries->SetColor(SerieColor);
// Finally re-enable the refresh of the control. This will refresh the // control if any refresh was still 'pending'. m_ChartCtrl.EnableRefresh(true); “Income over 2008” example:
srand((unsigned int)time(NULL));
// Disable the refresh
m_ChartCtrl.EnableRefresh(false); COleDateTime Min(2008,1,1,0,0,0);
COleDateTime Max(2008,10,1,0,0,0);
// Create the bottom axis and configure it properly CChartDateTimeAxis* pBottomAxis =
m_ChartCtrl.CreateDateTimeAxis(CChartCtrl::BottomAxis); pBottomAxis->SetMinMax(Min,Max); pBottomAxis->SetDiscrete(true);
pBottomAxis->SetTickIncrement(false,CChartDateTimeAxis::tiMonth,1); pBottomAxis->SetTickLabelFormat(false,_T(\// Create the left axis and configure it properly CChartStandardAxis* pLeftAxis =
m_ChartCtrl.CreateStandardAxis(CChartCtrl::LeftAxis); pLeftAxis->SetMinMax(0,100);
pLeftAxis->GetLabel()->SetText(_T(\// Create the right axis and configure it properly CChartStandardAxis* pRightAxis =
m_ChartCtrl.CreateStandardAxis(CChartCtrl::RightAxis); pRightAxis->SetVisible(true);
pRightAxis->GetLabel()->SetText(_T(\pRightAxis->SetMinMax(0,200);
// Configure the legend
m_ChartCtrl.GetLegend()->SetVisible(true);
m_ChartCtrl.GetLegend()->SetHorizontalMode(true); m_ChartCtrl.GetLegend()->UndockLegend(80,50); // Add text to the title and set the font & color
m_ChartCtrl.GetTitle()->AddString(_T(\CChartFont titleFont;
titleFont.SetFont(_T(\m_ChartCtrl.GetTitle()->SetFont(titleFont);
m_ChartCtrl.GetTitle()->SetColor(RGB(0,0,128)); // Sets a gradient background
m_ChartCtrl.SetBackGradient(RGB(255,255,255),RGB(150,150,255),gtVertical);
// Create two bar series and a line series and populate them with data CChartBarSerie* pBarSeries1 = m_ChartCtrl.CreateBarSerie(); CChartBarSerie* pBarSeries2 = m_ChartCtrl.CreateBarSerie();
CChartLineSerie* pLineSeries = m_ChartCtrl.CreateLineSerie(false,true); int lowIndex = -1; int lowVal = 999; for (int i=0;i<9;i++) {
COleDateTime TimeVal(2008,i+1,1,0,0,0); int DesktopVal = 20 + rand()%(100-30);
pBarSeries1->AddPoint(TimeVal,DesktopVal);
int LaptopVal = 10 + rand()%(80-20);
pBarSeries2->AddPoint(TimeVal,LaptopVal); int Income = DesktopVal + LaptopVal*1.5; if (Income < lowVal) {
lowVal = Income; lowIndex = i; }
pLineSeries->AddPoint(TimeVal,Income); }
// Configure the series properly
pBarSeries1->SetColor(RGB(255,0,0)); pBarSeries1->SetName(_T(\pBarSeries2->SetColor(RGB(68,68,255));
pBarSeries2->SetGradient(RGB(200,200,255),gtVerticalDouble); pBarSeries2->SetName(_T(\
pBarSeries2->SetBorderColor(RGB(0,0,255)); pBarSeries2->SetBorderWidth(3);
pLineSeries->SetColor(RGB(0,180,0));
pLineSeries->SetName(_T(\pLineSeries->SetWidth(2);
pLineSeries->EnableShadow(true);
// Add a label on the line series. TChartStringStream labelStream;
labelStream << _T(\CChartBalloonLabel
pLineSeries->CreateBalloonLabel(lowIndex, labelStream.str() + _T(\CChartFont labelFont;
labelFont.SetFont(_T(\pLabel->SetFont(labelFont);
// Re enable the refresh
m_ChartCtrl.EnableRefresh(true);
Feedback
Quite a lot of work is involved in the development of this control and, as any other software project, it might still contain bugs or errors in the documentation. If you encounter such a problem, please let me know (even if you fixed it yourself) so that I can fix the issue as soon as possible. Other users of the control will thank you for that. The same if you encounter errors in the documentation or typos in the article.
I’m also more or less constantly working on this control to add new features. If you have