Recent

Author Topic: [SOLVED] Problem printing second document  (Read 2713 times)

fatmonk

  • Full Member
  • ***
  • Posts: 232
[SOLVED] Problem printing second document
« on: November 28, 2019, 06:31:33 pm »
I'm having trouble printing...

I'm printing a fairly complex page of text and boxes (derived from the values in various TEdits on a form) and the page prints perfectly first time.

However if I print the exact same page by clicking my print button a second time without changing any of the values on the form the page gets corrupted - usually with large blocks of colour added across the page.

I won't copy all off the printing code here as there is a lot of and it includes a lot of logic, but the main flow of my code is as follows:

Code: Pascal  [Select]
  1. procedure TMainForm.doPrint();
  2. const
  3.   LEFTMARGIN = 100;
  4.   TOPMARGIN = 100;
  5.   PADDING = 20;
  6. var
  7.   XPos, YPos, LineHeight, LineWidth, senderAddressLinesCounter, senderAddressPrintLinesCounter, heightOfSenderBox, RefBoxHeight: Int64;
  8.   LeftSectionLeft, SectionCenter, RightSectionRight, SectionTop, SectionBottom, QRleft, QRtop, QRright, QRbottom: Int64;
  9.   row: Integer;
  10.   QRcodePosition: TRect;
  11.   stringToAdd, loopString, aSenderString: String;
  12.   senderAddressPrintLines: array of String;
  13. begin
  14.  
  15.   with Printer do
  16.   try
  17.     try
  18.       PaperSize.PaperName:=PAPERSIZENAME;
  19.  
  20.       Orientation:=poLandscape;
  21.  
  22.       LeftSectionLeft:=LEFTMARGIN;
  23.       SectionTop:=TOPMARGIN;
  24.       RightSectionRight:=PageWidth - LeftSectionLeft;
  25.       SectionCenter:=Round((RightSectionRight-LeftSectionLeft)/2);
  26.       SectionBottom:=PageHeight-SectionTop;
  27.  
  28.  
  29.       BeginDoc;
  30.  
  31.       // Setup the basics
  32.       Canvas.Erase;
  33.       Canvas.Font.Name := 'Arial';
  34.       Canvas.Font.Orientation:=0;
  35.  
  36.       // Draw the boxes
  37.       with Canvas do
  38.       begin
  39.          Rectangle (LeftSectionLeft, SectionTop, SectionCenter, SectionBottom);
  40.          Rectangle (SectionCenter, SectionTop, RightSectionRight, SectionBottom);
  41.       end;
  42.  
  43.  
  44.  
  45. ... a couple of hundred lines of Canvas.TextOut() and Rectangle() commands with font parameter changes and various bits of positioning logic...
  46.  
  47.  
  48.     except
  49.       on E: EPrinter do ShowMessage('Printer Error: ' +  E.Message);
  50.       on E: Exception do showMessage('Unexpected error when printing.');
  51.     end;
  52.   finally
  53.     EndDoc;
  54.   end;
  55. end;
  56.  
  57.  

My initial guess was that something in the Canvas is not being cleared down properly when the first print finishes and so the second print runs amock over the original. So, I added the Canvas.Erase and also tried Canvas.Clear but this didn't resolve the issue either.

If I exit my application and restart it then it prints perfectly the first time again, and them corrupts in the same way the second time.

Is there something else I need to do to clear down the canvas (or printer?) properly?

Thanks,

FM
« Last Edit: December 06, 2019, 05:06:53 pm by fatmonk »

howardpc

  • Hero Member
  • *****
  • Posts: 3257
Re: Problem printing second document
« Reply #1 on: November 28, 2019, 06:49:08 pm »
Have you tried
Code: Pascal  [Select]
  1. Printer.Refresh;
?

fatmonk

  • Full Member
  • ***
  • Posts: 232
Re: Problem printing second document
« Reply #2 on: November 28, 2019, 06:52:29 pm »
Same thing still happening with Printer.Refresh, I'm afraid.

(Added as the first item in the with Printer do as follows:

Code: Pascal  [Select]
  1.   with Printer do
  2.   try
  3.     try
  4.       Refresh;
  5.       PaperSize.PaperName:=PAPERSIZENAME;
  6.  
  7.       Orientation:=poLandscape;
  8.  

-FM

jamie

  • Hero Member
  • *****
  • Posts: 2243
Re: Problem printing second document
« Reply #3 on: November 28, 2019, 07:06:36 pm »
at the start of the printing, make a copy of the font and brush in the canvas or maybe just a copy of the
canvas...

 When done with your long printing, restore the printer canvas back to its original settings.

 Also, the Erase method you are calling works with the ClipRect settings, so that also needs to be set to the correct size and enabled if you want to use that otherwise it you shouldn't be using it.. Use a FillRect instead.

 Hope that gives you some insight .. :D
Number 1 at blue screen app creations!

fatmonk

  • Full Member
  • ***
  • Posts: 232
Re: Problem printing second document
« Reply #4 on: November 29, 2019, 12:31:30 pm »
I resolved the issue by adding a Canvas.Create as folows:

Code: Pascal  [Select]
  1.   with Printer do
  2.   try
  3.     try
  4.       Canvas.Create;
  5.       Refresh;
  6.       PaperSize.PaperName:=PAPERSIZENAME;
  7.  
  8.  

Just hope this doesn't cause a memory leak because adding a Canvas.FreeInstance in the finally block causes a SIGSEGV crash.

-FM

jamie

  • Hero Member
  • *****
  • Posts: 2243
Re: Problem printing second document
« Reply #5 on: November 29, 2019, 04:27:40 pm »
Really?

 DId you run Heaptrc after that?

 Looks like leaks to me.

 I use the Printer canvas for printing many times and don't have issues.

Number 1 at blue screen app creations!

lucamar

  • Hero Member
  • *****
  • Posts: 2254
Re: Problem printing second document
« Reply #6 on: November 29, 2019, 04:47:21 pm »
The printer canvas should be autocreated so you don't need that Canvas.Create. Even if you did, the proper way of doing it is:

Code: Pascal  [Select]
  1. Printer.Canvas := TCanvas.Create

Even worse with FreeInstance; That is a TObject method intended mainly for "internal" and "special needs" use. It should be enough to call just Canvas.Free if needed.

But, as jamie said, I've used the printer canvas to print (what else? :) ) and never had to create/free the canvas itself; it's usually just there, in the TPrinter instance, waiting for you.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.4/2.0.6  - FPC 3.0.4 on:
(K|L)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

wp

  • Hero Member
  • *****
  • Posts: 6620
Re: Problem printing second document
« Reply #7 on: November 29, 2019, 07:48:16 pm »
Here is a printing example which works correctly, no "corrupted" pages. Tested on Win10 with pdf printer to save paper (it should not make a difference, though).
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

fatmonk

  • Full Member
  • ***
  • Posts: 232
Re: Problem printing second document
« Reply #8 on: December 02, 2019, 05:46:53 pm »
@jamie: No, I haven't run heaptrc yet. I suspected by creating repeatedly I could be causing problems, though, hence my point in my post 04:27:40pm. It's good that you've never head issues, but I am - every time I try to print a second time withoutrestarting the application!

@lucamar: I assumed it was autocreating as my code works without the Create but only the first time you print. Print again without restarting and I end up with big blocks of colour over the print. Add that Create and the problem goes away. Incidentally, using Canvas:=TCanvas.Create (remember, this is already withinin a with Printer do block) causes a compile-time error of 'No member is provided to access property'.

@wp: Thanks for this. I've hunted through your example for anything that you are doing that I'm not doing and anything you are doing differently and I can't spot anything. Your code prints across multiple pages whereas mine generates a single page and makes everything fit within that page - that's the only difference I could see, but it doesn't explain why printing a page for the first time works perfectly but second time it breaks.''

-FM

wp

  • Hero Member
  • *****
  • Posts: 6620
Re: Problem printing second document
« Reply #9 on: December 02, 2019, 06:02:05 pm »
Please post an small sample project which shows the issue - you must be doing something wrong but I can't tell from the distance. My demo was just to make sure that printing a page several times does work in principle.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

fatmonk

  • Full Member
  • ***
  • Posts: 232
Re: Problem printing second document
« Reply #10 on: December 02, 2019, 06:11:00 pm »
I need to do a lot of paring down to get an example of the issue.. I'll try to post something tomorrow..

In the meantime I've run with heaptrc and as expected there are memory leaks, however the debugging is no particularly helpful as everything points to canvas.inc and printers.pas rather than anything in my code.

The leaks only happen when I'm printing, though, so it has to be something in that function that's breaking things.

This brings me to something I always struggle with, though, what is the correct way of freeing objects? If I add Canvas.free to the finally block of my code, after the EndDoc I get a SIGSEGV crash... I know this is fundamental and I should know this, but I'm obviously missing this key piece of info.

-FM

wp

  • Hero Member
  • *****
  • Posts: 6620
Re: Problem printing second document
« Reply #11 on: December 02, 2019, 06:42:29 pm »
General rule is: Free only what you have created. Every "Free" in your code must have a matching "Create". You did not create the Canvas, so don't free it. I suppose the printer created the canvas, therefore, the printer will free it.
« Last Edit: December 02, 2019, 06:50:52 pm by wp »
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

jshah

  • Full Member
  • ***
  • Posts: 200
Re: Problem printing second document
« Reply #12 on: December 02, 2019, 07:31:38 pm »
You don't need to free Printer.Canvas object.

I also face same issue free the object is always confusing but practicing and asking will clear the concept.

fatmonk

  • Full Member
  • ***
  • Posts: 232
Re: Problem printing second document
« Reply #13 on: December 06, 2019, 05:06:42 pm »
Well, this was a lesson in 'change one thing then retest'...

It turns out that the whole issue was actually to do with the order I was doing things... and the fact that I changed the order that I was adding elements to the canvas meant that I was forgetting to reset the brush colour!

Previously, I had an issue where I was drawing a box beyond the edge of the canvas due to some dodgy maths. When I corrected this I realised I need to shuffle teh order of adding the various elements to the canvas. It looked like the canvas was being corrupted as something was being drawn right to the edge of the canvas and with the wrong background colour.

I fixed this, but then reordered things again - the TWO changes.

What looked like corruption remained but it was actually just a recurrence of the brush colour mistake! This time, though, the brush colour was being remembered between the first print and any subsequent print, which is why the first print looked fine, but any subsequent ones had random blocks of colour all over them!.

By commenting out every element and then uncommenting one by one I found the culprit element and from that it was obvious what was going on.

No need to recreate the canvas object or anything - just get the code right and in the right order. (And removing the spurious canvas.create got rid of the memory leaks :-)