|
Displaying charts run-time - no file generation before |
Posted by Guillermo Ganem on May-17-2011 00:52 |
|
I am using code::blocks 10.05 + ChartDirector 5.0 to generate pie-charts for a Windows 7 application. I copied a couple of ChartDirectors' examples and executed them successfully.
As far as I browsed, all examples set the charts' parameters and then call makeChart (filename). In my application, however, I will be collecting a number of variables run-time, and displaying one - or more - pie charts at a child window depending on results. I don't want to save the files unless the user specifically requests (in fact, I would like to give him an option to Save, Print or Copy-to-Clipboard for pasting on a Word/Excel report).
My questions are:
a) How can I simply display the charts without saving them before to an image file?
b) In case it's possible to copy the chart for pasting it into another document, do I need to prepare something before calling the chart-display function, or will that be handled entirely by Windows' services?
c) Same as before for printing the chart: will Windows handle that, or should I set something up prior to displaying the chart?
I am new to code::blocks, to ChartDirector and to Windows GUI (tiple play!), so probably missing some basic stuff... Please provide step-by-step answers if necessary.
Note: code::blocks offers compatibility with MS Visual C++, but I couldn't generate a project using MFC, which as far as I understand would be the best option for my project, since it's C++ & Windows platform. If there is some simple directive to run/use MFC/MS Visual C++ with code::blocks, let me know, otherwise I will look for ways to adapt to "basic" C++. If you provide instructions for MFC, same question apply, basically how can I display the chart without creating a file before.
Thanks in advance.
Regards,
G. Ganem |
Re: Displaying charts run-time - no file generation before |
Posted by Peter Kwan on May-17-2011 01:56 |
|
Hi Guillermo,
ChartDirector can create charts as files or in various standard formats in memory. Most GUI frameworks can support at least one of the standard formats. Because there is no standard GUI framework in C++, and there are dozens of GUI frameworks commonly in use, it is not practical for us to provide examples for all possible GUI frameworks. So we only provide examples for MFC and QT.
In brief, in both MFC and QT, we output the chart in DIB (device independent bitmap, sometimes also called BMP) format in memory using BaseChart::makeChart. It is like:
MemBlock m = c->makeChart(Chart::BMP);
In MFC, we use a Win32 function CreateDIBitmap to convert the DIB to a HBITMAP, and use the MFC CStatic control to display the HBITMAP.
In QT, the QPixmap::loadFromData can accept a DIB in memory to create a QPixmap object, which can then be displayed by various QT widgets.
The detail source code are included in the MFC and QT sample code included ChartDirector.
For your case, I suspect code::blocks would have some functions that can handle DIB/BMP in memory, and display them and print them, (in MFC, you can print a HBITMAP by using the printer device context.) and put them into the clipboard. For the clipboard, you can also use the Win32 SetClipboardData to paste a DIB or a HBITMAP to the clipboard.
Hope this can help.
Regards
Peter Kwan |
Re: Displaying charts run-time - no file generation before |
Posted by Guillermo Ganem on May-17-2011 13:08 |
|
Hi,
Thanks for the quick and precise reply.
As I am learning in parallel C++ and GUI (particularly Windows), I still have some doubts. However, I feel confident that the problem is now down to very specific issues.
I have the following class for handling BMP info, from a useful tutorial I will be using as a base for this part of the code. As you can see, it currently supports loading BMP images from files, by filling some headers. I think that if I create a function to read the same info from memory ("MemoryBMP"), GDIPaint will work transparently regardless of how I get the image:
class CRaster {
public:
int Width,Height; // Dimensions
int BPP; // Bits Per Pixel.
char * Raster; // Bits of the Image.
RGBQUAD * Palette; // RGB Palette for the image.
int BytesPerRow; // Row Width (in bytes).
BITMAPINFO * pbmi; // BITMAPINFO structure
// Member functions (defined later):
int LoadBMP (char * szFile);
int GDIPaint (HDC hdc,int x,int y);
//THIS IS THE FUNCTION I WOULD ADD
MemoryBMP (Piechart *c);
};
Problem is that I don't know where to get some of the variables. Following the code I have in mind for "MemoryBMP", please let me know how can I fill in the blanks (or comment if my approach is wrong).
int MemoryBMP (PieChart *c) {
// Function for a CRaster object, filling the data from a ChartDirector generated pie chart
// Assume global "MemBlock m", from previous answer by ChartDirector
Width = c->width; //From Pie Chart's structure
Height = c->height;
BPP = ??? // Where do I find this data?
m = c->makeChart (Chart::BMP); // See previous answer
Raster = m->data //Is this correct? Where do I get Raster data?
Palette = ??? // Where do I find this data?
BytesPerRow = ??? // Where do I find this data?
pbmi = ???? // Where do I find this data?
return 0; // or error code depending on "c" data...
};
Thanks in advance.
Regards,
G. Ganem |
Re: Displaying charts run-time - no file generation before |
Posted by Peter Kwan on May-17-2011 18:41 |
|
Hi Guillermo,
The output from BaseChart.makeChart is exactly the same as the BMP file, except it is in memory instead of in a file. In fact, if you use fwrite to save the memory to a file, it will be exactly the same as the BMP file. So if you already have the code that process the BMP file, you may modify it to process the memory block (just change the file access to memory access).
If you want to process the memory BMP differently for some reasons, you may refer to the BMP standard to see where are the information:
http://en.wikipedia.org/wiki/BMP_file_format
According to the BMP standard, the information you need should be at the following memory position. Chances are, you already have similar code in your LoadBMP. (Note: I have not tested the code myself.)
MemBlock m = c->makeChart (Chart::BMP);
struct tagBITMAPINFOHEADER *h = (struct tagBITMAPINFOHEADER *)(m.data + 14);
Width = h->biWidth;
Height = h->biHeight;
BPP = h->biBitCount;
Raster = (char *)(m.data + *(int *)(m.data + 10));
Palette = (RGBQUAD *)(m->data + 54);
BytesPerRow = (Width + 3) / 4 * 4;
pbmi = (BITMAPINFO *)h;
Hope this can help.
Regards
Peter Kwan |
Re: Displaying charts run-time - no file generation before |
Posted by Guillermo Ganem on May-17-2011 21:58 |
|
Hi Peter,
Thanks, that worked perfectly!
A minor note for anybody with a similar problem:
Make sure of correcting the following line:
Palette = (RGBQUAD *)(m.data + 54);
(instead of Palette = (RGBQUAD *)(m->data + 54); see below).
Regards,
G. Ganem
Peter Kwan wrote:
MemBlock m = c->makeChart (Chart::BMP);
struct tagBITMAPINFOHEADER *h = (struct tagBITMAPINFOHEADER *)(m.data + 14);
Width = h->biWidth;
Height = h->biHeight;
BPP = h->biBitCount;
Raster = (char *)(m.data + *(int *)(m.data + 10));
Palette = (RGBQUAD *)(m->data + 54);
BytesPerRow = (Width + 3) / 4 * 4;
pbmi = (BITMAPINFO *)h;
Hope this can help.
Regards
Peter Kwan
|
|