Click here to Skip to main content
15,885,985 members
Articles / Desktop Programming / MFC
Article

CBarChart

Rate me:
Please Sign up or sign in to vote.
4.93/5 (70 votes)
13 Feb 2007CPOL5 min read 286.4K   14.2K   209   110
CBarChart is a simple MFC control derived from CWnd. It can load data from a table or a stored procedure using ODBC.

Sample Image - BarChart-Snapshot.jpg

Contents

Introduction

CBarChart is a simple MFC control derived from CWnd. It helps you develop your own charts quickly and print them easily.

Background

A few days ago, I needed to add a chart to a project. When completed, I thought to myself that it's not too bad, so I decided to share it with my workmates in Code Project, and here it is.

I did not have a lot of time to work on this control, so I had to keep it as simple as possible. My goals for creating this chart were as follows:

  • Development should not take more than two or three days.
  • The chart must be more attractive rather than accurate. Since users are not familiar with the application and even computers, I had to do my best to attract their attention.
  • It has to be easy to understand, not filled with a lot of data that mostly confuse new users.
  • It should be printable.
  • It should be reusable.

With all the above assumptions, I started what you see here. Enjoy and please help me with the invaluable notes, bugs reports, ideas, etc. that you think might improve the quality of this code.

Using the code

Creating chart

First we have to create a chart:

  1. Add BarChart.cpp and BarChart.h to your project.
  2. Add #include "BarChart.h" to the top of header file of class in which you want to add this chart.
  3. Add a membrt variable of type CBarChart.
  4. In your cpp file, use the Create method of the member variable to create a chart control.

C++
// Create a bar chart control
if (!m_chart.Create(
    rcBound,              // Bounding rectangle of the control
    this,                 // A pointer to the parent window to be shown on
    0 ))                  // ID of this control
    {
    // Error, can't create the chart
    }

If Create suceeds, it returns TRUE.

Title text and background color

You can use SetTitle or SetBKColor to add a title or change color of the background of control.

C++
m_chart.SetTitle("A test chart, displaying some dummy data...");
m_chart.SetBKColor(RGB(255, 255, 240));

Adding bars

Finally, to add bars to the chart, use AddBar method as follows:

C++
m_chart.AddBar(
1600.356,           // A value to be shown at the top of the bar
"Jan",              // A label under the bar chart
RGB(255,255,0));    // Color of the bar

Note that the control uses this color (last parameter of AddBar) to create a gradient for the bar, which in my humble opinion is more polished.

Grid, labels and tooltip

You can also decide whether to see grid lines, labels or values:

C++
m_chart.ShowGrid(m_bShowGrid, TRUE);            // Show/Hide grids
m_chart.ShowBarText(1, m_bShowText, TRUE);      // Show/Hide values(top)
m_chart.ShowLabel(m_bShowLabel, TRUE);          // Show/Hide labels(bottom)
m_chart.ShowTooltip(m_bShowTip);                // Activate/deactivate tooltips

Also note that the first parameter of ShowBarText is used to toggle between two states: 0 indicates show value of the bar at the top of it and 1 indicates show percentage regarding other values.

You can also change default behaviour of the grid. By default, the grid fills the chart background by crossed vertical and horizontal lines resulting in rectangles with 10 (device) unit width and height. To change this behavior, use SetGridLines member function.

C++
SetGridLines(
int nHorLineCount,      // Number of horizontal lines, 0 = ignore
int nVerLineCount,      // Number of vertical lines, 0 = ignore
BOOL bFixedSize,        // If TRUE, first 2 parameters will be ignored
int nFixedSize)         // A fixed value that defines distance between 2 lines,
                        // Will be used if previous parameter is set to TRUE

Scaling

The bar is able to scale itself if had been asked to, but quality drops suddenly since it uses StretchBlt. This decreases quality drastically. I hope you don't mind since I did not have enough time to redraw the whole chart to fit in to the screen.

C++
m_chart.SetAutoScale(m_bScale);         // Set chart to be auto scaled
// Reposition window, so it finds out the size to fit into
m_chart.SetWindowPos( 0, 0, 0,
rcClient.Width(),
rcClient.Height() , SWP_NOMOVE);
m_chart.Refresh();                      // Force the chart to redraw itself

// You might also need to override OnSize of the
// Parent to position the chart, so it is always at the size you like

Removing bars

You can use RemoveAt or RemoveAll to remove bars from the control for a specific zero based index or totally respectively.

C++
m_chart.RemoveAt(nRemIndex);    // Removes the item indexed nRemIndex.
                                // Index is zero based.
m_chart.RemoveAll();            // Removes all bars

Saving to a bitmap file

Call SaveToFile to save the chart as a bitmap file. Function accepts a CString member function that is set to empty by default. If this string is empty, function prompts for file path by displaying a FileSaveAs dialog box. This function returns False in case of failure. Use GetLastErrorMessage() member function to get a string describing reason for failure.

C++
// Save chart as a bitmap file
if (!m_chart.SaveToFile())
    {
    AfxMessageBox(m_chart.GetLastErrorMessage());
    };

It would be appreciated if someone checks out saving to bitmap code, to make sure there are no bugs.

Printing

Use Print function to print the chart.

Use this function with care: According to the article by Roger Allen: PrintingTricksAndTips if we are going to print a bitmap, it is better to use DIB's instead of DDB's. So this function takes a parameter of type boolean:bCompatible (default is false).

If you set the parameter to true, it means you asked the chart to use DIB's which is recommended. I just copy-pasted the code snippet that Mr. Roger Allen provided and created two copies of the Print one that uses StretchBlt directly, and one that uses the code mentioned to convert it to DIB.

To me both types of functions work fine. But unfortunately, I did not have enough time to check the printing process correctly. So it would be very kind of you to report any bugs you might find or any corrections. I'm not familiar enough with printing.

C++
m_chart.Print();        // Prints the whole chart fitted in the page.
// If you have a lot of bars, I recommend selecting landscape in the 
// print dialog box.

Connecting to database

CBarChart uses ODBC Version 3 to connect to the database.

To connect the chart to an ODBC data source, use one of the forms of ReadFromDatabase

SQL
// Use this form to call a stored procedure or a query and use 
// result set as chart input

ReadFromDatabase("DS Name", "Stored proc/Query Name", "List of all parameters",
         "Bars Color", "UserName", "Password"));

// Note that the query or stored procedure MUST have at least 2 columns,
// First column MUST be of type char with maximum length of 50 and
// Second a double. These columns will be used as input data for the chart.

Second form can be used to conect to a table

SQL
m_chart.ReadFromDatabase("DS Name", "Table name", "Filter",
"Laabel column name", "dValue column name",
Bars color , "username", "password");

Below is an example of a call to these functions

C++
if (!m_chart.ReadFromDatabase("CHTst", "SpChartGetSale", "1, 12",
                      RGB(0, 0, 0), "hamed", "hamed"))
    {
        AfxMessageBox(m_chart.GetLastDatabaseErrMessage());
    };
or
m_chart.ReadFromDatabase("CHTst", "Sales", "",
"Month", "SaleRate",
RGB(0, 0, 0) , "hamed", "hamed");

I added a sample access database file to the download list. You can add this to your 'system' or 'user' data sources in ODBC Administration tool in the control panel. Name it CHTst and press the 'FromDatabase' button on the sample application. What you see is a result set of a call to a stored procedure that is done with one line of code. Enjoy.

History

  • 2007/01/10
    • Version (Or perhaps first beta version).

  • 2007/01/11
    • Some scaling bugs fixed
    • Tooltips added.
    • Unsigned long double converted to double

  • 2007/01/15
    • Some functions changed.
    • Tooltip updated.
    • Some comments added.

  • 2007/01/24
    • Tooltips now behave much like real tooltips.
    • Database connections added.

  • 2007/01/26
    • Tooltip bug fixed.(it disappears as control loses capture.)

  • 2007/01/31
    • Some grid bugs fixed.

  • 2007/02/3
    • Save to bitmap added
    • Grid updated

Acknowledgements

  • Mr. Nishant S. for his article about creating gradients.
  • Mr. Chris Maunder for his nice article called MFC Grid, that helped me for printing.
  • Mr. Roger Allen for 'Printing tips and tricks from the trenches' article.
  • Mr. David Bennett and Mr. Chuck Wood in Visual C Unleashed book, for code snippets and help for ODBC database programming.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
BugGDI crash Pin
Drew Hernandez13-Nov-13 14:50
Drew Hernandez13-Nov-13 14:50 
GeneralRe: GDI crash Pin
Hamed Musavi14-Nov-13 8:29
Hamed Musavi14-Nov-13 8:29 
GeneralRe: GDI crash Pin
Drew Hernandez14-Nov-13 18:10
Drew Hernandez14-Nov-13 18:10 
GeneralRe: GDI crash Pin
Hamed Musavi15-Nov-13 7:28
Hamed Musavi15-Nov-13 7:28 
QuestionGarbled Problem Pin
lsmandrew30-Jul-13 22:36
lsmandrew30-Jul-13 22:36 
AnswerRe: Garbled Problem Pin
Hamed Musavi8-Aug-13 23:39
Hamed Musavi8-Aug-13 23:39 
QuestionHow to scroll it? Pin
PunkyVigoss14-Jun-12 22:59
PunkyVigoss14-Jun-12 22:59 
AnswerRe: How to scroll it? Pin
Hamed Musavi21-Jun-12 22:53
Hamed Musavi21-Jun-12 22:53 
GeneralRe: How to scroll it? Pin
PunkyVigoss24-Jun-12 15:12
PunkyVigoss24-Jun-12 15:12 
GeneralRe: How to scroll it? Pin
Hamed Musavi26-Jun-12 3:07
Hamed Musavi26-Jun-12 3:07 
GeneralRe: How to scroll it? Pin
PunkyVigoss26-Jun-12 15:16
PunkyVigoss26-Jun-12 15:16 
GeneralRe: How to scroll it? Pin
Hamed Musavi27-Jun-12 5:29
Hamed Musavi27-Jun-12 5:29 
GeneralMy vote of 4 Pin
OnBlackSabbath5-Jun-12 15:21
OnBlackSabbath5-Jun-12 15:21 
Questionif the value is negative,the bar cann't be drawed, I am new to vc,can you tell me how to realize it?Thank you ! Pin
Angela201227-Dec-11 0:56
Angela201227-Dec-11 0:56 
QuestionHas anyone managed to incorporate Horizontal Scrolling into this control? Pin
Member 345539810-Nov-10 13:36
Member 345539810-Nov-10 13:36 
AnswerRe: Has anyone managed to incorporate Horizontal Scrolling into this control? Pin
Member 345539812-Nov-10 1:47
Member 345539812-Nov-10 1:47 
Generaldoes it work on console project Pin
Ahmed Ismail Mohamed21-Oct-10 11:02
Ahmed Ismail Mohamed21-Oct-10 11:02 
QuestionHow can I use this class into SDI/MDI project ? Pin
mesajflaviu26-Sep-10 7:57
mesajflaviu26-Sep-10 7:57 
AnswerRe: How can I use this class into SDI/MDI project ? Pin
Hamed Musavi26-Sep-10 9:20
Hamed Musavi26-Sep-10 9:20 
GeneralInternational overtaken's not enough, do not support Chinese Pin
jianan1-Jun-10 22:36
jianan1-Jun-10 22:36 
Generalamazing just what i was looking for Pin
santu16-Apr-10 1:43
santu16-Apr-10 1:43 
GeneralRe: amazing just what i was looking for Pin
Hamed Musavi16-Apr-10 6:57
Hamed Musavi16-Apr-10 6:57 
Generalconnection with MySQL Pin
kip_chuko28-Mar-10 21:21
kip_chuko28-Mar-10 21:21 
GeneralRe: connection with MySQL Pin
Hamed Musavi29-Mar-10 6:31
Hamed Musavi29-Mar-10 6:31 
GeneralRe: connection with MySQL Pin
kip_chuko29-Mar-10 15:54
kip_chuko29-Mar-10 15:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.