Author: Jonas Bilinkevicius
How to print a TRichEdit upside down
Answer:
Below are the 4 base orientations, but TXForm (in windows.pas) gives you the
ability to turn the world to any degree. World transformations are interesting in
that they raise the prospect of working in code with portrait objects and simply
turning the world, rather than turning the objects individually to conform to the
world - which I have been doing up until now.
Note: This does not work for Win9x.
1 { ... }
2 type
3 TWorldOrientation = (woPortrait, woLandscape, woInversePortrait,
4 woInverseLandscape);
5
6 function GetWorldOrientation(APageRect: TRect; AOrientation: TWorldOrientation):
7 TXForm;
8 begin
9 case AOrientation of
10 woPortrait:
11 begin
12 Result.eM11 := 0;
13 Result.eM12 := 0;
14 Result.eM21 := 0;
15 Result.eM22 := 0;
16 Result.eDX := APageRect.Left;
17 Result.eDY := APageRect.Top;
18 end;
19 woLandscape:
20 begin
21 Result.eM11 := 0;
22 Result.eM12 := -1;
23 Result.eM21 := 1;
24 Result.eM22 := 0;
25 Result.eDX := APageRect.Left;
26 Result.eDY := APageRect.Bottom;
27 end;
28 woInversePortrait:
29 begin
30 Result.eM11 := -1;
31 Result.eM12 := 0;
32 Result.eM21 := 0;
33 Result.eM22 := -1;
34 Result.eDX := APageRect.Right;
35 Result.eDY := APageRect.Bottom;
36 end;
37 woInverseLandscape:
38 begin
39 Result.eM11 := 0;
40 Result.eM12 := 1;
41 Result.eM21 := -1;
42 Result.eM22 := 0;
43 Result.eDX := APageRect.Right;
44 Result.eDY := APageRect.Top;
45 end;
46 end;
47 end;
48
49 function PrintText(ACanvas: TCanvas; APageRect, APrintRect: TRect; AText: string;
50 ATextFlags:
51 Integer; AOrientation: TWorldOrientation): Boolean;
52 var
53 SaveGM: Integer;
54 SaveXF: TXForm; // unit Windows.pas
55 begin
56 {save graphics mode}
57 SaveGM := Windows.GetGraphicsMode(ACanvas.Handle);
58 {can we do it}
59 Result := Windows.SetGraphicsMode(aCanvas.Handle, GM_ADVANCED) <> 0;
60 if Result then
61 begin
62 {save transform}
63 Windows.GetWorldTransform(ACanvas.Handle, SaveXF);
64 // set orientation
65 Windows.SetWorldTransform(ACanvas.Handle, GetWorldOrientation(APageRect,
66 AOrientation));
67 {move text to page}
68 Windows.DrawText(ACanvas.Handle, PChar(AText), -1, APrintRect, ATextFlags);
69 {restore transform}
70 Windows.SetWorldTransform(ACanvas.Handle, SaveXF);
71 {restore graphics mode}
72 Windows.SetGraphicsMode(aCanvas.Handle, SaveGM);
73 end;
74 end;
75
76 function PrintRichText(ACanvas: TCanvas; APageRect, APrintRect: TRect; ARichEdit:
77 TRichEdit;
78 APixelsPerInchX, APixelsPerInchY: Integer; AOrientation: TWorldOrientation):
79 Boolean;
80 const
81 RICH_TWIPS = 1440;
82 var
83 SaveGM: Integer;
84 SaveXF: TXForm; {unit Windows.pas}
85 FmtRange: TFormatRange; {unit RichEdit.pas}
86 begin
87 {save graphics mode}
88 SaveGM := Windows.GetGraphicsMode(ACanvas.Handle);
89 {can we do it}
90 Result := Windows.SetGraphicsMode(aCanvas.Handle, GM_ADVANCED) <> 0;
91 if Result then
92 begin
93 {save transform}
94 Windows.GetWorldTransform(ACanvas.Handle, SaveXF);
95 {set orientation}
96 Windows.SetWorldTransform(ACanvas.Handle, GetWorldOrientation(APageRect,
97 AOrientation));
98 {adjust for twips}
99 APrintRect.Left := APrintRect.Left * RICH_TWIPS div APixelsPerInchX;
100 APrintRect.Top := APrintRect.Top * RICH_TWIPS div APixelsPerInchY;
101 APrintRect.Right := APrintRect.Right * RICH_TWIPS div APixelsPerInchX;
102 APrintRect.Bottom := APrintRect.Bottom * RICH_TWIPS div APixelsPerInchY;
103 {move rich text to page}
104 System.FillChar(FmtRange, SizeOf(FmtRange), 0);
105 FmtRange.Hdc := ACanvas.Handle;
106 FmtRange.HdcTarget := ACanvas.Handle;
107 FmtRange.Rc := APrintRect;
108 FmtRange.ChrG.CpMin := 0;
109 FmtRange.ChrG.CpMax := Length(ARichEdit.Text);
110 ARichEdit.Perform(EM_FORMATRANGE, 1, LongInt(@FmtRange));
111 ARichEdit.Perform(EM_FORMATRANGE, 0, 0);
112 {restore transform}
113 Windows.SetWorldTransform(ACanvas.Handle, SaveXF);
114 {restore graphics mode}
115 Windows.SetGraphicsMode(aCanvas.Handle, SaveGM);
116 end;
117 end;
118
119 Examples:
120
121 procedure TForm1.FormCreate(Sender: TObject);
122 begin
123 {Apparently you need to initialise before using the first time otherwise the
124 canvas doesn't appear to paint properly}
125 Windows.SetGraphicsMode(Self.Canvas.Handle, GM_ADVANCED);
126 end;
127
128 procedure TForm1.Button1Click(Sender: TObject);
129 var
130 R: TRect;
131 begin
132 R := Rect(20, 20, 200, 200);
133 PrintText(Self.Canvas, Self.ClientRect, R, 'I am portrait', 0, woPortrait);
134 PrintText(Self.Canvas, Self.ClientRect, R, 'I am landscape', 0, woLandscape);
135 PrintText(Self.Canvas, Self.ClientRect, R, 'We are inverse portrait' + #13#10 +
136 'As are we', 0, woInversePortrait);
137 PrintText(Self.Canvas, Self.ClientRect, R, 'We are inverse landscape.' + #13#10 +
138 'Us to', DT_RIGHT, woInverseLandscape);
139 end;
140
141 procedure TForm1.Button2Click(Sender: TObject);
142 var
143 R: TRect;
144 begin
145 if OpenDialog1.Execute then
146 begin
147 RichEdit1.Lines.LoadFromFile(OPenDialog1.FileName);
148 R := Rect(10, 10, 200, 300);
149 PrintRichText(Self.Canvas, Self.ClientRect, R, RichEdit1, Screen.PixelsPerInch,
150 Screen.PixelsPerInch, woPortrait);
151 PrintRichText(Self.Canvas, Self.ClientRect, R, RichEdit1, Screen.PixelsPerInch,
152 Screen.PixelsPerInch, woLandscape);
153 PrintRichText(Self.Canvas, Self.ClientRect, R, RichEdit1, Screen.PixelsPerInch,
154 Screen.PixelsPerInch, woInverseLandscape);
155 PrintRichText(Self.Canvas, Self.ClientRect, R, RichEdit1, Screen.PixelsPerInch,
156 Screen.PixelsPerInch, woInversePortrait);
157 end;
158 end;
|