Author: Tomas Rutkauskas
I have a TRichEdit Control that I want to print as part of a document. There is
other information that needs to go on the printed page. The Print method seems to
start a separate document. How do I print the rich edits contents to the printer
canvas of my document. As well I need to anticipate that there could be one or two
pages of printed depending on the information in the TRichEdit.
Answer:
You have to use the EM_FORMATRANGE message to print the richedits content in code.
Printing rich edit contents using EM_FORMATRANGE:
1
2 procedure TForm1.Button2Click(Sender: TObject);
3 var
4 printarea: TRect;
5 x, y: Integer;
6 richedit_outputarea: TRect;
7 printresX, printresY: Integer;
8 fmtRange: TFormatRange;
9 begin
10 Printer.beginDoc;
11 try
12 with Printer.Canvas do
13 begin
14 printresX := GetDeviceCaps(handle, LOGPIXELSX);
15 printresY := GetDeviceCaps(handle, LOGPIXELSY);
16 Font.Name := 'Arial';
17 Font.Size := 14;
18 Font.Style := [fsBold];
19 printarea :=
20 Rect(printresX, {1 inch left margin}
21 printresY * 3 div 2, {1.5 inch top margin}
22 Printer.PageWidth - printresX, {1 inch right margin}
23 Printer.PageHeight - printresY * 3 div 2 {1.5 inch bottom margin}
24 );
25 x := printarea.left;
26 y := printarea.top;
27 TextOut(x, y, 'A TRichEdit print example');
28 y := y + TextHeight('Ag');
29 Moveto(x, y);
30 Pen.Width := printresY div 72; {1 point}
31 Pen.Style := psSolid;
32 Pen.Color := clBlack;
33 LineTo(printarea.Right, y);
34 Inc(y, printresY * 5 div 72);
35 {Define a rectangle for the rich edit text. The height is set to the maximum.
36 But we need to convert from device units to
37 twips, 1 twip = 1/1440 inch or 1/20 point.}
38 richedit_outputarea := Rect((printarea.left + 2) * 1440 div printresX,
39 y * 1440 div printresY, (printarea.right - 4) * 1440 div printresX,
40 (printarea.bottom) * 1440 div printresY);
41 {Tell rich edit to format its text to the printer.
42 First set up data record for message:}
43 fmtRange.hDC := Handle; {printer handle}
44 fmtRange.hdcTarget := Handle; {ditto}
45 fmtRange.rc := richedit_outputarea;
46 fmtRange.rcPage := Rect(0, 0, Printer.PageWidth * 1440 div printresX,
47 Printer.PageHeight * 1440 div printresY);
48 fmtRange.chrg.cpMin := 0;
49 fmtRange.chrg.cpMax := richedit1.GetTextLen - 1;
50 {first measure the text, to find out how high the format rectangle will be.
51 The call sets fmtrange.rc.bottom to the actual height required,
52 if all characters in the selected range will fit into a smaller rectangle}
53 richedit1.Perform(EM_FORMATRANGE, 0, Longint(@fmtRange));
54 {Draw a rectangle around the format rectangle}
55 Pen.Width := printresY div 144; {0.5 points}
56 Brush.Style := bsClear;
57 Rectangle(printarea.Left, y - 2, printarea.right, fmtrange.rc.bottom *
58 printresY div 1440 + 2);
59 {Now render the text}
60 richedit1.Perform(EM_FORMATRANGE, 1, Longint(@fmtRange));
61 y := fmtrange.rc.bottom * printresY div 1440 + printresY * 5 div 72;
62 {Free cached information}
63 richedit1.Perform(EM_FORMATRANGE, 0, 0);
64 TextOut(x, y, 'End of example.');
65 end;
66 finally
67 Printer.EndDoc;
68 end;
69 end;
This example assumes that anything will fit on one page but it is no problem to
extend it to multiple pages. The richedit1.perform( EM_FORMATRANGE) call returns
the index of the last character that could be fitted into the passed fmtrange.rc, +
1. So if multiple pages are required one repeats with fmtrange.chrg.cpMin set to
this value, until all characters have been printed.
Note that the rich edit control strips blanks and linebreaks off the end of the text so the number of characters to output may be < richedit.gettextLen!
|