Printing Text (&etc) along with Chart

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
Paul
Newbie
Newbie
Posts: 20
Joined: Tue Mar 01, 2005 5:00 am

Printing Text (&etc) along with Chart

Post by Paul » Thu Aug 04, 2005 4:29 pm

Has anyone had any experience with printing additional text/graphics/etc along with TChart? I can get the text to appear in the previewer, but it never actually prints. I've tried this with several PC's and printers, all the same. The chart prints, but nothing else.

Can anyone help with this?

Thanks

Paul

Pep
Site Admin
Site Admin
Posts: 3295
Joined: Fri Nov 14, 2003 5:00 am
Contact:

Post by Pep » Fri Aug 05, 2005 1:35 am

Hi Paul,
This is as designed. The problem is all custom positioned object (legend,
text, series marks) use screen pixels coordinates. While this is fine for
screen it does not work for printer. Why ? The reason for this is if you
print, TeeChart will internally change chart size (so that it fits in
specified printer.Canvas region). The result is Chart size will change but
the custom positioned items "positions" on printer canvas will remain the
same (in screen pixel coordinates). This will result in custom items being
drawn at wrong place.
The solutions:

+ To print, use the following code:

var tmpMeta: TMetaFile;
begin
tmpMeta := Chart1.TeeCreateMetafile(true,Chart1.ClientRect);
try
Printer.BeginDoc;
try
Printer.Canvas.StretchDraw(custom_printer_rect_region,tmpMeta);
finally
Printer.EndDoc;
end;
finally
tmpMeta.Free;
end;

Basically you're creating a metafile with the same size as original chart.
The consequence of this is custom positions will be valid for metafile as
well. Then you use StretchDraw method to "paint" this image (with correct
custom items positions) directly onto Printer.Canvas.

+ If possible try using "axis" scale coordinate for mark position position.

Basically, set (an example) custom item position to x=1.0, y=5.2 and then
use Chart1.BottomAxis.CalcPosValue(x), Chart1.LeftAxis.CalcPosValue(y) to
calculate current "screen" or "printer" canvas pixel position (you'll also
have to define an array where you'll store all positions, expressed in axis
values). Now you're defining marks positions in axis scale and using
CalcPosValue method to convert it to screen pixel coordinate. The advantage
of this method is you can use TChartPreviewer and existing print methods.

Paul
Newbie
Newbie
Posts: 20
Joined: Tue Mar 01, 2005 5:00 am

Post by Paul » Fri Aug 05, 2005 12:57 pm

Hello -

Yes, I understand the problem with screen versus printer coordinates. I guess I just assumed that when it's advertized in "All Features" the ability to place text on the paper in the print previewer, it would actually print. It seems reasonable that the writers of TChart would have resolved the translation problem.

Actually, what is happening is not that the objects get printed in the wrong place or at the wrong size (I specifically looked for that situation), but rather they don't print *at all*.

Thanks for your help.

Paul

Pep
Site Admin
Site Admin
Posts: 3295
Joined: Fri Nov 14, 2003 5:00 am
Contact:

Post by Pep » Fri Aug 05, 2005 2:01 pm

Hi Paul,

whops..in that case, could you please send me a simple example with which I can reproduce the problem as is here ?
Send me it directly to pep@steema.com

Betaversion
Newbie
Newbie
Posts: 1
Joined: Fri Nov 15, 2002 12:00 am
Location: Germany
Contact:

Post by Betaversion » Mon Aug 15, 2005 10:45 am

Hello,

how do I compute the values for 'custom_printer_rect_region'? I don't really get this.

Thanks!
Mike aka Betaversion

leaf
Newbie
Newbie
Posts: 37
Joined: Fri Nov 15, 2002 12:00 am

Post by leaf » Wed Aug 17, 2005 2:24 pm

Pep,

Were you able to reproduce and solve this issue? I am having the same problem. I am placing annotation text next to chart that does not get printed at all. Thanks

Pep
Site Admin
Site Admin
Posts: 3295
Joined: Fri Nov 14, 2003 5:00 am
Contact:

Post by Pep » Thu Aug 18, 2005 7:43 am

Hi leaf,

have you tried the solutions I posted on this post ? I've also posted a txt file into the news://www.steema.net/steema.public.attachments newsgroup (RE: Printing Better) which contains a detailed explanation about the use of TeeChart and the Printers. Could you please take a look at it ?

leaf
Newbie
Newbie
Posts: 37
Joined: Fri Nov 15, 2002 12:00 am

Post by leaf » Sun Aug 28, 2005 4:59 pm

This is still a problem for me.

I want to go to the link you provided and try your solution but I am unable to get there. Is ther another way other than the link you provided? How do I display your solution?

Thanks

PvdE
Newbie
Newbie
Posts: 13
Joined: Tue Aug 16, 2005 4:00 am
Location: Washington, DC

Post by PvdE » Sat Sep 03, 2005 5:17 pm

I wrote the following code to print on the default printer using a margin and print my chart proportional as large as possible. I appreciate any feedback (like this is in the library already etc.)
--Paul

Code: Select all

procedure TChartFrame.Print1Click(Sender: TObject);
var
   tmpMeta: TMetaFile;
const
   Margin = 0.5;   //margins in inches
var
   PPIX     ,
   PPIY     : integer; //printer pixels per inch
   OffSetX  ,          //margins
   OffSetY  : integer;
   SizeX    : integer; //size for printer image
   SizeY    : integer;
   PrMaxX   ,          //maximum for printer image
   PrMaxY   : integer;
   Mult     : double;
   ChartX   ,          //size of screen image
   ChartY   : integer;
begin
//Chart1.Print;  //does not print text boxes etc
tmpMeta := Chart1.TeeCreateMetafile(true,Chart1.ClientRect);
ChartX := (Chart1.ClientRect.Right - Chart1.ClientRect.Left);
ChartY := (Chart1.ClientRect.Bottom - Chart1.ClientRect.Top);

Printer.PrinterIndex := -1;  //default printer

   try
   Printer.BeginDoc;

   PPIX := GetDeviceCaps(Printer.Handle, LOGPIXELSX);
   PPIY := GetDeviceCaps(Printer.Handle, LOGPIXELSY);

   OffSetX := Round(Margin * PPIX);
   OffSetY := Round(Margin * PPIY);

   PrMaxX := Printer.PageWidth - 2 * OffSetX;
   PrMaxY := Printer.PageHeight - 2 * OffSetY;

   SizeX := PrMaxX;
   Mult := prMaxX / ChartX / PPIX;
   SizeY := Round(ChartY * Mult * PPIY);

   if SizeY > PrMaxY
   then
      begin
      SizeY := PrMaxY;
      Mult := prMaxY / ChartY / PPIY;
      SizeX := Round(ChartX * Mult * PPIX);
      end;

      try
      Printer.Canvas.StretchDraw(Rect( OffSetX, OffSetY, OffSetX + SizeX, OffSetY + SizeY ), tmpMeta);
      finally
      Printer.EndDoc;
      end;
   finally
   tmpMeta.Free;
   end;
end;

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Tue Sep 06, 2005 7:37 am

Hi leaf,

To get to the attachments newsgroup you need a newsreader, set up a new news server being www.steema.net with all default settings and subscribe to steema.public.attachments newsgroup. Depending on your machine settings, clicking in the following link may also bring you directly to the newsgroups [url]news://www.steema.net/steema.public.attachments[/url]

In case you have any problem accessing to the newsgroups please let us know and we will send you the mentioned document.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Marc
Site Admin
Site Admin
Posts: 1266
Joined: Thu Oct 16, 2003 4:00 am
Location: Girona
Contact:

Post by Marc » Tue Sep 06, 2005 9:12 am

Hello,

To position Custom Canvas elements on a Chart (eg. such a Canvas.TextOut) then they should be done so relatively.

For example an item to be printed at the Bottom Axis at value 3 should use:

Code: Select all

m_Chart1.GetCanvas().TextOut(m_Chart1.GetAxis().GetBottom().CalcXPosValue(3),m_Chart1.GetAxis().GetBottom().GetPosition(),"Hello world");
The above codeline should be added in the OnAfterDraw or other Chart paint event or it will not appear on the Chart.

Regards,
Marc

Marc
Site Admin
Site Admin
Posts: 1266
Joined: Thu Oct 16, 2003 4:00 am
Location: Girona
Contact:

Post by Marc » Tue Sep 06, 2005 5:20 pm

Hello,

Whoops, syntax from the last post is from the AX version for custom element output. The principle is similar with the VCL version (ie. Chart1->BottomAxis->CalcXPosValue(3)).

With respect to Chart location on the printed page please remember the availability of the Chart PrintPartial and PrintPartialCanvas methods to output the Chart to a determined rectangle size/location.

Regards,
Marc Meumann
Steema Support

leaf
Newbie
Newbie
Posts: 37
Joined: Fri Nov 15, 2002 12:00 am

Post by leaf » Thu Sep 29, 2005 7:01 pm

OK, I have gotten a couple of print routines working. Now that I am able to print both the annotation and chart together, how can I call my print routine from the TChartPreviewer control? Your control does not print the text in the annotation tool.

Pep
Site Admin
Site Admin
Posts: 3295
Joined: Fri Nov 14, 2003 5:00 am
Contact:

Post by Pep » Mon Oct 03, 2005 10:48 am

Hi,

if you want to print the Chart with custom objects from a preview you should use the TPreviewPanel component and then print directly using similar code to the following :

Code: Select all

procedure TForm1.TeePreviewPanel1AfterDraw(Sender: TObject);
begin
  with TeePreviewPanel1,Canvas do
  begin
    Font.Color:=clRed;
    Font.Size:=12;
    TextOut(PaperRect.Left+10,PaperRect.Top+6,'Some text');
  end;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
var tmpMeta: TMetaFile;
OldColor : TColor;
begin
    Chart1.BevelOuter := bvNone;
    OldColor := Chart1.Color;
    Chart1.Color := clNone;
    tmpMeta := TeePreviewPanel1.TeeCreateMetafile(true,TeePreviewPanel1.ClientRect);
    try
        Printer.Orientation := poLandscape;
        Printer.BeginDoc;
        try
            Printer.Canvas.StretchDraw(Rect(1,1,Printer.PageWidth - 1,
Printer.PageHeight - 1),tmpMeta);
        finally
            Printer.EndDoc;
        end;
    finally
        tmpMeta.Free;
        Chart1.BevelOuter := bvRaised;
        Chart1.Color := OldColor;
    end;
end;
Using the TPreviewPanel component you can create your custom form Prevewer form.

Post Reply