分类: C/C++
2008-09-14 19:48:16
For one of my previous projects, I needed to display a continuous flow of data on a charting control. I decided to develop my own control because I couldn't find any free control that could provide the required flexibility. One of the main restrictions was that the control had to plot a lot of data and be able to display it quickly (on a Pocket PC). The control is able to do that by plotting only the new points of data, not the complete series. The chart is also able to display static data.
This control is the result of long hours of work and sometimes frustration in order to provide something flexible enough to be used by people who need it. I would really appreciate feedback: a mail, a post in the message board or just by rating the article. There is no point for me to maintain this control when I don't know if it is used.
This article contains two main parts: a section that describes , and a section that lists . With the first part, you will be able to quickly integrate the control inside your application. If a more advanced control is required, the second part will be useful because it lists the properties of all the objects of the chart.
This control is the result of a lot of hours of development, thus I'm placing some minor conditions on the use of the code:
This code may be used for any non-commercial
and commercial purposes in a compiled form.
The code may be redistributed as long as it remains
unmodified and providing that the author name
and the disclaimer remain intact. The sources
can be modified with the author consent only.
This code is provided without any guarantees.
I cannot be held responsible for the damage or
the loss of time it causes. Use it at your own risks.
This is not too much to ask considering the effort spent on the development of this control. If this code is used in a commercial application, then please send me a mail letting me know.
The main features of the control are:
In order to be able to use the chart control in your application, you first need to add the files contained in the sources zip in your project. There are two ways of using the chart control within your application: inserting it manually, or through the resource editor.
Important: the control uses dynamic casts internally so RTTI (RunTime Type Information) must be enabled, otherwise a crash will probably occur. RTTI is not enabled by default for VC6, so to enable it open the project settings -> "C/C++" tab -> "C++ language" category and there make sure that the "Enable Run-Time Type Information (RTTI)" check-box is checked.
#include "ChartCtrl"
at the top of your dialog header file
CChartCtrl
in your dialog class: //{{AFX_DATA(CChartDemoDlg)
//}}AFX_DATA
CChartCtrl m_ChartCtrl;
OnInitDialog
of your dialog class, call the Create
method of the control. ChartCtrl
for the Class
attribute. To avoid flickering on the scrollbars, you have to set the WS_CLIPCHILDREN
style (0x02000000L), as shown on the image. #include "ChartCtrl.h"
at the beginning of your dialog header file.
CChartCtrl
in your dialog class: //{{AFX_DATA(CChartDemoDlg)
//}}AFX_DATA
CChartCtrl m_ChartCtrl;
DDX_Control
line in the DoDataExchange
function in the CPP file of your dialog class (don't forget to change the ID and the name to the appropriate values): void CChartDemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CChartDemoDlg)
// Add this line with the appropriate ID and variable name
DDX_Control(pDX, IDC_CHARTCTRL, m_ChartCtrl);
//}}AFX_DATA_MAP
}
Once the chart is ready to be used, you can add data to it. As the chart can have multiple series, you first need to add at least one series (there is no maximum limit for the series number). A series can be of different types; for now, only line and point series are supported.
CChartLineSerie* pLineSerie = dynamic_cast<CChartLineSerie*>
(m_ChartCtrl.AddSerie(CChartSerie::stLineSerie));
CChartPointsSeries* pPointSerie = dynamic_cast<CChartPointsSerie*>
(m_ChartCtrl.AddSerie(CChartSerie::stPointsSerie));
The cast is only required if you need to change the properties that are related to the series type (point size, line style, ...), otherwise you can work with the CChartSerie
pointer returned by AddSerie
.
You can then add data to the series. You can either set all the data of the series in one block, or you can add data point by point. The latter is used for dynamic display of data, and only the new points are drawn (which is much faster); take a look at the CChartSerie::AddPoint
method.
Here is an example for setting the data in one block:
double XValues[10];
double YValues[10];
for (inti=0;i<10;i++)
XValues[i] = YValues[i] = i;
pLineSerie->SetPoints(XValues,YValues,10);
pPointSerie->SetPoints(XValues,YValues,10);
You can also customize the chart control by accessing the properties of the different objects in the control. One important rule is that you will never create your own object but always retrieve them through the CChartCtrl
class. For example, if you want to change the scale of the bottom axis, call GetBottomAxis
from CChartClass
; this will return you a pointer to the a CChartAxis
class in which you can call SetMinMax
to change the minimum and maximum values.
m_MyChartCtrl.GetBottomAxis()->SetMinMax(-10,10);
Important: Since the version 1.4 of the control, every call to modify a property on the control will cause a complete refresh of the control (even things like changing the font of some text or the color of an object). To avoid that the control is refreshed when it is not necessary (like for example when you change several properties at the same time), you should disable the refresh, change the properties and then re-enable the refresh:
m_ChartCtrl.EnableRefresh(false);
// Set your properties here
...
m_ChartCtrl.EnableRefresh(true);
This should typically be done when you first initialize the control for example.
Note: Since the version 1.5 of the control, support for UNICODE has been introduced. All occurances of std::string
objects have been replaced by TChartString
objects, which is simply a typedef which resolves to a std::string
if UNICODE is not enabled and resolves to std::wstring
when UNICODE is enabled.
In version 1.1 of the control, zoom and pan features have been added to the control. The zoom is controlled with the left mouse button, and the pan is controlled with the right mouse button. To zoom a specific part of the chart, simply left-click on the chart (this will be the upper-left corner of the zoomed rectangle) and drag to the bottom-right. A rectangle will appear. As soon as you release the mouse button, the four axes will automatically adjust themselves to the region you have selected. The zoom is enabled by default but you can disable it by calling CChartCtrl::SetZoomEnabled(bool bEnabled)
. You can also specify a zoom limit for each axis by calling CChartAxis::SetZoomLimit(double dLimit)
. This specifies the minimum range of the axis while zooming. Default is 0.001.
To pan the control, right-click somewhere on the control and move the mouse. The point under the mouse will 'follow' the movement of the mouse (in fact, the axis min and max will change). The pan is enabled by default but you can disable it by calling CChartCtrl::SetPanEnabled(bool bEnabled)
.
If you left-click on the chart (like for starting a zoom) but if you move to the top-left corner instead, all the modifications done with the zoom and pan features will be cancelled (the control will be in the state it was before the manipulations with the pan and zoom). Finally, there is also a way to disable to pan and zoom feature for a specific axis by calling CChartAxis::SetPanZoomEnabled(bool bEnabled)
In version 1.2 of the control, date/time axes have been added. The important point to understand about date/time axis is that they work internally with COleDateTime
objects. The reason is simple: COleDateTime
is a wrapper class around the DATE
type which is simply a double. As points in the chart are expressed as double values, it fits nicely: there is no difference between using standard points (non date/time) and date/time points, which makes the usage of the latter less complicated. All points are still stored as double
, no matter if they are date/time or not.
The first thing to do when working with date/time data is to change the type of the specific axis to date/time type. This is done by calling void SetAxisType(AxisType Type)
on the axis. The example below will switch the bottom axis to date/time mode:
m_ChartCtrl.GetBottomAxis()->SetAxisType(CChartAxis::atDateTime);
You can then populate data in the control. For that purpose, nothing changed: you have to call either void AddPoint(double X, double Y)
or void SetPoints(double *X, double *Y, int Count)
from the CChartSerie
class. The CChartCtrl
class provides you with two static
functions to let you convert from a COleDateTime
to a double
and vice-versa:
double DateToValue(const COleDateTime& Date)
COleDateTime ValueToDate(double Value)
If you have a date in another format (e.g. a time_t
or a SYSTEMTIME
), this is not a problem because the COleDateTime
object can be constructed from different time formats (check the MSDN documentation of the COleDateTime
class to see from which format you can construct it).
Once you have populated your data, you can configure the axis to display what you need. Several functions related to date/time axis are available:
void SetDateTimeIncrement(TimeInterval Interval, int Multiplier)
void SetDateTimeFormat(bool bAutomatic, const TChartString& strFormat)
The first one lets you specify an interval between two ticks displayed on the axis. For a date/time axis, the function SetTickIncrement
is not used anymore and if you want to specify a tick interval, you should use SetDateTimeIncrement
. The interval between two ticks will respect the correct time, meaning that if you specify a tick increment of 1
month (Interval=CChartAxis::tiMonth and Multiplier=1)
, then the space between two ticks will be irregular (28, 30 or 31 days).
The second function let's you specify the format of the tick label. The control automatically formats the tick labels depending on the tick interval but you can override it by calling this function. Check the documentation of the COleDateTime::Format
function on MSDN for more information.
Important note: You should be careful when using date/time axis with the pan feature enabled. There is a known issue when the interval between two ticks is different than one time interval (e.g. 2 months, or 3 years). When the axis is moved so that another time unit is available on the axis, this new unit will be taken as first tick, no matter what the previous tick was, resulting in a 'cyclic' tick. Let's take an example to make things clearer. Suppose that you have a date/time axis that starts at February 8th with an interval of 2 days between the ticks (so, the next tick that is displayed is February 10th, and so on). When you pan the axis in order to see previous data, as soon as the February 7th will be on the axis, this will be taken as new first tick (and the tick for the February 8th will disappear, replaced by February 9th). So, the effect is visually disturbing. I'll try to fix the problem but I still didn't came up with a solution for that.
The line and point series allow you to plot data at a high rate. This is typically done when you want to plot data coming from an external device for example (e.g. a sensor). This is possible because, when you add a point to such a series, the control won't be refreshed totally, only the last point (or last line section) will be drawn, which is quite efficient. However, you have to take into consideration several points if you want the control to plot data fast enough.
One important thing is that the use of automatic axes will probably decrease a lot the performances. This is due to the fact that if a point is plotted outside the range of the axis, the axis range will be automatically adjusted, which means that the control will be totally refreshed. So, if you are using an automatic bottom axis and have a 'scroll' trace, each new point will be outside the current range of the axis and a refresh of the control will occur for every points. A better way to handle that would be to use a fixed axis and to increase manually the range of the axis each second (or at a reasonable rate).
Another important point is that you should never call RefreshCtrl
after having added a new point to a series. This will of course refresh completely the control which should be avoided. Finally, if you need to apply several modifications or add several points to the control at the same time, you should wrap those calls between EnableRefresh(false)
and EnableRefresh(true)
(see the "Changing the Properties of Objects" section).
This section describes the functionalities of all the classes that are part of the control.
This is the base class for all the components in the control; except for the CChartCtrl
class, all classes of the control inherit from this class. It lets you access the general properties of objects:
void SetVisible(bool bVisible)
bool GetVisible() const
Get
/set
the visibility of the object.
void SetColor(COLORREF NewColor)
COLORREF GetColor() const
Get
/set
the color of the object.
void EnableShadow(bool bEnable)
Specifies if the object generate a shadow. This is not available for all objects, only for CChartLegend
, CChartTitle
, CChartLineSerie
, CChartBarSerie
and CCharPointSerie
.
void SetShadowColor(COLORREF NewColor)
COLORREF GetShadowColor() const
Get
/set
the color of the shadow.
void SetShadowDepth(int Depth)
Specifies the depth of the shadow. This is the distance (in pixels) from the top-left corner of the object to the top-left corner of the shadow.
This is the main class of the control, through which you can access and modify the properties of all other components of the control (axis, legend, grid).
bool Create(CWnd* pParentWnd, const RECT& rect, UINT nID, DWORD dwStyle=WS_VISIBLE)
Creates the chart 'dynamically' (not through the resources editor).
pParentWnd
: Parent window of the control
rect
: Position of the control
nID
: ID of the control
dwStyle
: Style of the control void RefreshCtrl()
Forces a redraw of the control. This is in general not needed because all modifications on the control will automatically refresh the control.
void EnableRefresh(bool bEnable)
Enable or disable the refresh of the control. This is used when several settings have to be changed at the same time on the control. This way we can avoid refreshing the control when it is not needed (see the "Changing the Properties of Objects" section).
COLORREF GetBackColor() const
void SetBackColor(COLORREF NewCol)
Get
s/set
s the background color.
COLORREF GetBorderColor() const
void SetBorderColor(COLORREF NewCol)
Get
s/set
s the color of border of the drawing area. This area is the one limited by the four axes.
void SetEdgeType(UINT NewEdge)
UINT GetEdgeType() const
Set
s and retrieves the edge type for the control border. See DrawEdge
in MSDN for the different border types.
CChartSerie* AddSerie(int Type)
Adds a series to the chart control.
Type
: Specifies the type of the series. The different series that can be added are the following:
CChartSerie::stLineSerie
CChartSerie::stPointsSerie
CChartSerie::stSurfaceSerie
CChartSerie::stBarSerie
NULL
if an error occurred. void RemoveSerie(size_t Index)
Remove a series from the control.
Index
: Index of the series to be removed void RemoveSerie(CChartSerie* pToRemove)
Remove a series. The pointer of the series to be removed is passed as an argument.
void RemoveAllSeries()
Remove all the series from the control.
size_t GetSeriesCount() const
Returns the number of series in the control.
CChartAxis* GetBottomAxis() const
CChartAxis* GetLeftAxis() const
CChartAxis* GetTopAxis() const
CChartAxis* GetRightAxis() const
Returns a pointer to the bottom, left, top, and the right axis respectively. Properties of the axes can then be modified through this pointer.
CChartLegend* GetLegend() const
Returns a pointer to the legend object. Properties of the legend can be modified through this pointer.
CChartTitle* GetTitle() const
Returns a pointer to the title object. Properties of the titles can be modified through this pointer.
void SetPanEnabled(bool bEnabled)
bool GetPanEnabled() const
Set
s and retrieves if the panning feature is enabled.
void SetZoomEnabled(bool bEnabled)
bool GetZoomEnabled() const
Set
s and retrieves if the zoom feature is enabled.
void UndoPanZoom()
Undo all the pan and zoom modifications. This has the same effect as undoing a zoom or pan operation with the mouse.
static double DateToValue(const COleDateTime& Date)
static COleDateTime ValueToDate(double Value)
Helper functions to convert from a COleDateTime
to a double
and from a double
to a COleDateTime
.
void SetBackGradient(COLORREF Col1, COLORREF Col2, EGradientType GradientType)
Specifies a gradient background for the control.
Col1
: The first gradient color.
Col2
: The second gradient color.
GradientType
: The type of gradient, which can be one of the following:
gtHorizontal
: a simple left-to-right gradient, from Col1 to Col2.
gtVertical
: a simple top-to-bottom gradient, from Col1 to Col2.
gtHorizontalDouble
: a left-to-middle-to-right gradient, with Col2 in the middle.
gtVerticalDouble
: a top-to-middle-to-bottom gradient, with Col2 in the middle. Note: Gradient functionality is not available for VC6 and earlier.
void Print(const TChartString& strTitle, CPrintDialog* pPrntDialog = NULL)
Print the chart.
strTitle
: The title of the print document.
pPrntDialog
: A pointer to a CPrintDialog. If NULL is passed, the default print dialog will be displayed. This is the base class for all specialized series in the control. It allows you to modify the general properties of a series. By default the points in the series are reordered along the X coordinate. If you need to remove this behavior (like in the oscilloscope example), call the SetSeriesOrdering
function
void AddPoint(double X, double Y)
Adds a new point in the series.
double X
: X value of the point
double Y
: Y value of the point void AddPoints(double* X, double* Y, int Count)
Adds new points which are appedend to the end of the series.
double* X
: Array containing the X values for all the points
double* Y
: Array containing the Y values for all the points
int Count
: Number of points to be added (size of the array) void SetPoints(double *X, double *Y, int Count)
Clears the series and adds an array of points. A refresh of the control is necessary for these changes to be visible.
double* X
: Array containing the X values for all the points
double* Y
: Array containing the Y values for all the points
int Count
: Number of points to be added (size of the arrays) void ClearSerie()
Removes all the points from the series.
void RemovePointsFromBegin(unsigned Count)
Removes Count
points from the begining of the series.
void RemovePointsFromEnd(unsigned Count)
Removes Count
points from the end of the series.
size_t GetPointsCount() const
Returns the number of points in the series.
double GetXPointValue(int PointIndex) const
double GetYPointValue(int PointIndex) const
Returns the X or Y value of the point at the index specified by PointIndex
.
void SetXPointValue(int PointIndex, double NewVal)
void SetYPointValue(int PointIndex, double NewVal)
Sets the X or Y value of the point at a specific index.
PointIndex
: Index of the point to be modified
NewVal
: New value of the point bool GetSerieXMinMax(double& Min, double& Max) const
bool GetSerieYMinMax(double& Min, double& Max) const
Retrieves the minimum and maximum X or Y values of the series. If there is no point in the series, false
is returned.
void SetName(const TChartString& NewName)
TChartString GetName() const
Get
s/set
s the name of the series. The name is only used when displayed in the legend. If no name is set, the series won't appear in the legend.
bool SetHorizontalAxis(bool bSecond)
bool SetVerticalAxis(bool bSecond)
Set
s the horizontal or vertical axis to which the series is associated.
bSecond
: Specifies the primary or secondary axis (the secondary axis is the top axis for the horizontal axis and the left axis for the vertical axis) void ValueToScreen(double XValue, double YValue, CPoint& ScreenPoint) const
Converts a point (in value) into screen coordinates.
double XValue
: X value of the point
double YValue
: Y value of the point
CPoint& ScreenPoint
: Point in which the results will be stored double XScreenToValue(long XScreenCoord) const
double YScreenToValue(long YScreenCoord) const
Converts an X or Y screen coordinate into a value. The value is returned by the method.
SeriesOrdering GetSeriesOrdering() const
void SetSeriesOrdering(SeriesOrdering newOrdering)
Get
s/Set
s the ordering of the series. The series ordering defines if the points are reordered when added to the series. If a series is oredered, there is a small speed improvement because only the points which are on the screen will be plotted. The SeriesOrdering is an enum which can take the following values:
soNoOrdering
: The points are not reordered. This is less efficient but sometimes needed (for example if you have to draw an ellipse).
soXOrdering
: The points are ordered along the X coordinate. This is the default value.
soYOrdering
: The points are ordered along the Y coordinate. Warning: if you specify an ordering (along the X or Y coordinate), the points will be reordered and you won't be able to revert to the original ordering when switching to no ordering (this will only affect future points that will be added to the series).
The CChartPointSerie
class is a specialized series class used to plot points. The shape and the size of the points can be modified.
void GetPointSize(int& XSize, int& YSize) const
void SetPointSize(int XSize, int YSize)
Get
s/set
s the X and Y size of the points displayed. The size is expressed in pixels.
PointType GetPointType() const
void SetPointType(PointType Type)
Get
s/set
s the type of the points displayed. PointType
is an enum that can take the following values:
ptEllipse
: The points are ellipses (if X and Y sizes are the same, the points are circles)
ptRectangle
: The points are rectangles
ptTriangles
: The points are triangles The CChartLineSerie
class is a specialized series class used to plot lines. The pen style and the width of the line can be modified.
int GetPenStyle() const
void SetPenStyle(int NewStyle)
Get
s/set
s the style of the pen (solid, dashed, ...). For a list of pen styles available, see the CreatePen
function in MSDN.
int GetWidtth() const
void SetWidth(int NewValue)
Get
s/set
s the width of the line. The width is expressed in pixels.
The CChartSurfaceSerie
class is a specialized series class used to display surfaces. A surface can be horizontal (default) or vertical: this defines how the filling of the surface is done. For a horizontal surface, the filling is done between the points and the associated horizontal axis and for a vertical surface, the filling is done between the points and the associated vertical axis. Of course, you can associate the series with a secondary axis. For example, if the surface series is horizontal and is associated with the top axis (secondary axis), the filling is done between the top axis and the points.
FillStyle GetFillStyle() const
void SetFillStyle(FillStyle NewStyle)
Get
s/set
s the style of the filling area (solid, hatched, ...). FillStyle
is an enumeration with the different fill styles as follow:
fsSolid
: The area is completely filled with the color of the series.
fsHatchDownDiag
: The area is filled with a hatching pattern. The lines are diagonal from the top-left corner to the bottom-right corner.
fsHatchUpDiag
: The area is filled with a hatching pattern. The lines are diagonal from the bottom-right corner to the top-left corner.
fsHatchCross
: The area is filled with a hatching pattern. The lines are both horizontal and vertical.
fsHatchDiagCross
: The area is filled with a hatching pattern. The lines are diagonal (both directions).
fsHatchHorizontal
: The area is filled with a hatching pattern. The lines are horizontal.
fsHatchVertical
: The area is filled with a hatching pattern. The lines are vertical. void SetHorizontal(bool bHoriz)
bool GetHorizontal() const
Specifies if the surface is horizontal (for the Set
method).
The CChartBarSerie
class is a specialized series class used to display vertical (default) or horizontal bars. Each bar in the series is centered around its X value (for vertical bars) or Y value (for horizontal bars). Bars can be grouped together, so that they do not overlap but are stacked next to each other (or on top of each other). This is done by specifying a group Id: bar series with the same group Id will be grouped together (stacked). Series with different group Id will be independant (they will be drawn as if they were the only one, meaning that the different series will probably overlap).
bool GetHorizontal() const
void SetHorizontal(bool bHorizontal)
Get
s/set
s the horizontal or vertical mode.
COLORREF GetBorderColor() const
void SetBorderColor(COLORREF BorderColor)
Get
s/set
s the bar border color.
int GetBorderWidth() const
void SetBorderWidth(int Width)
Get
s/set
s the bar border width (in pixels).
int GetBarWidth() const
void SetBarWidth(int Width)
Get
s/set
s the width of the bar (in pixels).
unsigned GetGroupId() const
void SetGroupId(unsigned GroupId))
Get
s/set
s the group Id of the bar. Bars with the same group Id will be stacked instead of overlapping.
void SetGradient(COLORREF GradientColor, EGradientType GradientType)
Specify a gradient color and a gradient type for the bar. EGradientType is an enumeration that can take the following values:
gtHorizontal
: a simple left-to-right gradient, with the left color being the series color.
gtVertical
: a simple top-to-bottom gradient.
gtHorizontalDouble
: a left-to-middle-to-right gradient (gradient color in the middle).
gtVerticalDouble
: a top-to-middle-to-bottom gradient (gradient color in the middle). void ShowGradient(bool bShow)
Show or hide the gradient on the bar series.
Note: gradient functionality is not available for VC6 and before.
static int GetInterSpace()
static void SetInterSpace(int Space)
Static functions to get
s/set
s the space between bar series with the same group Id (in pixels).
void SetBaseLine(bool bAutomatic, double dBaseLine)
Enable (or disable a baseline for the bar series). The base line specifies from where the bar starts (in axis value). If the baseline is set to automatic, the bars will be drawn from the bottom axis (for vertical bars).
This class allows you to modify the properties of the axes of the chart control. Pointers to these classes can be retrieved by calling GetLeftAxis()
, GetBottomAxis()
, GetRightAxis()
, or GetTopAxis()
from the CChartCtrlClass
.
void SetInverted(bool bNewValue)
bool IsInverted() const
Get
s/set
s the axis inverted. If the axis is inverted, the minimum value is displayed at the top of the axis.
void SetLogarithmic(bool bNewValue)
bool IsLogarithmic() const
Get
s/set
s the axis logarithmic.
Note: this function exists only for backward compatibility. You should use SetAxisType
instead.
void SetAxisType(AxisType Type)
AxisType GetAxisType() const
Set
s and retrieve the axis type, which AxisType
being an enumeration with the following values:
atStandard
: Standard axis (non-logarithmic and non-date/time)
atLogarithmic
: Logarithmic axis
atDateTime
: Date/time axis void SetAutomatic(bool bNewValue)
bool IsAutomatic() const
Get
s/set
s the axis automatic. If the axis is automatic, the maximum and minimum values will be recalculated each time data goes out of the range of the axis (auto-scaling). You can still use the SetMinMax
method to supply the default range (that will stay if the data does not go outside these bounds).
void GetMinMax(double& Minimum, double& Maximum) const
void SetMinMax(double Minimum, double Maximum)
Get
s/set
s the minimum and maximum values of the axis.
double GetTickIncrement() const
void SetTickIncrement(bool bAuto, double Increment)
Get
s/set
s the tick increment. This allows you to specify your own value for the tick increment used on the axis (or to set it to automatic).
bAuto
: Specifies if the tick increment is calculated automatically or is defined by the user. If automatic, the Increment
parameter is ignored.
Increment
: Tick increment used on the axis when not automatic. Note: Do not use these functions if the axis is set to date/time. You should use the SetDateTimeIncrement
function instead.
void SetDateTimeIncrement(bool bAuto, TimeInterval Interval, int Multiplier)
Set
s the tick increment for a date/time axis or set
s it to automatic.
bAuto
: Specifies if the tick increment is calculated automatically or is defined by the user. If automatic, the other parameters are ignored.
Interval
: Specifies the base interval between two ticks. This interval is then multiplied by the Multiplier
parameter to have the total interval between two ticks. This parameter can have one of the following values:
tiSecond
tiMinute
tiHour
tiDay
tiMonth
tiYear
Multiplier
: Tick increment used on the axis when not automatic. void SetDateTimeFormat(bool bAutomatic, const TChartString& strFormat)
Lets you specify the format of the tick labels for a date/time axis (or switch to automatic).
bAutomatic
: Specifies if the format of the tick label is automatic or user defined. If automatic, the strFormat
parameter is ignored.
strFormat
: Format of the tick label. Check the documentation of the COleDateTime::Format
function on MSDN for more information. long ValueToScreen(double Value) const
double ScreenToValue(long ScreenVal) const
Converts an axis value to the corresponding screen value, or converts a screen value to the corresponding axis value.
void SetFont(int nPointSize,const TChartString& strFaceName)
Set
s the font used to display the tick labels. For more information, see the CreatePointFont
in MSDN.
nPointSize
: Size of the font
strFaceName
: Specifies the typeface name of the font void SetTextColor(COLORREF NewColor)
COLORREF GetTextColor() const
Set
s/Get
s the color of the axis text (the numbers that appear next to the ticks).
void SetMarginSize( bool bAuto, int iNewSize)
Specifies the total size of the axis margin (including the axis label, the tick labels and the ticks). This function can be used when several charts need to be stacked with the vertical axis at the same position.
bAuto
: Specifies if the size is automatic or user defined. If automatic, the iNewSize
parameter is ignored.
iNewSize
: Specifies the new size of the margin, in pixels. CChartAxisLabel* GetLabel() const
Get
s a pointer to the CChartAxisLabel
class associated with this axis. Through this class, you can set the properties of the axis label (axis title).
CChartGrid* GetGrid() const
Get
s a pointer to the CChartGrid
class associated with this axis. Through this class, you can access the properties of the grid associated with this axis.
void SetPanZoomEnabled(bool bEnabled)
Specifies if the the pan ans zoom feature is enabled for this axis.
void SetZoomLimit(double dLimit)
Specifies the limit of the zoom. This is in fact the minimum range that the axis will display while doing a zoom operation. This is not supported for logarithmic axes.
void EnableScrollBar(bool bEnabled)
Enable/disable the scrollbar on this axis. A disabled scrollbar won't be visible.
bool ScrollBarEnabled() const
Returns true if the scrollbar is enabled, otherwise false.
void SetAutoHideScrollBar(bool bAutoHide)
bool GetAutoHideScrollBar() const
Sets/Gets the auto-hide mode of the scrollbar. When auto-hide mode is hidden unless the mouse is over it. This avoids parts of the series to be hidden by the scrollbars.
This class is responsible for the label of an axis. It is retrieved by calling the GetLabel()
function from the CChartAxis
class.
TChartString GetText() const
void SetText(const TChartString& NewText)
Get
s/set
s the axis title.
void SetFont(int nPointSize,const TChartString& strFaceName)
Set
s the font used for the axis labels. For more information, see CreatePointFont
in MSDN.
nPointSize
: Size of the font.
strFaceName
: Specifies the typeface name of the font. This class is responsible for the grid related to an axis. There are no specific properties except the ones inherited from the CChartObject
class (SetVisible
and SetColor
). It is also retrieved by calling the GetGrid()
function from the CChartAxis
class.
This class is responsible for the legend displayed on the control. It is retrieved by calling the GetLegend()
function from the CChartCtrl
class.
void SetFont(int nPointSize,const TChartString& strFaceName)
Set
s the font used for the series names in the legend. For more information, see CreatePointFont
in MSDN.
nPointSize
: Size of the font
strFaceName
: Specifies the typeface name of the font void DockLegend(DockSide dsSide)
Docks the legend on one side of the control. DockSide is an enumeration that can take the following values:
dsDockRight
: legend is docked on the right of the control.
dsDockLeft
: legend is docked on the left of the control.
dsDockTop
: legend is docked on the top of the control.
dsDockBottom
: legend is docked on the bottom of the control. void UndockLegend(int iLeftPos, int iTopPos)
Specifies that the legend is floating on top of the control, with iLeftPos
being the position of the left side of the legend and iTopPos
being the position of the top side of the legend (relative to the area of the chart control).
void SetTransparent(bool bTransparent)
Specifies if the background of the legend is transparent or not.
void SetHorizontalMode(bool bHorizontal)
Specifies if the items in the legend are in horizontal mode (elements next to each others). The default is vertical (items on top of each other).
This class is responsible for the titles displayed on the control. Several lines can be displayed in the title. It is retrieved by calling the GetTitle()
function from the CChartCtrl
class.
size_t GetStringCount() const
Get
s the number of strings in the title.
TChartString GetString(size_t Index) const
Get
s the string at the specified index.
void AddString(const TChartString& NewString)
Adds a new string in the title.
void RemoveAll()
Removes all strings in the title.
void SetFont(int nPointSize, const TChartString& strFaceName)
Set
s the font used for the series names in the legend. For more information, see CreatePointFont
in MSDN.
nPointSize
: Size of the font
strFaceName
: Specifies the typeface name of the font This section is simply a code snippet that shows how the control can be used. This snippet of code will reproduce the image of the oscilloscope example (see the top of this article). The code is documented so it shouldn't be too difficult to understand.
// Disable the refresh of the control (avoid multiple refresh).
m_ChartCtrl.EnableRefresh(false);
// Add a new series of type line to the control and add data to it
CChartLineSerie* pLine = (CChartLineSerie*)m_ChartCtrl.AddSerie(CChartSerie::stLineSerie);
// Specifies that the points in the series are not ordered (needed to be able
// to draw an ellipse).
pLine->SetSeriesOrdering(CChartSerie::soNoOrdering);
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);
pLine->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 min and max values of the bottom and left axis to -15 -> 15
m_ChartCtrl.GetBottomAxis()->SetMinMax(-15,15);
m_ChartCtrl.GetLeftAxis()->SetMinMax(-15,15);
//Sets the color of the different elements of the bottom axis
m_ChartCtrl.GetBottomAxis()->SetColor(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()->SetColor(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("Times New Roman"));
m_ChartCtrl.GetTitle()->AddString(_T("An example of oscilloscope"));
// Change the color of the line series
pLine->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);
ScreenToValue
function (CChartAxis
)
RemoveAllSeries
function (CChartCtrl
)
RemovePointsFromBegin
, RemovePointsFromEnd
and AddPoints
in the CChartSeries
class
EnableRefresh
and UndoPanZoom
functions added in CChartCtrl
I would like to thank all the people from this community, they were a great help when I started programming. Thanks also to all the people who contributed to this control with their various help or feedback: toxcct, Chris Maunder, Kevin Hoffman, jerminator-jp, Laurie Gellatly, Eugene Pustovoyt, Andrej Ritter and Nick Holgate. A special thanks to Bruno Lavier for the time spent working on the control. I hope I didn't forget anybody.