Author: Tomas Rutkauskas
How to print a TScrollBox that contains controls generated at runtime
Answer:
If this is some kind of custom control you developed yourself teach it to print
itself. In fact it may be able to do that already using the PaintTo method. The
main problem here is scaling. If your control uses device units (pixels) as
measures instead of some device-independent unit like mm or inches you will need to
scale the printer.canvas before you pass it to a controls PaintTo method. Scaling
the printer canvas to the screen resolution is pretty straightforward. Here is an
older example that you can tailor to your needs.
Print all of a forms client area, even if parts are not visible. The form will clip
the output to the visible area if you try to output it to a canvas using using the
forms paintto method. But one can print the controls on it individually and that is
not clipped:
1
2 procedure TForm1.Button1Click(Sender: TObject);
3 var
4 c: TControl;
5 i: Integer;
6 topX, topY: Integer;
7 begin
8 printer.begindoc;
9 try
10 { Scale printer to screen resolution. }
11 SetMapMode(printer.canvas.handle, MM_ANISOTROPIC);
12 SetWindowExtEx(printer.canvas.handle, GetDeviceCaps(canvas.handle, LOGPIXELSX),
13 GetDeviceCaps(canvas.handle, LOGPIXELSY), nil);
14 SetViewportExtEx(printer.canvas.handle, GetDeviceCaps(printer.canvas.handle,
15 LOGPIXELSX),
16 GetDeviceCaps(printer.canvas.handle, LOGPIXELSY), nil);
17 topX := 10;
18 topY := 10;
19 for i := 0 to controlcount - 1 do
20 begin
21 c := controls[i];
22 if c is TWinControl then
23 TWinControl(c).paintto(printer.canvas.handle, c.left + topX, c.top + topy);
24 end;
25 finally
26 printer.enddoc;
27 end;
28 end;
The problem here is that this only prints TWinControl descendents, if you have
TLabels or TImages on the form they are not printed. The solution is to put
everything on the form onto a single top level TPanel. This panel is *not* aligned
to alClient, it has its left and top set to 0 and its width and height is such that
all controls fit on it. The code above then prints this panel unclipped and the
panel prints any non-TWinControls on it.
The usual caveats for PaintTo apply: not all controls will implement this method properly (a Windows limitation). Bitmaps on the form may not appear on the printer if the printer is not able to print device-dependent bitmaps for the screen. It may be advisable to first paint the form to a properly sized tBitmaps canvas (you can omit all the scaling stuff for that since the bitmap resolution is the same as the screens) and then print the bitmap as a device independent bitmap using StretchDIBits.
|