Recent

Author Topic: (Solved) DrawText to a printer.  (Read 7095 times)

Hopestation

  • Full Member
  • ***
  • Posts: 181
(Solved) DrawText to a printer.
« on: December 15, 2014, 12:17:21 pm »
Hi.

I am using Windows XP, SP3 with Lazarus Version #1.2.4, FPC version 2.6.4.

I am trying to put text onto a printer canvas, using a unit converted from Delphi 4 :-

procedure TMainForm.FilePrintClick(Sender: TObject);
Var
  I, LineHeight, LinesPerPage, LineCount, X, Y: Integer;
  R: TRect;
  S: String;
  Printer: TPrinter;
begin
  If PrintDialog.Execute then
  begin
    Printer.Title := 'ScratchPad - ' +  OpenDialog.FileName;
    Printer.Canvas.Font := Memo.Font;

    Y := Printer.YDPI;

    LineHeight := Abs(MulDiv(Printer.canvas.Font.Size, Y, 72));
    Inc(LineHeight, (LineHeight * 4) Div 10);
    LinesPerPage := (Printer.PageHeight Div LineHeight) - 4;
    LineCount := 4;
    Printer.BeginDoc;
    R.Top := LineHeight;
    R.Left := 50;
    R.Right := Printer.PageWidth;
    R.Bottom := LineHeight * 2;
    DrawText(Printer.handle, PChar(OpenDialog.FileName), -1, R, DT_Center);

Compiling fails at the DrawText line with the message

                       Error: identifier idents no member "handle".

How do I correct this line to suit Lazarus?

« Last Edit: December 18, 2014, 01:20:07 pm by Hopestation »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: DrawText to a printer.
« Reply #1 on: December 15, 2014, 10:43:11 pm »
I think you can use DrawText for printing in Lazarus, but it comes from the world of Windows APIs. It is better to use fully cross-platform routines; so you could adapt the following (which assumes a Memo1, PrintDialog1, OpenDialog1 and an appropriate uses clause) to suit your case.
Printer is a pre-declared global TPrinter instance variable, initialised for you by the LCL - there is no need to declare it in your code.

Code: [Select]
procedure TForm1.ButtonPrintClick(Sender: TObject);
Var
  i, lineCount, linesPerPage: integer;
  scaleFactor, lh: single;
begin
  if OpenDialog1.Execute then
  If PrintDialog1.Execute then
  begin
    Memo1.Lines.LoadFromFile(OpenDialog1.FileName);
    Printer.Canvas.Font.Assign(Memo1.Font);
    scaleFactor:=Printer.XDPI / Screen.PixelsPerInch;
    Printer.Canvas.Font.Size:=trunc(12 * scaleFactor); // assuming a 12-point font
    lh:=printer.Canvas.TextHeight('Xg')*1.2; // 1.2 is one possible factor, depends how far apart ('leading') you want the lines to be
    linesPerPage:=trunc(Size(Printer.PaperSize.PaperRect.WorkRect).cy / lh) - 1;

    Printer.BeginDoc;
    lineCount:=1;
    try
      for i:=0 to Memo1.Lines.Count-1 do
        begin
          Printer.Canvas.TextOut(0, trunc(lh*lineCount), Memo1.Lines[i]);
          Inc(lineCount);
          if (lineCount > linesPerPage) then begin
            lineCount:=1;
            Printer.NewPage;
          end;
        end;
    finally
      Printer.EndDoc;
    end;
  end;
end;

Hopestation

  • Full Member
  • ***
  • Posts: 181
Re: DrawText to a printer.
« Reply #2 on: December 16, 2014, 09:51:30 am »
Thanks for your reply.

I don't understand the section

   Size(Printer.PaperSize.PaperRect.WorkRect).cy

Why is the .cy outside the Size bracket?

I have asked this question before with regard to TaChart and I am in the same position with TPinters.

Is there a list of all properties. The Wiki entries seem to give specific examples but I can never find a list of all properties and what they should be set to.

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: DrawText to a printer.
« Reply #3 on: December 16, 2014, 10:42:52 am »
Quote
I don't understand the section "Size(Printer.PaperSize.PaperRect.WorkRect).cy". Why is the .cy outside the Size bracket?
Instead of looking for wikis and possibly outdated documentation, have a look at the source code. This is the most up-to-date documentation. You only need to know the must basic navigation technique:

Left-click on "printer" with the CTRL key down. This opens the unit in which "printer" is declared:
Code: [Select]
var
  Printer: TPrinter = nil; 
This does not help much, but you can do the same with "TPrinter". This brings you to the declaration of "TPrinter".

Howard's code refers to "Printer.PaperSize" - scroll down untill you see it. "PaperSize" is type "TPaperSize". Ctrl-Left-Click on "TPaperSize" - this brings you to to the declaration of this object. A bit down you find the property PaperRect which is a "TPaperRect". Another ctrl-left-click, and we're there:

Code: [Select]
  TPaperRect = Record
    PhysicalRect : TRect;
    WorkRect     : TRect;
  end;

You see now that Printer.PaperSize.PaperRect.WorkRect is a TRect. Howard needs the height of this rectangle. He could calculate the difference between Bottom an Top of the TRect. But he is a clever guy and knows that there is a function "Size" in unit "Types" which does exactly the same. If you have "Types" in the uses clause you can ctrl-left-click on "Size" to see that declaration. The function "Size" returns a TSize record, the rectangle height is the cy field.

Hopestation

  • Full Member
  • ***
  • Posts: 181
Re: DrawText to a printer.
« Reply #4 on: December 16, 2014, 07:48:42 pm »
Thanks for all your help.

I had looked at http://lazarus-ccr.sourceforge.net/docs/lcl/printers/tprinter.html, but the definitions were nowhere near as comprehensive as your answers.

 

TinyPortal © 2005-2018