Author: Peter Below
I have 3 columns in my TListView (1 main item, 2 sub-items) and I've tried to print
the text with the use of TPrintDialog but I've had no luck. I was thinking about
using the TextRect Canvas property to accomplish this. I'm not using a TMemo so
what would be the TListView text property to use here. I would like to print them
out in the same format that they appear in the list view.
Answer:
There is a bit more to this than a single textrect call. The printer and your
screen have very different resolutions, so the positions and sizes you get from the
listview need to be scaled for the printer. For which you need the printers
resolution. Some other pieces like printable area are also of interest:
1 { ... }
2 type
3 TPageInfo = record
4 width, height: Integer; {physical width and height, in dots}
5 offsetX, offsetY: Integer; {non-printable margin, in dots}
6 resX, resY: Integer; {logical resolution, dots per inch}
7 end;
8
9 procedure GetPageinfo(var info: TPageInfo; index: Integer = -1);
10 begin
11 if index > -1 then
12 Printer.PrinterIndex := index;
13 with Printer do
14 begin
15 info.resX := GetDeviceCaps(handle, LOGPIXELSX);
16 info.resY := GetDeviceCaps(handle, LOGPIXELSY);
17 info.offsetX := GetDeviceCaps(handle, PHYSICALOFFSETX);
18 info.offsetY := GetDeviceCaps(handle, PHYSICALOFFSETY);
19 info.width := GetDeviceCaps(handle, PHYSICALWIDTH);
20 info.height := GetDeviceCaps(handle, PHYSICALHEIGHT);
21 end;
22 end;
Note that the following example assumes that the listview columns widths are > 0
(autosize = true or explicit column width set).
23
24 procedure TForm1.PrintButtonClick(Sender: TObject);
25 const
26 colspacing = 12; {12 dots between columns}
27 var
28 item: TListItem;
29 info: TPageInfo;
30 X, Y, leftMargin, TopMargin, BottomMargin: Integer;
31 screenres: Integer;
32
33 function ScreenToPrint(dim: Integer): Integer;
34 begin
35 result := (dim * info.resX) div screenres;
36 end;
37
38 procedure printHeader;
39 var
40 r: Trect;
41 i: Integer;
42 begin
43 r.Left := X;
44 r.top := Y;
45 printer.canvas.Font.style := [fsBold];
46 r.Bottom := r.Top + printer.canvas.TextHeight('Äy');
47 for i := 0 to listview1.columns.count - 1 do
48 begin
49 r.Right := r.Left + ScreenToPrint(listview1.column[i].Width);
50 printer.canvas.TextRect(r, r.left, r.Top, listview1.Column[i].Caption);
51 r.Left := r.Right + colspacing;
52 end;
53 printer.canvas.Font.style := [];
54 printer.Canvas.Pen.Width := ScreenToPrint(2);
55 printer.canvas.MoveTo(X, r.Bottom);
56 printer.Canvas.Lineto(r.Right, r.Bottom);
57 Y := r.Bottom + colspacing;
58 end;
59
60 procedure PrintItem;
61 var
62 r: Trect;
63 i: Integer;
64 s: string;
65 begin
66 if Y >= BottomMargin then
67 begin
68 printer.NewPage;
69 Y := TopMargin;
70 PrintHeader;
71 end;
72 r.Left := X;
73 r.top := Y;
74 r.Bottom := r.Top + printer.canvas.TextHeight('Äy');
75 for i := 0 to listview1.columns.count - 1 do
76 begin
77 r.Right := r.Left + ScreenToPrint(listview1.columns[i].Width);
78 if i = 0 then
79 S := item.caption
80 else
81 S := item.SubItems[i - 1];
82 printer.canvas.TextRect(r, r.left, r.Top, S);
83 r.Left := r.Right + colspacing;
84 end;
85 Y := r.Bottom + colspacing div 2;
86 end;
87
88 var
89 i: Integer;
90 begin
91 if PrintDialog1.Execute then
92 begin
93 GetPageInfo(info);
94 screenres := Screen.PixelsPerInch;
95 try
96 Printer.BeginDoc;
97 Printer.Canvas.Font := listview1.Font;
98 leftMargin := info.resX - info.offsetX; {1 inch left}
99 topMargin := info.resY - info.offsetY; {1 inch top}
100 bottomMargin := info.height - info.resY - info.offsetY; {1 inch}
101 X := leftMargin;
102 Y := topMargin;
103 PrintHeader;
104 for i := 0 to listview1.Items.Count - 1 do
105 begin
106 item := listview1.Items[i];
107 PrintItem;
108 end;
109 finally
110 Printer.EndDoc;
111 end;
112 end;
113 end;
|