Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5833519
  • 博文数量: 671
  • 博客积分: 10010
  • 博客等级: 上将
  • 技术积分: 7310
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-14 09:56
文章分类

全部博文(671)

文章存档

2011年(1)

2010年(2)

2009年(24)

2008年(271)

2007年(319)

2006年(54)

我的朋友

分类: C/C++

2008-09-14 19:48:16

ChartImage1a.JPG

ChartImage2a.jpg

ChartImage3a.jpg

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:

  • High-speed drawing (when axis is fixed) which allows fast plotting of data
  • Unlimited number of series (memory is the limitation)
  • Unlimited amount of data per series
  • Line, point, surface and bar series available
  • Up to four axes (left, bottom, right, and top axes)
  • Standard, logarithmic or date/time axis
  • Automatic, and/or inverted axes (independent from each other)
  • Axis labels
  • Grid
  • Legend and titles
  • Support for manual zoom and mouse panning
  • Support for scrollbar on the axes
  • Highly customizable (colors, titles, labels, edge, fonts, etc.)
  • Support for UNICODE
  • Support for printing

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.

  1. #include "ChartCtrl" at the top of your dialog header file
  2. Add a variable of type CChartCtrl in your dialog class:
    //{{AFX_DATA(CChartDemoDlg)
    //}}AFX_DATA
    
    CChartCtrl m_ChartCtrl;
  3. In the OnInitDialog of your dialog class, call the Create method of the control.

  1. Add a custom control to your dialog resource, open the Properties of the control, and specify 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.
    Chart properties
  2. #include "ChartCtrl.h" at the beginning of your dialog header file.
  3. Add a variable of type CChartCtrl in your dialog class:
    //{{AFX_DATA(CChartDemoDlg)
    //}}AFX_DATA
    
    CChartCtrl m_ChartCtrl;
  4. Add a 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)

    Gets/sets the background color.

  • COLORREF GetBorderColor() const
  • void SetBorderColor(COLORREF NewCol)

    Gets/sets 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

    Sets 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
    • Return value: A pointer to the new series, or 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

    Sets and retrieves if the panning feature is enabled.

  • void SetZoomEnabled(bool bEnabled)
  • bool GetZoomEnabled() const

    Sets 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

    Gets/sets 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)

    Sets 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)

    Gets/Sets 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)

    Gets/sets the X and Y size of the points displayed. The size is expressed in pixels.

  • PointType GetPointType() const
  • void SetPointType(PointType Type)

    Gets/sets 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)

    Gets/sets 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)

    Gets/sets 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)

    Gets/sets 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)

    Gets/sets the horizontal or vertical mode.

  • COLORREF GetBorderColor() const
  • void SetBorderColor(COLORREF BorderColor)

    Gets/sets the bar border color.

  • int GetBorderWidth() const
  • void SetBorderWidth(int Width)

    Gets/sets the bar border width (in pixels).

  • int GetBarWidth() const
  • void SetBarWidth(int Width)

    Gets/sets the width of the bar (in pixels).

  • unsigned GetGroupId() const
  • void SetGroupId(unsigned GroupId))

    Gets/sets 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 gets/sets 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

    Gets/sets 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

    Gets/sets the axis logarithmic.

    Note: this function exists only for backward compatibility. You should use SetAxisType instead.

  • void SetAxisType(AxisType Type)
  • AxisType GetAxisType() const

    Sets 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

    Gets/sets 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)

    Gets/sets the minimum and maximum values of the axis.

  • double GetTickIncrement() const
  • void SetTickIncrement(bool bAuto, double Increment)

    Gets/sets 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)

    Sets the tick increment for a date/time axis or sets 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)

    Sets 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

    Sets/Gets 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

    Gets 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

    Gets 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)

    Gets/sets the axis title.

  • void SetFont(int nPointSize,const TChartString& strFaceName)

    Sets 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)

    Sets 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

    Gets the number of strings in the title.

  • TChartString GetString(size_t Index) const

    Gets 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)

    Sets 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.

Collapse
// 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);

  • 08/05/2006: Release of version 1.0
  • 19/08/2006: Release of version 1.1
    • Bug fix in ScreenToValue function (CChartAxis)
    • Bug fix in RemoveAllSeries function (CChartCtrl)
    • Added support for manual zoom
    • Added support for mouse panning
    • Ability to specify a tick increment on the axis
    • Added support for resizing the control
  • 09/04/2007: Release of version 1.2
    • GDI leak corrected
    • Invisible series are not taken in account for auto axis and legend (thanks to jerminator-jp)
    • Ability to change the text color of the axis
    • Ability to change the color of the border of the drawing area
    • Surface series added
  • 16/02/2008: Release of version 1.3
    • Added date/time axis
    • Bug fix in how the logarithmic labels are displayed (trailing 0)
    • Ability to change the color of the zoom rectangle
    • Removed compiler warnings for VC2005
    • Bug fix in the zoom
  • 14/04/2008: Release of version 1.4
    • Added support for scrollbars
    • Bar series added
    • Legend can be docked on any side or floating
    • Suport for legend in horizontal mode
    • Support for transparent background on the legend
    • Support for shadow for several objects
    • RemovePointsFromBegin, RemovePointsFromEnd and AddPoints in the CChartSeries class
    • Support for gradient background
    • EnableRefresh and UndoPanZoom functions added in CChartCtrl
    • Possibility to enable/disable the zoom for a specific axis and to set its limit
    • Speed improvement on the series (min and max cached, ordering of the series)
    • Series can be removed using their pointers
    • Bug fix for invisible series in the legend
    • Bug fix for logarithmic axis (1 digit was not displayed)
    • Bug fix when removing series from the control
    • Bug fix if the pen width is bigger than 1 for line series
    • Bug fix for automatic axis
  • 20/08/2008: Release of version 1.5
    • Added support for UNICODE
    • Added support for printing
    • Auto-hide scrollbars
    • Baseline selection for bar series.
    • Performance patch
    • Scrollbar flickering removed (see )
    • Bug fix: scrollbar is now updated when axis is panned
    • Bug fix: calling AddPoint was not drawing the new point
    • Bug fix: tick labels for log axis were not always correct (rounding error)
    • Bug fix: last point of ChartPointSerie was not displayed
    • Bug fix: moving the mouse outside the control doesn't stop the zoom or pan operation (the button can be released outside the control)

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.

  • (used in the demo application)

License

This article, along with any associated source code and files, is licensed under

阅读(5779) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~