### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: <Solved> TopMargin  (Read 690 times)

#### Sprek Skik

• New Member
• Posts: 21
• Beginner Lazarus & Free Pascal
##### <Solved> TopMargin
« on: May 20, 2024, 03:32:22 pm »
Is there a way to make use of TopMargin in this code:

Code: Pascal  [Select][+][-]
1. procedure TfrmNoteBook.PrintMemo;
2. var
3.   I, n, Line : Integer;
4.
5. begin
6.   I := 0;
7.   n := 0;
8.   Line := 0 ;
9.   Printer.BeginDoc ;
10.   Printer.Canvas.Font.Name := 'MS Sans Serif';
11.   Printer.Canvas.Font.Size := 10;
12.   Printer.Canvas.Font.Color := clBlack;
13.   for I := 0 to Memo1.Lines.Count - 1 do
14.   begin
15.     if Line = 0 then
16.       for n := 0 to 3 do
17.         begin
18.           Printer.Canvas.TextOut(500, Line, '');
19.           Line := Line + Abs(Printer.Canvas.Font.Height);
20.         end;
21.     Printer.Canvas.TextOut(500, Line, Memo1.Lines[I]);
22.
23.     {Font.Height is calculated as -Font.Size * 72 / Font.PixelsPerInch which returns
24.      a negative number. So Abs() is applied to the Height to make it a non-negative
25.      value}
26.     Line := Line + Abs(Printer.Canvas.Font.Height);
27.     if (Line >= Printer.PageHeight) then
28.       begin
29.         Line := 0;
30.         Printer.NewPage;
31.       end;
32.
33.   end;
34.   Printer.EndDoc;
35. end;

I used a loop to make a margin but using topmargin would be more logical.
Any help would be great I am just beginning and it's difficult to find simple code. It would be better to use TRY with:

With Printer do
TRY
begin

end;
Except

end;
end;

But I don't know enough about error handing so this will do the job for now.

« Last Edit: May 22, 2024, 09:05:16 pm by Sprek Skik »

#### wp

• Hero Member
• Posts: 12069
##### Re: TopMargin
« Reply #1 on: May 20, 2024, 06:14:45 pm »
The first two parameters of the Canvas.TextOut method denote the x and y coordinates of the point where the top/left corner of the text given as third argument is printed. So, when you want to reserve a top margin do not begin drawing at y = 0 but at the value corresponding to the top margin. But note: the pixels on the printer are much denser than on the screen (usually). The printer has properties XDPI and YDPI (dpi = dots per inch) which you can use to convert a given distance to pixels. The following function converts millimeters to pixel count:
Code: Pascal  [Select][+][-]
1. function mmToPx(mm: Double; PPI: Integer): Integer;
2. var
3.   inches: Double;
4. begin
5.   inches := mm/25.4;
6.   Result := round(inches * PPI);
7. end;
Basically you can use the PageSetupDialog's MarginLeft/Top/Right/Bottom values here which are displayed as millimeters on my system; looking at it with the debugger, however, I saw that the actually returned values are millimeters multiplied by 100. And there is a property Units (pmDefault, pmMillimeters, pmInches) which suggests that there may be more complicated cases in general - I did not investigate this.

Find in the attachment a small project which prints a memo and uses the PageSetupDialog's margins. It is a bit special (and thus more complicated) because it automatically tries to wordwrap the lines of the memo, certainly not perfect in all cases, but good enough for the demo's dummy text.

#### Sprek Skik

• New Member
• Posts: 21
• Beginner Lazarus & Free Pascal
##### Re: TopMargin
« Reply #2 on: May 20, 2024, 09:56:34 pm »
The first two parameters of the Canvas.TextOut method denote the x and y coordinates of the point where the top/left corner of the text given as third argument is printed. So, when you want to reserve a top margin do not begin drawing at y = 0 but at the value corresponding to the top margin. But note: the pixels on the printer are much denser than on the screen (usually). The printer has properties XDPI and YDPI (dpi = dots per inch) which you can use to convert a given distance to pixels. The following function converts millimeters to pixel count:
Code: Pascal  [Select][+][-]
1. function mmToPx(mm: Double; PPI: Integer): Integer;
2. var
3.   inches: Double;
4. begin
5.   inches := mm/25.4;
6.   Result := round(inches * PPI);
7. end;
Basically you can use the PageSetupDialog's MarginLeft/Top/Right/Bottom values here which are displayed as millimeters on my system; looking at it with the debugger, however, I saw that the actually returned values are millimeters multiplied by 100. And there is a property Units (pmDefault, pmMillimeters, pmInches) which suggests that there may be more complicated cases in general - I did not investigate this.

Find in the attachment a small project which prints a memo and uses the PageSetupDialog's margins. It is a bit special (and thus more complicated) because it automatically tries to wordwrap the lines of the memo, certainly not perfect in all cases, but good enough for the demo's dummy text.

Wow that some example it need some study. Thanks it's a difficult subject. I thought that there were simple instructions to make TopMargin work but thank you for the function it should make it more simple....

#### wp

• Hero Member
• Posts: 12069
##### Re: TopMargin
« Reply #3 on: May 21, 2024, 01:13:55 am »
Maybe my example is too difficult to get started... (and, btw, it contains an error in calculation of the maximum horizontal and vertical print positions). Here is a simpler project without wordbreak. It reads the names of the files in the Windows (root) directory and displays them in the memo. The names are rather short and word-break is not needed if the memo is sufficiently wide. I added lots of comments to explain what is happening.