Adding Charts With the "Easy-to-Use" Control: CChartCtrl

Wednesday Mar 12th 2003 by Scott M. Pelger

Adding flexible charts quickly and easily requires a good control. Discover how to use this charting control in your own applications. (The demo program and source code were updated.)

Click here for a larger image.

Environment: VC6 SP5

About a year ago, there were not as many chart implementations on as there are now. This is why I decided to write one of my own. I am happy to see more implementations now and to be among those who attempt to author such a useful control. I set out to design a simple charting control that fit my needs as they are today and to build on them as future needs arise. I believe that this is laid out in an easy manner that you can take advantage of for your customized needs also.

The CChartCtrl is based on a CWnd and can be placed anywhere a CWnd can be placed. The sample application places it into a CChartView (based on CView) as a data member, as well as on a dialog that shows some of the styles that can be set. I believe this to be an easy peice of code to take advantage of because it is so straightforward, as shown in the following code snippit from the dialog's OnInitDialog():

                  CRect(0, 0, 0, 0), 



m_wndChart.SetAxisFormatString(X_AXIS, CString("%.2f"));
m_wndChart.SetAxisFormatString(Y_AXIS, CString("%.2f"));

/****clear all data and create the data sets****/
m_wndChart.AddDataSeries("RED", RGB(255, 0, 0));
m_wndChart.AddDataSeries("GREEN", RGB(0, 255, 0));
m_wndChart.AddDataSeries("BLUE", RGB(0, 0, 255));
/****clear all data and create the data sets****/

CDataPoint DataPoint;
double dDivisor((rand()%20)+2+2*DBL_EPSILON); //mimimum == 2

/****invent some data****/
for (int i(0);i<10;i++) {
    DataPoint.m_dX = i;
    DataPoint.m_dY = (rand()%50)/dDivisor;
    DataPoint.m_sCaption.Format("DataPoint %d", i);

    DataPoint.m_dY = (rand()%50)/dDivisor;
    DataPoint.m_sCaption.Format("DataPoint %d", i);
    m_wndChart.AddDataPoint(&DataPoint, 1);

    DataPoint.m_dY = (rand()%50)/dDivisor;
    DataPoint.m_sCaption.Format("DataPoint %d", i);
    m_wndChart.AddDataPoint(&DataPoint, 2);
/****invent some data****/



That's pretty much it. Using this in a CView-based object is not much different; you need to create it as above in your overridden OnCreate() function and handle the sizing in your overridden OnSize() function. Check out CChartView to see how this is done; they're both one-liners.

You can periodically add data points through a timer or other timed event; this is what the StripChart does. Cleanup is handled on its own.

Things to note:

The strip chart does work but can eat a lot of processor resources if the style is any of the filled strip charts greater than 60 data points. The bottle neck here is the CDC::Polygon() function. To overcome this, the strip chart skips every other data point and compresses what is already there. Compressing any more than every other data point results in a lousy image, at best. After the maximum number of data points is reached (automatically set, based on the strip chart type), the chart begins to scroll from right to left, tossing out the oldest point. Here, the image is shifted toward the right and only a new data segment is added. At this point, CPU usage is barely perciveable. I was hoping to improve this CPU hog considerably, but I am out of ideas. I welcome any suggestions you may have. The non-filled strip chart is not a problem and is graphically superior because it redraws completely every time.

Currently the data sets are limited to positive numbers because those are my needs for the time being.

Included in the demo project is a CChartCtrl interface guide called ChartHelp.htm.


Download demo project - 60 Kb
Download source - 129 Kb
Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved