Introduction

Just recently, I was given a task: "Create a report with a chart." Sounds
simple, right? That was what I though too, at first. My first reaction was to
use a 3rd party plug-in of some sort, such as Crystal Report. "Sorry, we don't
have budget to use a third party item which requires royalty or additional fee."
All righty then, how about exporting the data to an excel template? "Sorry,
exporting a 10x30000 spread sheet on a Pentium 2-300 would take about an hour
before printing." How about I code the report onto the printer's device context?
"Great! We'll need that in 3 days. And make sure it has some flexibility for us
do some custom configuration and filtering"

*Gasp* Okay, this doesn't leave me with too many choices, so I looked into
the ActiveX component, MsChart. I've seen postings of people talking about
MsChart in VC++ forums, but they were mostly questions without answers. This
lead me to believe that it might not be a very good component. Furthermore, I've
never been a very big far for ActiveX. Frankly, I find ActiveX pretty ugly; Just
another nightmare for C++ coders like other COM objects. Usually, I am pretty
good at avoiding ActiveX when I can, but this time I'm cornered. Searching my
favorite VC++ forums came up either empty or unanswered questions when I entered
"print + MsChart". Oh boy, this is going to take me forever to figure out
myself, right?

Not really. Surprisingly, it only took 5 hours of my Saturday afternoon.

Getting Started

I have to admit, MsChart isn't as difficult to use as I though. Actually, it
is fairly easy to incorporate it into your project or report.

First thing you must do is add the MsChart Component into your project. For
this, you can refer to JL Colson's article Passing an Array of
Values to the Visual C++ MSChart OCX. It's a really nice article to get you
started with adding the chart control. Either that, or you can can try to
compile the sample source code. However, you might have to run the .reg file
enclosed in the zip file so that everything that must be in the registry is
there. The only thing you must make sure is that MsChart must reside in a form,
so it's easier to create a SDI project with a CFormView as your
view base.

How to Print MsChart

Alright. Now let's get down to the code. First thing you would need to do is
go into your resource's toolbar and change the printer icon from
ID_FILE_PRINT to ID_FILE_PRINT_PREVIEW. This makes it
easier for us to access the print preview without always having to go to the
File Menu. Next, use the ClassWizard and add OnPrint to your
CFormView.

In the header of your view class (i.e. PrintMyChart.h) add this
private member:

protected:
HBITMAP m_hbitmap;

Also be sure to use the ClassWizard to add a member variable
m_chart to your MsChart component.

The actual logic to print the chart is actually quite simple. First, you tell
the chart component to copy itself into the clipboard using
m_chart.EditCopy(). Once it is in memory, create a DC and past the
clipboard bitmap onto it and then transfer it to the printer's DC
(pDC). Now, go to your view class and edit the two functions as
shown below.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

Victor Porter is a software engineer who is in Taiwan learning martial arts in his virtually little free time. He also enjoys playing golf occasionally at 5:30 in the morning by sacrificing his dearly needed sleep. He is constantly racking his brains trying to decided if his next project should use his near-decade-experienced-C++ or his near-half-year-C# skills. An American from Pennsylvania, he is currently living in Taipei, Taiwan with his wife and lovely 6 months old daughter, Christine.

I would like to copy one CMSChart into another CMSChart which is created dynamically. I attempt to do so and I get an error... I would like to copy one CMSChart into a very large CMSChart. Then when I get the HBITMAP from the very large CMSChart it will look really good when it is printed out.

I am using the CMSChart inside a dll, inside a template class, inside a private function....I dont want this chart to be visible because I just want it to hold the data.

<pre>CMSChart MSChart;<br />
if(!MSChart.Create("MSChart",WS_CHILD,rectPage,m_pMSChart->GetParent(),10))<br />
{<br />
//-rectPage is the rectangle of the page the<br />// chart is to be printed on. <br />//-m_pMSChart is a pointer to the chart <br />// which is displayed on the screen.<br />//<br />// Error;<br />
}</pre>

Since error is ambiguous call to overloaded function, why don't you try calling CreateControl directly instead of the wrapped Create function and see if it works?
Look at your main IDispatch Wrapper for MSChart OCX

I run the example code,preview the mschart...runs ok...
then i minimize the preview's window,and copy/paste some others code ...restore the
preview's window...i find the preview window's graph dispears...HBITMAP'S handle not exit ---bcz i do other paste/copy operation...
How to prevent this?

I found the solutions:
To Get the pic Data of m_pMSChart->EditCopy(),you must call <big>GetClipboardData(CF_DIB)</big> instead of GetClipboardData(CF_BITMAP).
then copy the DIB HANDLE'S DATA TO ANOTHER HANDLE...use the new handle's data as printout

The much better way to print MSChart control (and any other ActiveX control) is to use IViewObject interface to draw the control directly to printer device context (as has been suggested by Andrew Wirger (http://www.codeproject.com/com/WirgerPrintArticle.asp[^]). Below is the code that I used to get a bitmap from MSChart control:

This is nice and all in that it works, but isn't it poor form to use the clipboard this way? I was under the impression that the clipboard was for moving data between applications, and if you're using it within an application, find another way.

Problem is, I'm too stupid to find that other way, so I guess I should stop pointing out the issues with others' stuff. But I am curious if anyone knows of another way to perform this without using the clipboard.

hello,
This way of printing that was working on Win98 and Win2k is aborting on WinXP ... but I have not investigated yet.
Which OS are you using ?
Is it just printing a blank page ?
Is it printing a page with all but the chart ?
Is it aborting ?
As said before, I also met a problem to print the chart and my problem was solved by upgrading the printer driver ...
Not easy to find such a problem ....

In fact, my whole application is based on the dialog class and my MsChart is also in a dialog window.
I have no File menu so no print ou print preview, but I would like to have a simple button beside my chart that I could click on to send my chart on a printer.
What would be the code to allow this ?
I guess that a big part of code written above is still good, but I guess I should replace the DoPreparePrinting(pInfo), the OnPreparePrinting(CPrintInfo* pInfo), in fact all CView class member by something else, but what ?
Help would be very appreciated.
Regqrds
DD