Introduction
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.
Background
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:
// First call the constructor
m_pGraphObject1 = new CGraphObject();
// Then initialize m_pGraphObject1 object
// (or however you name it, in your project)
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 CGraphObject
class.
Then, you will need to
decide what chart type you need and when you do, create
the chart of the
specified type, like this:
// Create chart of the specified type
m_pGraphObject1->CreateGraph( GT_2DPIE );
Possible chart types
are: 2D pie chart (GT_2DPIE
),
2D bar chart (GT_2DBAR
)
and 2D line chart (GT_2DLINE
).
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:
// Add 2D pie chart segment
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:
// Set 2D pie chart animation
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 (AT_PIE_BLEND
).
That is it! Your chart
is now fully functional.
When you finish working
with CGraphObject
object, you must destroy
it in the following manner:
//Destroy graph object
m_pGraphObject1->DestroyWindow();
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 CGraphObject
class Create()
method. If you would like to move your chart windows on
the screen then alter parameters passed in this function
to CWnd
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.