TExcellentFormPrinter Delphi Documentation Version 0A.3.1

Copyright © 1989-2010 by Joe C. Hecht All Rights Reserved
Copyright © 2011-2019 by CODE4SALE, LLC All Rights Reserved

Contact CODE4SALE, LLC - Joe Hecht.

TExcellent home page

TExcellent documentation home page!

Try TExcellentFormPrinter!   Buy TExcellentFormPrinter!
Try TExcellentImagePrinter!   Buy TExcellentImagePrinter!

Product names, trademarks, and servicemarks mentioned are owned by their respective owners.


Changes since version 3.4

All TExcellent products have now been upgraded to be compatible with all 32 and 64 bit versions of the Delphi and C++ Builder Windows compilers, and the TExcellent version number has been adjusted to now reflect compatibility with RAD Studio compiler version numbers.

Please note that TExcellentFormPrinter and the PrnUtils dialog are very VCL specific.

Non VCL notes: While TExcellent products are VCL and Windows specific, and FireMonkey is not officially supported, we have found that some TExcellent products are in fact usable in non-VCL projects. For example, TExcellentImagePrinter can be used in a FireMonkey Windows application (complete with the PrnUtils abort dialog) with minimal changes to your calling code. For example, creating our printing abort / status dialog can be accomplished with the following code:

C++Builder:

  AbortDialog := CreateAbortDialog(FMX.Platform.Win.FormToHWND(this),
                                   this);

Delphi:
  AbortDialog := CreateAbortDialog(FMX.Platform.Win.FormToHWND(self),
                                   self);


TExcellentCompilerDefs.inc: Not required by the TExcellent products themselves. The example and demo projects now make use of an include file to help determine the compiler version and capabilities in use, and is

PrnDibBuildMode.inc: An include file used to determine the build mode (Currently demo/release) and is required to compile release (non-demo) versions of TExcellent products.

Some Types have been renamed to reflect the name of the unit they are used in (to avoid scoping and compiler errors, and to allow the C and Pascal source to have greater symmetry).

Pointer types traditionally passed to callback functions as typecast integer values have been typed to a pointer sized integer (size_t where practical and a 32 unsigned integer where not practical) and renamed as follows:

UNITNAME_PTR_UINT
UNITNAME_PTR_AS_UINT

Example:

PRNFORM_PTR_AS_UINT
PRNFORM_PTR_UINT

TAppCallbackFn() has been renamed to:

TPrnFormAppCallbackFn (TExcellentFormPrinter)
TPrnDibAppCallbackFn (TExcellentImagePrinter)

Pointers to character strings used in filenames and captions hsve changed to TCaption and TFilename types!

In some cases, pointers to untyped pointer types (void *) have changed to (PVOID *).


Functions and structures:

Installation
PrintForm
PrintFormXY
PrintFormEx
PrintFormXYEx
PrintTCustomForm
PrintTScrollingWinControl
PrintTScrollingWinControlEx
HasClass
TPrintFormData
VirtualClientSize
VirtualClientScrolledOffset
PrnFormSetDebugMsg
PrnFormSetAbortDialogHandle
PrnFormSetDebugDoBlt
PrnFormSetDebugUseDDB
PrnFormSetDebugAutoUseDDB
PrnFormSetDebugFrames
PrnFormSetSleepValue
PrnFormSetOutputScaleFactor
PrnFormSetDoWinScale


Installation

These units provide a 100 percent API interface, and do not install components in the Delphi IDE component palette.

For the unregistered version of the product, simply unzip the .dcu and .dfm files and place them in your project directory.

For the registered version of the product, simply unzip the .pas and .dfm files and place them in a directory that has a common path with your other Delphi components.

Back to Functions and Structures


PrintForm

function PrintForm(TheScrollingWinControl : TScrollingWinControl;
                   dc : HDC;
                   Centered : BOOL;
                   UsePerfectMargins : BOOL) : BOOL;

Location: PrnForm.pas

Prints a form (or other TScrollingWinControl) to the Windows dc (Canvas.Handle) given, stretched proportionally to fit the page. If Centered is TRUE, then the printout will be centered on the device, else the printout will start at the top left corner of the device. If UsePerfectMargins is TRUE, then the print margin will be adjusted to accommodate devices that have uneven page margins. Note that the dc passed in should not be a DIBSECTION, and must be a true windows device or memory dc. Returns TRUE if successful.

Example:

uses
  Printers,
  PrnUtils,
  PrnForm;

procedure TForm1.Menu1Click(Sender: TObject);
begin
  Printer.BeginDoc;
  PrintForm(self,
            Printer.Canvas.Handle,
            TRUE,
            TRUE);
  Printer.EndDoc;
end;

Back to Functions and Structures


PrintFormXY

function PrintFormXY(TheScrollingWinControl : TScrollingWinControl;
                     dc : HDC;
                     x : integer;
                     y : integer;
                     Width : integer;
                     Height : integer) : BOOL;

Location: PrnForm.pas

Prints a form (or other TScrollingWinControl) to the Windows dc (Canvas.Handle) given. The output starts at x,y, and the image is stretched to width, height.

Note: The dc passed in should not be a DIBSECTION, and must be a true windows device or memory dc. Returns TRUE if successful.

Example:

uses
  Printers,
  PrnUtils,
  PrnForm;

procedure TForm1.Menu1Click(Sender: TObject);
var
  TheVirtualClientSize : TSize;
begin
  TheVirtualClientSize := VirtualClientSize(self);
  Printer.BeginDoc;
  PrintFormXY(self,
              Printer.Canvas.Handle,
              0,
              0,
              TheVirtualClientSize.cx,
              TheVirtualClientSize.cy);
  Printer.EndDoc;
end;

Back to Functions and Structures


PrintFormEx

function PrintFormEx(TheScrollingWinControl : TScrollingWinControl;
                     dc : HDC;
                     Centered : BOOL;
                     UsePerfectMargins : BOOL;
                     lpPrintFormData : PPrintFormData) : BOOL;

Location: PrnForm.pas

Prints a form (or other TScrollingWinControl) to the Windows dc given, stretched proportionally to fit the page. Note that the dc (Canvas.Handle) passed in should not be a DIBSECTION, and must be a true windows device or memory dc. If Centered is TRUE, then the printout will be centered on the device, else the printout will start at the top left corner of the device. If UsePerfectMargins is TRUE, then the print margin will be adjusted to accommodate devices that have uneven page margins. Additional options are set by passing a pointer to a TPrintFormData structure in the lpPrintFormData parameter. Returns TRUE if successful.

Example:

uses
  Printers,
  PrnUtils,
  PrnForm;

procedure TForm1.Menu1Click(Sender: TObject);
var
  PrintFormData : TPrintFormData;
begin
  FillChar(PrintFormData,
           sizeof(PrintFormData),
           0);
  PrintFormData.StrucSize := sizeof(PrintFormData);
 {Set the PrintFormData options you wish to set}
  PrintFormData.UseAbortDialog := TRUE;
  Printer.BeginDoc;
  PrintFormEx(self,
              Printer.Canvas.Handle,
              TRUE,
              TRUE,
              @PrintFormData);
  Printer.EndDoc;
end;

Back to Functions and Structures


PrintFormXYEx

function PrintFormXYEx(TheScrollingWinControl : TScrollingWinControl;
                       dc : HDC;
                       x : integer;
                       y : integer;
                       Width : integer;
                       Height : integer;
                       lpPrintFormData : PPrintFormData) : BOOL;

Location: PrnForm.pas

Prints a form (or other TScrollingWinControl) to the Windows dc (Canvas.Handle) given. The output starts at x,y, and the image is stretched to width, height. Note that the dc passed in should not be a DIBSECTION, and must be a true windows device or memory dc. Additional options are set by passing a pointer to a TPrintFormData structure in the lpPrintFormData parameter. Returns TRUE if successful.

Example:

uses
  Printers,
  PrnUtils,
  PrnForm;

procedure TForm1.Menu1Click(Sender: TObject);
var
  PrintFormData : TPrintFormData;
  TheVirtualClientSize : TSize;
begin
  FillChar(PrintFormData,
           sizeof(PrintFormData),
           0);
  PrintFormData.StrucSize := sizeof(PrintFormData);
 {Set the PrintFormData options you wish to set}
  PrintFormData.UseAbortDialog := TRUE;
  TheVirtualClientSize := VirtualClientSize(self);
  Printer.BeginDoc;
  PrintFormXYEx(self,
                Printer.Canvas.Handle,
                0,
                0,
                TheVirtualClientSize.cx,
                TheVirtualClientSize.cy,
                @PrintFormData);
  Printer.EndDoc;
end;

Back to Functions and Structures


PrintTScrollingWinControl

function PrintTScrollingWinControl(TheScrollingWinControl : TScrollingWinControl;
                                   dc : HDC;
                                   x : integer;
                                   y : integer;
                                   Width : integer;
                                   Height : integer;
                                   ClipRect : TRect;
                                   TrueColor : BOOL;
                                   OnAppCallbackFn : TPrnFormAppCallbackFn;
                                   OnAppCallbackData : PRNFORM_PTR_AS_UINT;
                                   OnPaintCallbackEvent : TOnPaintCallbackEvent;
                                   OnPaintControlCallbackEvent : TOnPaintControlCallbackEvent) : BOOL;

Location: PrnForm.pas

Special Note: This function is provided for backwards compatibility. We recommend you upgrade your code to use the new PrintTScrollingWinControlEx() function, as this function is now a simple wrapper to the new PrintTScrollingWinControlEx() function. The wrapper ignores the TrueColor parameter, as the print engine has been enhanced, and this parameter is no longer useful. Documentation for this function's parameters can be found in the documentation for PrintTScrollingWinControlEx() function.

Back to Functions and Structures


PrintTCustomForm

function PrintTCustomForm(TheScrollingWinControl : TScrollingWinControl;
                          dc : HDC;
                          x : integer;
                          y : integer;
                          Width : integer;
                          Height : integer;
                          ClipRect : TRect;
                          AbortDialog : TPrinterAbortDialog;
                          OnPaintCallbackEvent : TOnPaintCallbackEvent;
                          OnPaintControlCallbackEvent : TOnPaintControlCallbackEvent) : BOOL;

Location: PrnForm.pas

Special Note: This function is provided for backwards compatibility. We recommend you upgrade your code to use the new PrintTScrollingWinControlEx() function, as this function now a simple wrapper to the new PrintTScrollingWinControlEx() function. Documentation for this functions parameters can be found in the documentation for PrintTScrollingWinControlEx() function.

Back to Functions and Structures


PrintTScrollingWinControlEx

function PrintTScrollingWinControlEx(TheScrollingWinControl : TScrollingWinControl;
                                     dc : HDC;
                                     x : integer;
                                     y : integer;
                                     Width : integer;
                                     Height : integer;
                                     ClipRect : TRect;
                                     OnAppCallbackFn : TPrnFormAppCallbackFn;
                                     OnAppCallbackData : PRNFORM_PTR_AS_UINT;
                                     OnPaintCallbackEvent : TOnPaintCallbackEvent;
                                     OnPaintControlCallbackEvent : TOnPaintControlCallbackEvent;
                                     lpPrintFormData : PPrintFormData) : BOOL;

Location: PrnForm.pas

Prints a form (or other TScrollingWinControl) to the Windows dc (Canvas.Handle) given. The output starts at x,y, and the image is stretched to width, height. Note that the dc passed in should not be a DIBSECTION, and must be a true windows device or memory dc.

The ClipRect parameter specifies the area of the device to clip output to, and should be no larger than the device surface. The ClipRect parameter is useful in stretching the output to span across multiple pages (up to 2 billion pixels high and wide), and allows the PrintForm engine to optimize output by processing only the stretched data contained in the ClipRect area. This also allows the engine to overcome Windows 9x GDI limitations of a 32000 pixel high/wide output.

The OnAppCallbackFn is an optional callback function that you may install to track the progess of the print job and optionally provide real time status updates to your user (perhaps by using a progress meter) as well as allowing you to cancel the print job. If you do not install a callback function, simply pass nil in this parameter. If you do install a callback function, you would pass the address of your callback function, and during the printjob, you will be passed the original value you passed in the OnAppCallbackData parameter each time your callback function is called. If you do not install a callback function, you simply pass zero in the OnAppCallbackData parameter. The callback fuction is passed the number of "UnitsDone" (the amount completed), the "TotalUnits" (the total number of units that will be processed) and the OnAppCallbackData that you originally passed to the PrintTScrollingWinControlEx() function. Note that while the OnAppCallbackData parameter is prototyped as a pointer sized unsigned integer, any pointer sized value can be passed by using typecasting. In other words, you could pass a pointer or object reference (such as a form reference or a reference to a TMemo) by using typecasting. This is demonstrated in the example given below for the PrintTScrollingWinControlEx() function. Note that this function may be called several times with the same value for "UnitsDone". Please also note that this is a pure stand alone callback function and not a TEvent or a method. The prototype for the callback function looks like this:

function AppPrintingCallbackFn(UnitsDone : DWORD;
                               TotalUnits : DWORD;
                               UserData : PRNFORM_PTR_AS_UINT) : BOOL; stdcall;
begin
 {Return TRUE to continue the printjob or FALSE to abort the the printjob}
  result := TRUE;
end;

The OnPaintCallbackEvent is an optional event that allows your application to trap (or hook) the rendering of the contols OnPaint event during the print job, and optionally paint the area yourself. This can be useful should you wish to take over the OnPaint event during the print job and paint something different (or perhaps nothing at all). If you do not care to install this hook, simply pass nil for this paramter. The prototype for the callback event looks like this:

function TForm1.OnPaintCallbackEvent(dc : HDC) : BOOL;
begin
 {Handle the painting yourself here and return TRUE, or return FALSE}
 {and TExcellentFormPrinter will handle the call for you!}
  result := FALSE;
end;

The OnPaintControlCallbackEvent is an optional event that allows your application to trap (or hook) the rendering of each control that gets printed during the print job, and optionally paint the control yourself. This can be useful should you wish to take over the rendering of a problematic control. From time to time, we publish hook code for printing third party problematic controls to our registered users. If you do not care to install this hook, simply pass nil for this paramter. The prototype for the callback event looks like this:

function TForm1.OnPaintControlCallbackEvent(TheControl : TControl;
                                            dc : HDC) : BOOL;
begin
 {You may test to see what kind of contol "TheControl" is (by using the Delphi}
 {"IS" operator or the PrintForms "HasClass" function, and selectively}
 {handle the painting yourself and return TRUE, or you may return FALSE and}
 {TExcellentFormPrinter will handle the call for you! The coordinates to}
 {paint to are (0,0), as the dc's offset has been already been adjusted to}
 {account for the left, top of the control}
  result := FALSE;
end;

Additional options are set by passing a pointer to a TPrintFormData structure in the lpPrintFormData parameter.

Returns TRUE if successful.

Example notes: This complete (and intimidating) example prints a form, stretched across multiple pages. This example uses functions from the PrnUtils unit. Please refer to the PrnUtils documentation for additional information.

Example:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    procedure WMShowWindow(var M : TMessage); message WM_SHOWWINDOW;
    function OnPaintCallbackEvent(dc : HDC) : BOOL;
    function OnPaintControlCallbackEvent(TheControl : TControl;
                                         dc : HDC) : BOOL;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

uses
  Printers,
  PrnUtils,
  PrnForm;


{disable changes to ShowWindow if we are printing}
procedure TForm1.WMShowWindow(var M : TMessage);
begin
  if ((M.WParam = 0) AND
      (Printer.Printing)) then begin
    m.Result := 1;
    exit;
  end;
  inherited;
end;

{optional form OnPaint callback event}
function TForm1.OnPaintCallbackEvent(dc : HDC) : BOOL;
begin
 {let TExcellentFormPrinter handle it}
  result := FALSE;
end;


{optional form OnPaintControl callback event}
function TForm1.OnPaintControlCallbackEvent(TheControl : TControl;
                                            dc : HDC) : BOOL;
begin
 {let TExcellentFormPrinter handle it}
  result := FALSE;
end;

{define a data type we will use during a callback}
{to update an abort dialog with a status update}
type
  PAppCallbackData = ^TAppCallbackData;
  TAppCallbackData = packed record
    AbortDialog : TAbortDialog; {The abort dialog}
    PageAcross : integer;       {current page printing across}
    PageDown : integer;         {current page printing down}
  end;


{Our optional status update callback event}
function AppPrintingCallbackFn(UnitsDone : DWORD;
                               TotalUnits : DWORD;
                               UserData : PRNFORM_PTR_AS_UINT) : BOOL; stdcall;
var
  s : string;
  TheData : PAppCallbackData;
begin
 {cast UserData into a useable form}
  TheData := PAppCallbackData(UserData);
 {Update the abort dialogs caption to give a status update}
  s := 'Printing Page ' +
       IntToStr(TheData^.PageAcross) +
       ':' +
       IntToStr(TheData^.PageDown) +
       ' - ' +
       IntToStr(Trunc(((UnitsDone / TotalUnits) * 100))) +
       '%';
  AbortDialogSetCaption(TheData^.AbortDialog,
                        pChar(s));
 {return if the user has canceled the print job.}
  result := (NOT AbortDialogUserHasCanceled(TheData^.AbortDialog));
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  PagesWide : integer;                {How many pages wide you want.}
  PagesHigh : integer;                {How many pages high you want.}
  CenterFormOnPage : BOOL;            {Center on the page or print at the top left corner}
  AbortDialog : TAbortDialog;         {The Abort Dialog}
  AppCallbackData : TAppCallbackData; {Our callback data structure}
  PrnPageInfo : TPrnPageInfo;         {Info about the page to be printed}
  VirtualFormSize : TSize;            {Size of the form (including non visible scrolled areas}
  TotalImageWidth : integer;          {Total width of the printout (including multiple pages)}
  TotalImageHeight : integer;         {Total height of the printout (including multiple pages)}
  ScaleX : double;                    {How much the form gets stretched in the x direction}
  ScaleY : double;                    {How much the form gets stretched in the y direction}
  PrintedFormWidth : integer;         {Total printed width of the form (including multiple pages)}
  PrintedFormHeight : integer;        {Total printed height of the form (including multiple pages)}
  PrintedFormOffset : TPoint;         {How much to offset the form to print it centered on the page(s)}
  i : integer;                        {Loop variable (for i := 1 to PagesHigh do)}
  j : integer;                        {Loop variable (for j := 1 to PagesWide do)}
  SaveIndex : integer;                {Used to save the state of the printer}
  AnAbortCaption : string;            {Used to update the abort dialog}
  PageRect : TRect;                   {The clipping rectangle for the page}
  PrintFormData : TPrintFormData;     {Additional parameters}
begin
 {how many pages to print across and down}
  PagesWide := 2;
  PagesHigh := 2;

 {center the output on the page? (FALSE prints the form at the top left of the page).}
  CenterFormOnPage := TRUE;

  FillChar(PrintFormData,
           sizeof(PrintFormData),
           0);
  PrintFormData.StrucSize := sizeof(PrintFormData);

 {Note: We are done with configurable print choices!}

 {disable the window so the user cannot click on anything while we are printing.}
  EnableWindow(self.Handle,
               FALSE);

 {try to fire up the printjob!}
  try
    Printer.BeginDoc;
  except
   {error! clean up and bail out!}
    EnableWindow(self.Handle,
                 TRUE);
    ShowMessage('Printer corrupt or not installed!');
    exit;
  end;

 {create our abort dialog}
  AbortDialog := CreateAbortDialog(Application.Handle,
                                   self);

 {Set our static callback information}
  AppCallbackData.AbortDialog := AbortDialog;

 {get the page information}
  GetPrnPageInfo(Printer.Handle,
                 @PrnPageInfo);

 {do some calculations to stretch and position}
 {the form to fit the page (or pages).}
  PageRect.Left := 0;
  PageRect.Top := 0;
  PageRect.Right := PrnPageInfo.AdjustedPageArea.x;
  PageRect.Bottom := PrnPageInfo.AdjustedPageArea.y;
  VirtualFormSize := VirtualClientSize(self);
  TotalImageWidth := PagesWide * PrnPageInfo.AdjustedPageArea.x;
  TotalImageHeight := PagesHigh * PrnPageInfo.AdjustedPageArea.y;
  ScaleX := TotalImageWidth / VirtualFormSize.cx;
  ScaleY := TotalImageHeight / VirtualFormSize.cy;
  if (ScaleX < ScaleY) then begin
    PrintedFormWidth := TotalImageWidth;
    PrintedFormHeight := Trunc(VirtualFormSize.cy * ScaleX);
    PrintedFormOffset.x := 0;
    PrintedFormOffset.y := (TotalImageHeight div 2) - (PrintedFormHeight div 2);
  end else begin
    PrintedFormHeight := TotalImageHeight;
    PrintedFormWidth := Trunc(VirtualFormSize.cx * ScaleY);
    PrintedFormOffset.x := (TotalImageWidth div 2) - (PrintedFormWidth div 2);
    PrintedFormOffset.y := 0;
  end;
  if (NOT CenterFormOnPage) then begin
    PrintedFormOffset.x := 0;
    PrintedFormOffset.y := 0;
  end;

 {loop through and print the pages!}
  for i := 1 to PagesHigh do begin
    for j := 1 to PagesWide do begin

     {set our dynamic callback information}
      AppCallbackData.PageAcross := j;
      AppCallbackData.PageDown := i;


     {set the abort dialog's caption to give the user a status update}
      AnAbortCaption := 'Printing Page ' +
                        IntToStr(j) +
                        ':' +
                        IntToStr(i) +
                        ' - 0%';
      AbortDialogSetCaption(AbortDialog,
                            pChar(AnAbortCaption));

     {test to see if the user canceled the print job}
      if (AbortDialogUserHasCanceled(AbortDialog)) then begin
       {user canceled the print job - clean up and bail out!}
        Printer.Abort;
        FreeAbortDialog(AbortDialog);
        EnableWindow(self.Handle,
                     TRUE);
        ShowMessage('Printing Aborted!');
        exit;
      end;

     {save the printer state}
      SaveIndex := SaveDc(Printer.Canvas.Handle);

     {move our origin to account for a perfect printing margin}
      MoveWindowOrg(Printer.Canvas.Handle,
                    PrnPageInfo.AdjustedMarginOffset.x,
                    PrnPageInfo.AdjustedMarginOffset.y);

     {allow drawing only within our prefect margins}
      IntersectClipRect(Printer.Canvas.Handle,
                        0,
                        0,
                        PrnPageInfo.AdjustedPageArea.x,
                        PrnPageInfo.AdjustedPageArea.y);

     {Print the form! We will need to "back up" the offset of where we print}
     {the form to account for printing across multiple pages. No need to fear,}
     {TExcellentPrinter will allow us to print up to 2 billion pixels high}
     {and wide, even under Windows 95 and 98!}
      if (NOT PrintTScrollingWinControlEx(self,
                                          Printer.Canvas.Handle,
                                          -((j - 1) * PrnPageInfo.AdjustedPageArea.x) + PrintedFormOffset.x,
                                          -((i - 1) * PrnPageInfo.AdjustedPageArea.y) + PrintedFormOffset.y,
                                          PrintedFormWidth,
                                          PrintedFormHeight,
                                          PageRect,
                                          AppPrintingCallbackFn,
                                          PRNFORM_PTR_AS_UINT(@AppCallbackData),
                                          OnPaintCallbackEvent,
                                          OnPaintControlCallbackEvent,
                                          @PrintFormData)) then begin
       {this will happen if the user has canceled the print job}
       {or an error occured. Clean up and bail out!}
        RestoreDc(Printer.Canvas.Handle,
                  SaveIndex);
        FreeAbortDialog(AbortDialog);
        Printer.Abort;
        EnableWindow(self.Handle,
                     TRUE);
        ShowMessage('Printing Aborted!');
        exit;
      end;

     {we can print a lovely page caption here!}
      Printer.Canvas.Font.Name := 'Arial';
     {fix a VCL issue that pops up sometimes with font scaling!}
      Printer.Canvas.Font.PixelsPerInch := PrnPageInfo.DPI.y;
      Printer.Canvas.Font.Size := 10;
      Printer.Canvas.TextOut(0,
                             0,
                             'Printing Page ' +
                             IntToStr(j) +
                             ':' +
                             IntToStr(i));

     {we are done printing on this page, restore the printer state!}
      RestoreDc(Printer.Canvas.Handle,
                SaveIndex);

     {if not the last page, we need to call NewPage!}
      if (NOT ((j = PagesWide) AND
               (i = PagesHigh))) then begin
        Printer.NewPage;
      end;
    end;
  end;

 {We are done! Time to clean up!}
  FreeAbortDialog(AbortDialog);
  Printer.EndDoc;
  EnableWindow(self.Handle,
               TRUE);
  ShowMessage('Printing Completed!');
end;

end.

Back to Functions and Structures


TScrollingWinControl

A VCL Class that many Windows components (such as a Form or TScrollBox) descend from.

Back to Functions and Structures


HasClass

function HasClass(AObject : TControl;
                  const AClassName : string) : BOOL;

Location: PrnForm.pas

Returns TRUE if the given control descends from a given class. AClassName is case sensitive. This function works in a similar manner as the Delphi "IS" operator, however it may be safer to use when working in a DLL environment.

Back to Functions and Structures


TPrintFormData

type
  PPrintFormData = ^TPrintFormData;
  TPrintFormData = packed record
    StrucSize : DWORD;
    UseAbortDialog : BOOL;
    DoNotFlushGDICalls : BOOL;
    Use24BitOutputOnly : BOOL;
  end;

Location: PrnForm.pas

The TPrintFormData structure is used with the PrintFormEx() functions, and allows us to add additional functionality in future releases without requiring you to make changes to your code (unless you wish to take advantage of the additional functionality). The only member of this structure that is required to be initialized is the StrucSize member. All other members are designed to default to zero values. The TPrintFormData members are currently defined as:

StrucSize : The size of the TPrintFormData structure. Required.

UseAbortDialog : If TRUE, an Abort/Status dialog is displayed while the form is being printed, and allows the user to cancel the print job.

DoNotFlushGDICalls : The PrintForm engine makes frequent calls to the Windows API GDIFlush() function. If this member is TRUE, we will not call the GDIFlush(). This is intended for experienced users who are writing multi-threaded printing applications.

Use24BitOutputOnly : The PrintForm engine prints in sections, and automatically analyzes each output section to obtain the minimum color depth required for that section, and outputs a bitmap for that section using the minimum number of colors required. This can substantially reduce the printing, transmission and resource overhead for the print job. If this member is set to TRUE, then this optimization is turned off, and all sections are sent as 24 bit True Color bitmaps.

Back to Functions and Structures


VirtualClientSize

function VirtualClientSize(AControl : TControl) : TSize;

Location: PrnForm.pas

Returns the total size of a controls client area, including any area that may be scrolled out of view (if the control descends from a TScrollingWinControl).

Note: A TSize structure is equivalent to a TPoint structure where the x and y members are named .cx and .cy.

Back to Functions and Structures


VirtualClientScrolledOffset

function VirtualClientScrolledOffset(AControl : TControl) : TPoint;

Location: PrnForm.pas

Returns the current offset of a controls client area (the amount the control is scrolled) if the control descends from a TScrollingWinControl, otherwise returns (0,0).

Back to Functions and Structures


PrnFormSetDebugMsg

procedure PrnFormSetDebugMsg(value : BOOL);

Location: PrnForm.pas

This function (when set to TRUE) causes a Windows messagebox to be displayed in the event that the Windows StretchDIBits, BitBlt, MoveTo, or LineTo functions fail. Should you use this function, you should also call the PrnFormSetAbortDialogHandle() to set the parent window of any messageboxes that are displayed, else the messageboxes may not appear on the screen, but may in fact show up on the taskbar. Should any messageboxes appear, this indicates that the problem is most likely downstream from TExcellentFormPrinter, but can also be caused by memory corruption in the VCL or your application, especially in multi-threaded applications.

The default value is FALSE.

Example:

uses
  Printers,
  PrnUtils,
  PrnForm;

procedure TForm1.Menu1Click(Sender: TObject);
begin
  Printer.BeginDoc;
  PrnFormSetDebugMsg(TRUE);
  PrnFormSetAbortDialogHandle(self.Handle);
  PrintForm(self,
            Printer.Canvas.Handle,
            TRUE,
            TRUE);
  Printer.EndDoc;
end;

Back to Functions and Structures


PrnFormSetAbortDialogHandle

function PrnFormSetAbortDialogHandle(value : THandle) : THandle;

Location: PrnForm.pas

This function informs the TExcellentFormPrinter engine of the handle of a status windows you may be displaying during the print job, allowing any error messageboxes to display on top of your status window. Failure to set this value may cause any error messageboxes to be shown with the Windows desktop as the owner.

This value only has meaning when PrnFormSetDebugMsg() is set to TRUE.

The default value is 0.

Returns:
The previous window handle.

Example:

uses
  Printers,
  PrnUtils,
  PrnForm;

procedure TForm1.Menu1Click(Sender: TObject);
begin
  Printer.BeginDoc;
  PrnFormSetDebugMsg(TRUE);
  PrnFormSetAbortDialogHandle(self.Handle);
  PrintForm(self,
            Printer.Canvas.Handle,
            TRUE,
            TRUE);
  Printer.EndDoc;
end;

Back to Functions and Structures


PrnFormSetDebugDoBlt

procedure PrnFormSetDebugDoBlt(value : BOOL);

Location: PrnForm.pas

This function (when set to FALSE) causes TExcellentFormPrinter to go through its normal code except it does not actually transfer the bitmap to the GDI (ie, you will get a blank sheet of paper, unless the PrnFormSetDebugFrames is set to TRUE.

If you get a crash in the TExcellentFormPrinter unit (using the standard supported list of controls) in a simple test app, then it is likly you have exposed a problem in the TExcellentFormPrinter code. Please alert us as soon as possible so that we may take steps to correct the problem and publish a fix (if it can be determined that TExcellentFormPrinter actually caused the problem).

The default value is TRUE.

Example:

uses
  Printers,
  PrnUtils,
  PrnForm;

procedure TForm1.Menu1Click(Sender: TObject);
begin
  Printer.BeginDoc;
  PrnFormSetDebugDoBlt(FALSE);
  PrnFormSetDebugFrames(TRUE);
  PrintForm(self,
            Printer.Canvas.Handle,
            TRUE,
            TRUE);
  Printer.EndDoc;
end;

Back to Functions and Structures


PrnFormSetDebugUseDDB

procedure PrnFormSetDebugUseDDB(value : BOOL);

Location: PrnForm.pas

This function (when set to TRUE) causes TExcellentFormPrinter to internally use a Device Dependent Bitmap (as opposed to Device Independent Bitmap), and transfer the bitmap using the Windows API function BitBlt(), (as opposed to using the Windows API function StretchDIBits().

Please note that if a call to StretchDIBits() fails, the TExcellentFormPrinter default recovery plan is to switch to using device dependent bitmaps and transfer the bitmap using the Windows API function BitBlt(). This automatic recovery logic can be controlled by the use of the PrnFormSetDebugAutoUseDDB() function. A word of warning: Some printers will claim that StretchDIBits() was successfull, even though the call actually failed. For those printers, your application should still provide a way for the user to force the use of device dependent bitmaps using a call to the PrnFormSetDebugUseDDB() function.

We have found that some printers report that they support the Windows StretchDIBits() function, however, calls to the StretchDIBits() function will sometimes fail on some printers. This function provides a workaround for buggy print drivers. Note that for printers that do not support the Windows StretchDIBits() function, it is still safe to call the StretchDIBits() function, as Windows should automatically simulate the call using lower level driver calls.

Note that the Device Dependent Bitmap that is created is based on the context of the output device. This implies that the bitmap created will most likly be a monochrome bitmap with one bit of color depth. Note that most devices do not provide for reasonable dithering of colors to a monochrome bitmap, so color translation may be lost.

The default value is FALSE.

Example:

uses
  Printers,
  PrnUtils,
  PrnForm;

procedure TForm1.Menu1Click(Sender: TObject);
begin
  Printer.BeginDoc;
  PrnFormSetDebugUseDDB(FALSE);
  PrintForm(self,
            Printer.Canvas.Handle,
            TRUE,
            TRUE);
  Printer.EndDoc;
end;

Back to Functions and Structures


PrnFormSetDebugAutoUseDDB

procedure PrnFormSetDebugAutoUseDDB(value : BOOL);

Location: PrnForm.pas

Normally, TExcellentFormPrinter uses Device Independent Bitmaps and the Windows API function StretchDIBits() to transfer images. This function (when set to TRUE) causes TExcellentFormPrinter first try using Device Independent Bitmaps and the StretchDIBits() function. If the StretchDIBits() function fails, then TExcellentFormPrinter will automatically switch to using device dependent bitmaps and attempt to transfer bitmaps using the Windows API function BitBlt().

Please note that some printers will claim that StretchDIBits() was successful, even though the call actually failed. For those printers, your application should provide a way for the user to force the use of device dependent bitmaps using a call to the PrnFormSetDebugUseDDB() function.

We have found that some printers report that they support the Windows StretchDIBits() function, however, calls to the StretchDIBits() function will sometimes fail on some printers. This function provides a workaround for buggy print drivers. Note that for printers that do not support the Windows StretchDIBits() function, it is still safe to call the StretchDIBits() function, as Windows should automatically simulate the call using lower level driver calls.

Note that the Device Dependent Bitmap that is created is based on the context of the output device. This implies that the bitmap created will most likly be a monochrome bitmap with one bit of color depth. Note that most devices do not provide for reasonable dithering of colors to a monochrome bitmap, so color translation may be lost.

The default value is TRUE.

Example:

uses
  Printers,
  PrnUtils,
  PrnForm;

procedure TForm1.Menu1Click(Sender: TObject);
begin
  Printer.BeginDoc;
  PrnFormSetDebugAutoUseDDB(FALSE);
  PrintForm(self,
            Printer.Canvas.Handle,
            TRUE,
            TRUE);
  Printer.EndDoc;
end;

Back to Functions and Structures


PrnFormSetDebugFrames

procedure PrnFormSetDebugFrames(value : BOOL);

Location: PrnForm.pas

This function (when set to TRUE) causes TExcellentFormPrinter to print cross-hairs through each "chunk" that is printed. This is useful for testing where the image chunks would be printed, and is often used with the PrnFormSetDebugDoBlt(FALSE) setting for debugging purposes.

The default value is FALSE in the registered versions of the product, and is automatically set to TRUE in the trial versions.

Example:

uses
  Printers,
  PrnUtils,
  PrnForm;

procedure TForm1.Menu1Click(Sender: TObject);
begin
  Printer.BeginDoc;
  PrnFormSetDebugFrames(TRUE);
  PrintForm(self,
            Printer.Canvas.Handle,
            TRUE,
            TRUE);
  Printer.EndDoc;
end;

Back to Functions and Structures


PrnFormSetSleepValue

procedure PrnFormSetSleepValue(value : integer);

Location: PrnForm.pas

This function (when set a value of zero or greater) causes TExcellentFormPrinter call the Windows API function Sleep(value) between each image transfer function, and may provide some relief for buggy 3rd party spooler software that may be installed with some printer drivers, by allowing the spooler to catch up with the image data that is sent.

The default value is -1.

Example:

uses
  Printers,
  PrnUtils,
  PrnForm;

procedure TForm1.Menu1Click(Sender: TObject);
begin
  Printer.BeginDoc;
  PrnFormSetSleepValue(1000);
  PrintForm(self,
            Printer.Canvas.Handle,
            TRUE,
            TRUE);
  Printer.EndDoc;
end;

Back to Functions and Structures


PrnFormSetOutputScaleFactor

procedure PrnFormSetOutputScaleFactor(x : integer;
                                      y : integer);

Location: PrnForm.pas

The TExcellentFormPrinter default behavior is output form images pre-scaled to the full resolution of the printer. This can produce large print jobs. This function reduces the resolution of the output by the scale factor given, and asks the print driver to enlarge the output by the same amount. In other words, a scale factor of 2 reduces the resolution of the output by 2, and the print driver will enlarge the output by 2. Reducing the resolution by a factor of 2 should provide a four times reduction in the amount of data spooled, and reducing the resolution by a factor of 4 should provide a sixteen times reduction in the amount of data spooled. For reliability, the scale factor should always be less than 8. A scale factor of (1,1) (the default value) outputs form images at the full resolution of the device. Note that printing systems with intellegent pre-processors may not actually reduce the amount of output generated, as the pre-processor may compress image data at the full resolution of the printer, however, some systems may greatly benefit from resolution reduction, and the gains measured may actually be double the expected amount. On high resolution printers, a scaling factor of (2,2) often provides output that appears identical to using the full resolution of the device.

The default value is (1,1).

Example:

uses
  Printers,
  PrnUtils,
  PrnForm;

procedure TForm1.Menu1Click(Sender: TObject);
begin
  Printer.BeginDoc;
  PrnFormSetOutputScaleFactor(2, 2);
  PrintForm(self,
            Printer.Canvas.Handle,
            TRUE,
            TRUE);
  Printer.EndDoc;
end;

Back to Functions and Structures


PrnFromSetDoWinScale

procedure PrnFormSetDoWinScale(value : BOOL);

Location: PrnForm.pas

The TExcellentFormPrinter default behavior is output form images pre-scaled to the full resolution of the printer. This can produce large print jobs. This function (when set to true) causes "form image chunks" to be sent to the printer for re-scaling. If the form you are printing is to be enlarged, this can amount to a significant savings in print job size. If the form you are printing is to be reduced, this can amount to a significant enlargement in print job size. This function responds to scaling factors introduced by the PrnFormSetOutputScaleFactor() function.

The default value is FALSE.

Example:

uses
  Printers,
  PrnUtils,
  PrnForm;

procedure TForm1.Menu1Click(Sender: TObject);
begin
  Printer.BeginDoc;
  PrnFormSetDoWinScale(TRUE);
  PrintForm(self,
            Printer.Canvas.Handle,
            TRUE,
            TRUE);
  Printer.EndDoc;
end;

Back to Functions and Structures


Validate HTML