Recent

Author Topic: Basic printing of form content.  (Read 1334 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 8504
Basic printing of form content.
« on: August 18, 2025, 05:25:14 pm »
I have a form containing a map viewer, a treeview and a couple of graphical panels.

As attached, I am able to dump a .png with no problems using the code below:

Code: Pascal  [Select][+][-]
  1. procedure TFormMain.MenuViewOutputAsPngClick(Sender: TObject);
  2.  
  3. var
  4.   defaultName: string;
  5.   png: TPortableNetworkGraphic;
  6.   everything: TRect;
  7.  
  8. begin
  9.  
  10. (* We want the default name to match what's currently on the status bar, if we  *)
  11. (* used the current time this might differ by a few seconds from what's being   *)
  12. (* displayed due to message backlog.                                            *)
  13.  
  14.   defaultName :=   StatusBar1.Panels[2].Text;
  15.   if Pos('.', defaultName) > 0 then
  16.     SetLength(defaultName, Pos('.', defaultName) - 1);
  17.   defaultName := DelChars(defaultName, '-');
  18.   defaultName := DelChars(defaultName, 'T');
  19.   defaultName := DelChars(defaultName, ':');
  20.  
  21. (* Capture the image to match, do this before faffing around trying to get the  *)
  22. (* name right in case it's an incident that needs to be recorded.               *)
  23.  
  24.   png := TPortableNetworkGraphic.Create;
  25.   try
  26.     everything.Top := 0;
  27.     everything.Left := 0;
  28.     everything.Bottom := Height - MainMenu1.Height - 2;
  29.     everything.Right := Width - 1;
  30.     png.Height := everything.Bottom + 1;
  31.     png.Width := everything.Right + 1;
  32.     png.Canvas.CopyRect(everything, Canvas, everything);
  33.     SaveDialog1.Filename := AirfieldShortname + '-' + defaultName;
  34.     SaveDialog1.DefaultExt := 'png';
  35.     SaveDialog1.InitialDir := UserHome();
  36.     if SaveDialog1.Execute then
  37.       png.SaveToFile(SaveDialog1.Filename)
  38.   finally
  39.     png.Free
  40.   end
  41. end { TFormMain.MenuViewOutputAsPngClick } ;
  42.  

Similar code works to the clipboard.

What do I have to do to instead send this to a printer? I've tried several variants of the code below:

Code: Pascal  [Select][+][-]
  1. procedure TFormMain.MenuViewPrintClick(Sender: TObject);
  2.  
  3. const
  4.   LEFTMARGIN = 100;
  5.   HEADLINE = 'I Printed My Very First Text On ';
  6. var
  7.   YPos, LineHeight, VerticalMargin: Integer;
  8.   SuccessString: String;
  9.  
  10. var
  11.   everything: TRect;
  12.  
  13.   workingBitmap: TBitMap;
  14.   fromLimits, toLimits: TRect;
  15.  
  16. begin
  17.  
  18. {
  19.  
  20. // This works.
  21.  
  22. // https://wiki.freepascal.org/Using_the_printer
  23.   if PrintDialog1.Execute() then begin // This works
  24.     with Printer do try
  25.       BeginDoc;
  26.       Canvas.Font.Name := 'Courier New';
  27.       Canvas.Font.Size := 10;
  28.       Canvas.Font.Color := clBlack;
  29.       LineHeight := Round(1.2 * Abs(Canvas.TextHeight('I')));
  30.       VerticalMargin := 4 * LineHeight;
  31.       // There we go
  32.       YPos := VerticalMargin;
  33.       SuccessString := HEADLINE + DateTimeToStr(Now);
  34.       Canvas.TextOut(LEFTMARGIN, YPos, SuccessString);
  35.     finally
  36.       EndDoc;
  37.     end;
  38.   end
  39. }
  40.  
  41. // The best I can get from either of the below is a blank page.
  42.  
  43.   workingBitMap := TBitMap.Create;
  44.   workingBitMap.Width := Width;
  45.   workingBitMap.Height := Height - MainMenu1.Height;
  46.   PaintTo(workingBitMap.Canvas, 0, 0);
  47.   fromLimits := Rect(0, 0, workingBitMap.Width, workingBitMap.Height);
  48.   toLimits := Rect(0, 0, Printer.PaperSize.Width, Printer.PaperSize.Height);
  49.   if PrintDialog1.Execute() then begin
  50.     Printer.BeginDoc;
  51.     Printer.Canvas.CopyRect(toLimits, workingBitMap.Canvas, fromLimits);
  52.     Printer.EndDoc;
  53.     workingBitMap.Free
  54.   end;
  55.  
  56. {
  57. // https://forum.lazarus.freepascal.org/index.php/topic,62651.msg473978.html#msg473978
  58.   if PrintDialog1.Execute() then begin // This doesn't work
  59.     Printer.BeginDoc;
  60.     try
  61.       everything.Top := 0;
  62.       everything.Left := 0;
  63.       everything.Bottom := Min(Printer.PageHeight, Height - MainMenu1.Height) - 2;
  64.       everything.Right := Min(Printer.PageWidth, Width) - 1;
  65.       Printer.Canvas.CopyRect(everything, Canvas, everything)
  66.     finally
  67.       Printer.EndDoc
  68.     end
  69.   end
  70. }
  71. end { TFormMain.MenuViewPrintClick } ;
  72.  

If nobody has any quick suggestions I'll drop this for the moment, since what I'm trying to focus on is generating a video for the airfield's "fly-in-" in three weeks time.

Lazarus 2.2.6, FPC 3.2.2, Linux with GTK2 on a KDE desktop (Debian 12), printer is a networked colour laser branded Dell which is generally trouble-free.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

wp

  • Hero Member
  • *****
  • Posts: 13213
Re: Basic printing of form content.
« Reply #1 on: August 18, 2025, 07:49:40 pm »
Why don't you just CopyRect the png that you successfully created in the 1st code to the printer's Canvas?

I am attaching a project which has a MapViewer and a button on a form, paints the form onto a bitmap and stretch-prints the bitmap to the printer such that it fits into the printable page width (raw page width minus page margins)

MarkMLl

  • Hero Member
  • *****
  • Posts: 8504
Re: Basic printing of form content.
« Reply #2 on: August 19, 2025, 10:27:54 am »
Why don't you just CopyRect the png that you successfully created in the 1st code to the printer's Canvas?

I am attaching a project which has a MapViewer and a button on a form, paints the form onto a bitmap and stretch-prints the bitmap to the printer such that it fits into the printable page width (raw page width minus page margins)

Using your standalone demo, the image is correctly transferred to the test.bmp file but does not appear on either the colour or the B&W printer; I do however get the two lines of text.

Same happens if I move your code into my program (which I've done, because I know from other forum postings etc. that you've put substantial work into the scaling etc. right).

If you have any immediate suggestions I'll try them in the interest of understanding what's going wrong, but otherwise I'll just disable the menu entry until I've moved the whole thing onto Lazarus v3 or even v4 (which won't be for at least another month).

Thanks for the help, which if nothing else has narrowed the problem down to Lazarus v2.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

wp

  • Hero Member
  • *****
  • Posts: 13213
Re: Basic printing of form content.
« Reply #3 on: August 19, 2025, 11:48:04 am »
For testing I had printed only to PDF, but now I switched to the "real" printer - perfect print-out, no issue. An issue with your printer driver? What happens when you print to PDF and/or a similar printer?

MarkMLl

  • Hero Member
  • *****
  • Posts: 8504
Re: Basic printing of form content.
« Reply #4 on: August 19, 2025, 12:21:43 pm »
For testing I had printed only to PDF, but now I switched to the "real" printer - perfect print-out, no issue. An issue with your printer driver? What happens when you print to PDF and/or a similar printer?

I've just installed Debian's printer-driver-cups-pdf, printing e.g. this page to a PDF works fine but your demo only outputs the two lines of text.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 8504
Re: Basic printing of form content.
« Reply #5 on: August 19, 2025, 12:37:56 pm »
I've just installed Debian's printer-driver-cups-pdf, printing e.g. this page to a PDF works fine but your demo only outputs the two lines of text.

It's specific to GTK2, possibly on LCL v2 (the Lazarus v3.0 I've got here has an internal error on GTK2, so I've not been able to test that combination yet). QT5 works.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018