This article demonstrates the use of Windows GDI in the creation and animation of different types of 2D charts (bars, lines and pies). With this article is also included a demo-project and a source with all needed classes to implement charting in Win32 applications.
A background of this can be found in various flash-chart projects and commercial software available on the Internet. My goal is to try to come as much closer as possible to existing Flash solutions in 2D charting using just Windows GDI (and no OpenGL rendering). That is why this solution is suitable for applications that would like to present graphical data in a dynamic way with the possibility of real-time data rendering. This solution is also built to run fast and reliable using minimum CPU time.
Using the code
To use the presented code, you will need to download just Source.zip file and extract the source files to your project application. Then, include headers and you can start creating and editing charts. You can also download a demo-project to see in one place all the available chart types and animations.
Creating 2D animated charts
First, I will explain the structure of presented solution. The base class is
CGraphObject providing functionality for creating different chart types and animations, and also for changing some default chart object properties. This class is derived from
CWnd and it is actually the window of the chart object. So, you will need to provide an ID for this object. Follow the example in creating this object:
m_pGraphObject1 = new CGraphObject();
m_pGraphObject1->Create( NULL, NULL, NULL,
CRect(40,20,240,220), this, ID_OBJECT_GRAPH_1, NULL );
I have limited the minimum size of the chart window because I don't see the reason in creating a chart window smaller than 200x200 pixels if you like to see or read something at all, but you are free to change this in the constructor of the
Then, you will need to decide what chart type you need and when you do, create the chart of the specified type, like this:
m_pGraphObject1->CreateGraph( GT_2DPIE );
Possible chart types are: 2D pie chart (
GT_2DPIE), 2D bar chart (
GT_2DBAR) and 2D line chart (
The next step depends on the chart type you have chosen to work with. In this article, I will presume you will work with the 2D pie chart graph object. So, next you will need to add segments to the pie chart. You don't need to worry about the segments percent. You can add segments as long as you like but when you reach to 100%, all segments you try to add will not be added (unless you change this, I wouldn't). To add segments to the pie chart, do the following:
m_pGraphObject1->Add2DPieGraphSegment( 40, RGB(255,0,0), "Seg_1" );
m_pGraphObject1->Add2DPieGraphSegment( 25, RGB(0,255,0), "Seg_2" );
m_pGraphObject1->Add2DPieGraphSegment( 15, RGB(0,0,255), "Seg_3" );
The first argument is the percent segment we will have in the resulting pie on the screen. The second is the color of the segment, and the third is the segment text that will be shown in the pie chart's legend.
After you finish adding pie chart segments, you should decide if you would like the chart to be animated on the screen or not. Follow the code:
m_pGraphObject1->SetGraphAnimation( TRUE, AT_PIE_DRAW );
First argument says if it will be animated or it not. If chart is not animated then the second argument is not important, but if the chart is going to be animated on the screen, then this argument can also have values that depend on the chart type you have chosen to work with. Since I am explaining here work with 2D pie chart, this argument can have the following values: 2D pie chart draw animation (
AT_PIE_DRAW) and 2D pie chart blend animation (
That is it! Your chart is now fully functional.
When you finish working with
CGraphObject object, you must destroy it in the following manner:
Changing default chart properties
Now, when you see your chart on the screen, you can think it isn't so much. It isn't much with default chart settings because these settings are there just to enable the chart's main function which is data representation and, maybe, animation. There are many chart properties you can modify, like:
- chart title text
- chart subtitle text
- chart title text color
- chart subtitle text color
- chart title text shadow (show or hide)
- chart subtitle text shadow (show or hide)
- chart background style (solid or gradient)
- chart background color
- chart background gradient style (vertical or horizontal)
- chart label text color
- chart legend (show or hide)
- chart legend background color
- chart legend text color
- chart size
- chart position
- chart animation type
Altering these properties, you can get results (I hope even better) shown in preview pictures.
Chart design considerations
Here, I will just explain some possible chart design considerations that can help your charts look better.
The first thing is that everything depends on the quantity of data and the type of the data you would like to show in your chart. If you are working with data you would like to see in comparison with some other data on the same chart, then you must use either 2D bar or 2D line chart types (since pie chart doesn't have a possibility to work with data in series).
If you find that your number of series is equal or smaller then the number of segments, then I suggest you use charts that have width and height the same. This will improve the chart's appearance, no matter what the chart's size is.
If you want to speed-up the chart's animation, you will need to change the
ANIMATION_TIME identifier that can be found in the header file of the
CGraphObject class. Be careful decreasing this value since it is a Windows timer resource that is created each time you create an animated chart object. This could possible be a threat if you have too many charts in your application. This demo works fine with all 12 charts and default animation timings. Speeding-up charts animation costs more CPU time but looks better.
You may find it useful to change default
Create() method. If you would like to move your chart windows on the screen then alter parameters passed in this function to
Create() method. Your charts can have the windows attributes all windows have.
Watch the text length you pass to the chart title or subtitle, labels or legend text. This solution contains no text-wrapping methods, so too long text strings can look ugly. Anyway, text on charts is used to mark data specific attributes (quantity, kind or something else).
All positioning and sizing inside the chart is done according to relative calculations, based on the chart's size and position. So, if you find you can improve your chart's appearance by changing these values, please do so.
At the end, you are free to modify everything you find in these solutions and accommodate them to your needs. It might be easy to combine different types of animation and get totally new ones, but it is a thing to experiment.
Points of Interest
I am interested in continuing the work on these charts but next time in 3D space, I hope. That will require using fast 3D rendering device and one possible solution might be employing OpenGL.