ChartDirector 7.1 (C++ Edition)
Using ChartDirector with MFC
This section describes how to use ChartDirector with MFC on Windows.
MFC Sample Programs
ChartDirector comes with a lot of MFC examples. They are included in the Visual Studio solution at "ChartDirector/mfcdemo/mfcdemo.sln". The solution includes two projects:
- helloworld: This is a basic MFC project that just displays a simple bar chart.
- mfcdemo: This project includes all ChartDirector chart types. It demonstrates various advanced features such as tooltips with rich formatting, clickable chart objects, programmable track cursors, zooming and scrolling, realtime charts, contour cross section, 3D chart rotations, PDF reports and huge dataset support.
The CChartViewer MFC Control
All ChartDirector MFC sample programs uses the
CChartViewer control to display charts and handle user 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:
- Include "ChartViewer.h" and "ChartViewer.cpp" in your project.
- Use the VC++ Dialog Editor to put a "Picture Control" in your Form or Dialog. Set the "Type" to "Bitmap". Set a valid resource ID for the control.
- Add a member variable for the control (eg. right click on the control and select "Add variable"), and set the variable type to CChartViewer.
- Visual Studio should automatically add the following line in the header file of your Form or Dialog. You may open the header file to verify if this is the case.
#include "ChartViewer.h"
NOTE for Precompiled Header: When Visual Studio creates a new MFC projects, it usually configures the project to use precompiled headers. Depending on the Visual Studio version, the precompiled header can be called stdafx.h or pch.h. Visual Studio then requires all C++ files to include the precompiled header in its first line, otherwise it will produce error that the precompiled header is not included.
That means the CChartViewer.cpp must include the precompiled header. It currently uses #include "stdafx.h"
to include the precompiled header. If your project uses another precompiled header filename, you may need to change the #include statement to that filename.
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:
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 Viewport Interactions
A viewport 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 viewport showing 10% of the underlying surface.
Scrolling can be handled as moving the viewport, while zooming in and out can be handled as changing the viewport size.
CChartViewer supports using mouse click and drag to control the viewport (see
CChartViewer.setMouseUsage). When the viewport 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 viewport.
CChartViewer also includes methods for changing the viewport programmatically. This allows external controls (such as scroll bars, mouse wheel, sliders, date picker, etc) to manipulate the viewport.
Microsoft MFC documentation contains the details on how to handle the control notification messages. In brief, the steps are:
- Add an ON_CONTROL entry to the message map section of the Window. An example is as follows, in which IDC_ChartViewer is the resource ID of the CChartViewer control, and OnViewPortChanged is the event handling method.
ON_CONTROL(CVN_ViewPortChanged, IDC_ChartViewer, OnViewPortChanged)
- Declare the event handling method in the message map function section of the header file.
afx_msg void OnViewPortChanged();
- Add the implementation of the event handling method. For example:
void CMyDialog::OnViewPortChanged()
{
// Viewport may have changed
// - update other controls if necessary
// - redraw chart
}
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:
- Include "ChartViewer.h" and "ChartViewer.cpp" in your project.
- Use the VC++ Dialog Editor to put a "Picture Control" in your Form or Dialog. Set the "Type" to "Bitmap". Set a valid resource ID for the control.
- Add a member variable for the control (eg. right click on the control and select "Add variable"), and set the variable type to CViewPortControl.
- Visual Studio should automatically add the following line in the header file of your Form or Dialog. You may open the header file to verify if this is the case.
#include "ChartViewer.h"
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);
© 2023 Advanced Software Engineering Limited. All rights reserved.