ChartDirector 6.0 (C++ Edition)

Using ChartDirector with MFC


This section describes how to use ChartDirector with MFC on Windows.

MFC Sample Programs

ChartDirector comes with a number of MFC sample programs in the "ChartDirector/mfcdemo" subdirectory. If you are using Visual Studio, you may open the solution file "mfcdemo.sln", and it will open the Visual Studio solution with the sample projects.

Note: The Visual Studio project files for the sample programs are based on Visual Studio 2005. If you are using later versions of Visual Studio, it may prompt you to convert them to match the Visual Studio version. Please proceed to convert them. If you are using earlier versions of Visual Studio, you may need to recreate the project files in order to compile the sample code.

Project NameDescription
helloworldThe "Hello World" example of using ChartDirector with MFC. This is a basic MFC project displaying a simple bar chart.
mfcdemoThe main MFC sample program, containing a chart browser for browsing over 200 charting subroutines, producing over 400 charts of various types.
financedemoAn interactive financial chart will comprehensive technical indicators support.
tracklegendDemonstrates a sweep line track cursor with dynamic legend entries for the data points at the cursor position.
tracklabelDemonstrates a sweep line track cursor with dynamic labels for the data points at the cursor position.
trackaxisDemonstrates a sweep line track cursor with dynamic axis labels for the data points at the cursor position.
trackboxDemonstrates a track rectangle and a floating legend box for the data points in the rectangle.
trackfinanceA finance chart with a sweep line track cursor and dynamic legend entries for the price and technical indicator values at the cursor position.
crosshairDemonstrates a crosshair cursor with dynamic axis labels showing the position of the cursor.
simplezoomscrollA simple zoomable and scrollable chart that uses mouse click and drag to control zooming and scrolling.
zoomscrolltrackDemonstrates using mouse click and drag, mouse wheel, and a scrollbar to control zooming and scrolling. There is also a sweep line track cursor that displays dynamic legend entries.
zoomscrolltrack2Demonstrates using mouse click and drag, mouse wheel, and a scrollbar to control zooming and scrolling. The axis range can also be set using date picker controls, and there is also a sweep line track cursor that displays dynamic data labels.
viewportcontroldemoDemonstrates using the ChartDirector viewport control to control zooming and scrolling. Other methods to control zooming and scrolling, such as using mouse click and drag and mouse wheel, are also included. There is also a sweep line track cursor, and a save button to save the chart as PDF, SVG, PNG, JPG, GIF or BMP.
xyzoomscrollDemonstrates using mouse click and drag, mouse wheel, a slider, and the ChartDirector viewport control to control zooming and scrolling both horizontally and vertically. There is also a crosshair cursor with axis labels, pop up tooltips over the data points, and a save button to save the chart as PDF, SVG, PNG, JPG, GIF or BMP.
realtimedemoA simple realtime chart with configurable update rate from 250ms to 2 sec.
realtimetrackA realtime chart with configurable update rate and a sweep line track cursor that displays dynamic legend entries.
realtimezoomscrollA realtime chart that is zoomable and scrollable, and with configurable update rate and a sweep line track cursor that displays dynamic legend entries. There is also a save button to save the chart as PDF, SVG, PNG, JPG, GIF or BMP.

To try a sample program, simply set the corresponding project as the "StartUp Project", then compile and run the program.

It is recommended you start with the helloworld project and then the mfcdemo project. The mfcdemo project demonstrates over 200 sample charting subroutine which produce over 400 charts of various types. The charting code are from simple to sophisticated, and are designed for use as tutorials.

The CChartViewer MFC Control

All ChartDirector MFC sample programs uses the CChartViewer control to display charts and handle mouse interactions. The CChartViewer is a derived class of the MFC CStatic control. It is released in source code format.

To use CChartViewer in your own project:

Displaying Charts On Screen

To display a chart using CChartViewer, only one line of code is needed:

     // m_ChartViewer is a CChartViewer control; myChart is a BaseChart pointer
     m_ChartViewer.setChart(myChart);

Handling Hot Spots Mouse Interactions

Hot spots are special regions in on the chart that are usually used to represent chart objects, such as data representation objects (sectors for pie chart, bars for bar charts, etc). One can display tool tips when the mouse is over the hot spots, and/or to make the hot spots clickable with mouse cursor feedback.

In ChartDirector, hot spots for the charts are defined using standard HTML image maps (text strings containing HTML tags). The BaseChart.getHTMLImageMap method can be used to generate image maps automatically for a chart. To set the image map to the CChartViewer control, one may use:

     m_ChartViewer.setImageMap(myImageMap);

After setting the image map, the CChartViewer control will display the tool tips defined in the image map when the mouse is over the hot spots. For clickable hot spots, it will also change the mouse cursor into a "hand" shape.

When the mouse clicks on the CChartViewer control, a BN_CLICKED notification code will be sent to the parent container. The parent container can handle this message and use ImageMapHandler to determine which hot spot has been clicked.

Microsoft MFC documentation contains the details on how to handle BN_CLICKED notification code. In brief, the steps are:

Adding Track Cursor to the Chart

In ChartDirector, track cursors can be created by drawing them on a "dynamic layer" when the mouse moves on the chart. For example, drawing a horizontal line and a vertical line will create a crosshair cursor that tracks the mouse. Other things, such as legend entries, data labels and axis labels, can also be drawn, allowing them to update as the mouse moves over the chart.

CChartViewer will send CVN_MouseMovePlotArea notification codes to the parent container when the mouse moves over the extended plot area. The track cursor drawing code can be implemented in the handler of this message.

Handling View Port Interactions

A view port can be imagined as a window to an underlying surface. For example, a data series with 10 years of data can be imagined as a long surface. If only 1 year of data is displayed, we may consider this as the view port showing 10% of the underlying surface.

Scrolling can be handled as moving the view port, while zooming in and out can be handled as changing the view port size.

CChartViewer supports using mouse click and drag to control the view port (see CChartViewer.setMouseUsage). When the view port is changed by mouse actions, CChartViewer will send a CVN_ViewPortChanged notification code to its parent container. The parent can handle this message and redraw the chart to reflect the updated view port.

CChartViewer also includes methods for changing the view port programmatically. This allows external controls (such as scroll bars, mouse wheel, sliders, date picker, etc) to manipulate the view port.

Microsoft MFC documentation contains the details on how to handle the control notification messages. In brief, the steps are:

The CViewPortControl

The CViewPortControl is a MFC control introduced in ChartDirector 6.0. It allows user to visualize and control the CChartViewer viewport.

In typical usage, the CViewPortControl will display an "overall chart" that shows the full data range. Once the CViewPortControl is associated with the CChartViewer, it will draw a rectangle on the overall chart to represent the CChartViewer viewport, and dim out the region outside the rectangle. If the viewport changed, such as if the user zooms in the chart, the rectangle will automatically update.

The user can drag the rectangle to move the CChartViewer viewport (equivalent to scrolling). The user can also resize the viewport by dragging the border of the rectangle (equivalent to zooming), or drag a new rectangular region on the overall chart to be used as the new viewport, or click on a point on the chart to center the viewport at that point. In all these cases, as the viewport has changed, the CVN_ViewPortChanged message will be sent.

The steps to use CViewPortControl in your own project is similar to that of CChartViewer:

The CViewPortControl requires an "overall chart" on which the viewport rectangle is drawn. It also requires connection to a CChartViewer so as to visualize and control its viewport. The code to do this is:

    // m_ViewPortControl is a CViewPortControl; myOverallChart is a BaseChart pointer
    m_ViewPortControl.setChart(myOverallChart);

    // m_ChartViewer is the CChartViewer to be associated with the CViewPortControl
    m_ViewPortControl.setViewer(&m_ChartViewer);

Saving the Charts

ChartDirector can output the charts in PDF, SVG, PNG, JPG, GIF and BMP format to a file using BaseChart.makeChart, or to memory using BaseChart.makeChart2. For example, to save the chart in a CChartViewer to a file, the code is:

    // m_ChartViewer is a CChartViewer object which contains the chart to save. The
    // format is determined by the file extension in pathname.
    m_ChartViewer.getChart()->makeChart(pathname);

Printing Charts On Paper

ChartDirector can output charts in BMP or DIB (Device Independent Bitmap) format in memory. The easiest method to print the chart is to blit the DIB directly to the printer device context. For example:

    // Output the chart as BMP
    MemBlock bmp = c->makeChart(Chart::BMP);

    // The BITMAPINFOHEADER is 14 bytes offset from the beginning
    LPBITMAPINFO header = (LPBITMAPINFO)(bmp.data + 14);

    // The bitmap data
    LPBYTE bitData = (LPBYTE)(bmp.data) +
        ((LPBITMAPFILEHEADER)(bmp.data))->bfOffBits;

    // The scaling factor to adjust for printer resolution
    // (pDC = CDC pointer representing the printer device context)
    double xScaleFactor = pDC->GetDeviceCaps(LOGPIXELSX) / 96.0;
    double yScaleFactor = pDC->GetDeviceCaps(LOGPIXELSY) / 96.0;

    // Output to device context
    StretchDIBits(pDC->m_hDC, (int)(40 * xScaleFactor), (int)(40 * yScaleFactor),
                  (int)(header->bmiHeader.biWidth * xScaleFactor),
                  (int)(header->bmiHeader.biHeight * yScaleFactor),
                  0, 0, header->bmiHeader.biWidth, header->bmiHeader.biHeight,
                  bitData, header, DIB_RGB_COLORS, SRCCOPY);