Printing from Delphi

There are two ways to printer, text and graphics. Now, the grapics is the most common, and will be described in the next text. It consists from creating a virtual graphics page, its generating and finally, printing.

The first step is to add the Printers unit to the uses declaration, for example on the end of the list:

  Windows, Messages, SysUtils, Classes, Graphics,
  Controls, Forms, Dialogs, StdCtrls, Printers;

The same for the text mode. This unit contains the printer object.

The second step is (in most cases) to select a printer (not necessary, we can use the default one). The prepared solution is to add a Print Dialog (the Dialogs ribbon, PrintDialog ), which "execute" method should be called:

  if printdialog1.execute then ;

If the user select printer and press OK, we will get true and we can continue with the next step. Because we use a procedure to do this, we can negate (reverse) the condition, and in the other case, just leave the procedure - using the "exit" command:

 if not printdialog1.execute then exit;

On the Dialogs ribbon, there are the PrinterSetupDialog. We don't need it, setup can be called by a button on the printer select dialog.

Note: The Printers unit can be used only once in the all project. The result is, that we don't need to save the result or copy it.

Step three: create a virtual page. This is done by the Printer.BeginDoc procedure (no parameters, no result).

Then, we can draw to the virtual printer canvas. It is described in the next text.

The last action is to send this virtual page to printer, after its' creation is completed. This is done by calling the Printer.EndDoc procedure (again, no parameters). Instead of this, you can call Printer.Abort, to destroy prepared virtual page (no print).

Important: Both of the dialogs can be called only before Printer.BeginDoc, you cannot change printer properties during printing.


Virtual page assembly

The printer canvas works just like an another canvas. Resolution and number of colors depends on the used (selected) printer. It can be checked after Printer.BeginDoc calling - the next example try to open virtual page and write the resolution to two prepared labels:

  if PrintDialog1.Execute then begin
    Label1.Caption := IntToStr(Printer.PageWidth);
    Label2.Caption := IntToStr(Printer.PageHeight);

Because there are nothing to print, we have to use Abort procedure to finish this. Try similar procedure and after execute, select different printer, or resolution (paper size, page orientation).

The "With" compiler directive

In many cases, we access more components of an object, in the next example for drawing a red rectangle:


To make the program clear to read, it is usefull not to write Printer.Canvas. again and again (for more complex program, even something like unit4.Form4.Printer.Canvas. ), we can use the with directive, in combination with the begin - end program brackets:

with <part of object or record name> do begin <some commands> end;

The previous example can be rewritten as either:

  with Printer do begin


  with Printer.Canvas do begin

... or the with directive can be nested.

The task: rewrite program from the previous week to print the final graph.

Note: the "pixels" property for the printer canvas is declared as write-only, but works - you can try to change few dots:

for i:=1 to 1000 do pixels[150,i]:=clBlack;

If you change only one dot on a modern printer, the change will be almost invisible.

The decision, that the pixels property will be unreadable, make the "print preview" function more complicated. The reason was probably the size of printer canvas - for example, A4 is about 8 x 12 inch size and with 600 dpi, this is more then 34 milion pixels; in the packed form (printer is black and white, one bit per pixel), only little more then 4MB memory is needed.