TExcellentImagePrinter Delphi Documentation Version 0A.2.3

Copyright © 1989-2010 by Joe C. Hecht All Rights Reserved
Copyright © 2011-2018 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 *).


Bitmap Primer

Functions and structures:

Installation
PrintDIBitmap
PrintDIBitmapXY
PrintDIBitmapCB
PrintDIBitmapEx
PrnDIBSetDebugMsg
PrnDIBSetAbortDialogHandle
PrnDIBSetDebugBlt
PrnDIBSetDebugBltCode
PrnDIBSetDebugUseDDB
PrnDIBSetDebugAutoUseDDB
PrnDIBSetDebugFrames
PrnDIBSetSleepValue
PrnDIBSetDebugPaletteNone
PrnDIBSetDebugPaletteForce
PrnDIBSetDebugPaletteNotAllowed
PrnDIBSetDebugDcSaves
PrnDIBSetDebugGdiFlush
PrnDIBSetOutputScaleFactor
PrnDIBSetDoWinScale


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


PrintDIBitmap

function PrintDIBitmap(dc : HDC;
                       lpBitmapInfo : PBITMAPINFO;
                       lpBits : Pointer;
                       Centered : BOOL;
                       UsePerfectMargins : BOOL) : integer; stdcall;

Location: PrnDib.pas

Images a Device Independent Bitmap onto dc (Canvas.Handle). Stretches the image proportionally to fit the device. The lpBitmapInfo parameter is a pointer to a BitmapInfo or a BitmapCoreInfo structure. The lpBits parameter is a pointer to the DIB bits. 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. It is recommended that you use one of the LoadDIB() functions contained in our PrnUtils unit to get your BitmapInfo and DIB bits pointers.

Returns:

const PRINT_SUCCESSFUL = 1;
const NOTHING_TO_PRINT = 0;
const BAD_PARAMETER = -1;
const MEMORY_ALLOC_FAILED = -2;
const MEMORY_READ_FAILED = -3;
const MEMORY_WRITE_FAILED = -4;
const USER_ABORT_OR_OTHER_ERROR = -5;

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrintDIBitmapXY

function PrintDIBitmapXY(dc : HDC;
                         dstx : integer;
                         dsty : integer;
                         dstWidth : integer;
                         dstHeight : integer;
                         lpBitmapInfo : PBITMAPINFO;
                         lpBits : Pointer) : integer; stdcall;

Location: PrnDib.pas

Images a Device Independent Bitmap onto dc (Canvas.Handle) at dstx, dsty, and stretches the image to dstWidth, dstHeight. The lpBitmapInfo parameter is a pointer to a BitmapInfo or a BitmapCoreInfo structure. The lpBits parmeter is a pointer to the DIB bits. It is recommended that you use one of the LoadDIB() functions contained in our PrnUtils unit to get your BitmapInfo and DIB bits pointers.

Returns:

const PRINT_SUCCESSFUL = 1;
const NOTHING_TO_PRINT = 0;
const BAD_PARAMETER = -1;
const MEMORY_ALLOC_FAILED = -2;
const MEMORY_READ_FAILED = -3;
const MEMORY_WRITE_FAILED = -4;
const USER_ABORT_OR_OTHER_ERROR = -5;

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrintDIBitmapXY(Printer.Canvas.Handle,
                  0,
                  0,
                  BitmapWidth,
                  BitmapHeight,
                  BitmapInfo,
                  Bits);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrintDIBitmapCB

function PrintDIBitmapCB(dc : HDC;
                         lpBitmapInfo : PBITMAPINFO;
                         lpBits : Pointer;
                         Centered : BOOL;
                         UsePerfectMargins : BOOL,
                         OnAppCallbackFn : TAppCallbackFn;
                         OnAppCallbackData : PRNDIB_PTR_AS_UINT) : integer; stdcall;

Location: PrnDib.pas

Images a Device Independent Bitmap onto dc (Canvas.Handle). Stretches the image proportionally to fit the device. The lpBitmapInfo parameter is a pointer to a BitmapInfo or a BitmapCoreInfo structure. The lpBits parmeter is a pointer to the DIB bits. 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. The OnAppCallbackFn is an optional callback function that you may install to track the progess of the imaging and optionally provide real time status updates to your user (perhaps by using a progress meter) as well as allowing you to cancel the imaging 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 image job, 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 function 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 PrintDIBitmapEx() 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. Note that this callback 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 : PRNDIB_PTR_AS_UINT) : BOOL; stdcall;
begin
 {Return TRUE to continue the printjob or FALSE to abort the printjob}
  result := TRUE;
end;


It is recommended that you use one of the LoadDIB() functions contained in our PrnUtils unit to get your BitmapInfo and DIB bits pointers.

Returns:

const PRINT_SUCCESSFUL = 1;
const NOTHING_TO_PRINT = 0;
const BAD_PARAMETER = -1;
const MEMORY_ALLOC_FAILED = -2;
const MEMORY_READ_FAILED = -3;
const MEMORY_WRITE_FAILED = -4;
const USER_ABORT_OR_OTHER_ERROR = -5;

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

{A callback function for updating an image printer abort dialog!}
function ImagePrinterCallbackFunction(UnitsDone : DWORD;
                                      TotalUnits : DWORD;
                                      AbortDialog : TAbortDialog) : BOOL; stdcall;
var
  s : string;
begin
 {Update the abort dialogs caption to give a status update}
  s := 'Printing - ' +
       IntToStr(Trunc(((UnitsDone / TotalUnits) * 100))) +
       '%';
  AbortDialogSetCaption(AbortDialog,
                        pChar(s));
 {Should we continue?}
  result := (NOT AbortDialogUserHasCanceled(AbortDialog));
end;


{Print test.bmp scaled to a full page - with abort dialog!}
procedure TForm1.PrintImageClick(Sender: TObject);
var
  AbortDialog : TAbortDialog;    {The abort dialog}
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;

 {Create the abort dialog}
  AbortDialog := CreateAbortDialog(Application.Handle, self);
  PrnDIBSetAbortDialogHandle(AbortDialog.Handle);

  PrintDIBitmapCB(Printer.Canvas.Handle,
                  BitmapInfo,
                  Bits,
                  TRUE,
                  TRUE,
                  @ImagePrinterCallbackFunction,
                  PRNDIB_PTR_AS_UINT(AbortDialog));

  FreeAbortDialog(AbortDialog);
  PrnDIBSetAbortDialogHandle(0);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrintDIBitmapEx

function PrintDIBitmapEx(dc : HDC;
                         dstx : integer;
                         dsty : integer;
                         dstWidth : integer;
                         dstHeight : integer;
                         srcx : integer;
                         srcy : integer;
                         srcWidth : integer;
                         srcHeight : integer;
                         lpBitmapInfo : PBITMAPINFO;
                         lpBits : Pointer;
                         Palette : HPALETTE;
                         ForcePalette : BOOL;
                         DoNotUsePalette : BOOL;
                         DeviceClipRect : TRect;
                         OnAppCallbackFn : TAppCallbackFn;
                         OnAppCallbackData : PRNDIB_PTR_AS_UINT) : integer; stdcall;

Location: PrnDib.pas

Images a Device Independent Bitmap onto dc (Canvas.Handle) at dstx, dsty, and stretches the image to dstWidth, dstHeight. srcx is horizontal position in the image to start the printout and srcy is the vertical position in the image to start the printout. srcWidth is the horizontal width of the source image to print, and srcHeight is the vertical height of the source image to print. NOTE: (srcx + srcWidth) or (srcy + srcHeight) cannot exceed the bitmap size, and srcx and srcy may not be negitive. The lpBitmapInfo parameter is a pointer to a BitmapInfo or a BitmapCoreInfo structure. The lpBits parmeter is a pointer to the DIB bits. It is recommended that you use one of the LoadDIB() functions contained in our PrnUtils unit to get your BitmapInfo and DIB bits pointers. Palette is an optional handle to a windows palette. If the palette is zero, and the device is a palette device, then TExcellentImagePrinter will attempt to create a palette in your behalf automatically and select it into the device context. ForcePalette is the value passed to the Windows SelectPalette() function. DoNotUsePalette is a boolean value used to disable palette handling. If this parameter is set to TRUE, then you are responsible for selecting and realizing the palette (if any) for the dc before and after the function call. In this case,you should set the Palette parameter to zero, and the ForcePalette parameter will be ignored. The DeviceClipRect parameter specifies the area of the device to clip output to, and should be no larger than the device surface. The DeviceClipRect parameter is useful in stretching the output to span across multiple pages (up to 2 billion pixels high and wide), and allows the Print 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 imaging and optionally provide real time status updates to your user (perhaps by using a progress meter) as well as allowing you to cancel the imaging 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 image job, 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 function 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 PrintDIBitmapEx() 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. Note that this callback 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 : PRNDIB_PTR_AS_UINT) : BOOL; stdcall;
begin
 {Return TRUE to continue the printjob or FALSE to abort the the printjob}
  result := TRUE;
end;

Returns:

const PRINT_SUCCESSFUL = 1;
const NOTHING_TO_PRINT = 0;
const BAD_PARAMETER = -1;
const MEMORY_ALLOC_FAILED = -2;
const MEMORY_READ_FAILED = -3;
const MEMORY_WRITE_FAILED = -4;
const USER_ABORT_OR_OTHER_ERROR = -5;

Example:

Note: This is a complex print bitmap example - uses default printer, allows for centering on page, perfect even margines, scaling the image *very large* to span multiple pages across and down, and provides a status/abort dialog using the optional callback function. The number of pages to span is hardcoded in the main function, and the image is scaled proportionally to fit the printout.

uses
  Printers,
  PrnUtils,
  PrnDIB;

{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;       {The current page across}
    PageDown : integer;         {The current page down}
  end;


{our optional status update callback event}
function AppCallbackFn(UnitsDone : DWORD;
                       TotalUnits : DWORD;
                       UserData : PRNDIB_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));
 {Should we continue?}
  result := (NOT AbortDialogUserHasCanceled(TheData^.AbortDialog));
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  BitmapInfo : PBITMAPINFO;           {pointer to a BitmapInfo structure}
  Bits : pointer;                     {pointer to the bits}
  BitmapWidth : integer;              {bitmap width}
  BitmapHeight : integer;             {bitmap height}
  ReturnValue : integer;              {success or error code}
  PagesWide : integer;                {How many pages wide you want.}
  PagesHigh : integer;                {How many pages high you want.}
  CenterImageOnPage : 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}
  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 image gets stretched in the x direction}
  ScaleY : double;                    {How much the image gets stretched in the y direction}
  PrintedImageWidth : integer;        {Total printed width of the image (including multiple pages)}
  PrintedImageHeight : integer;       {Total printed height of the umage (including multiple pages)}
  PrintedImageOffset : TPoint;        {How much to offset the image 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}
  APageCaption : string;              {Used to print a caption on the page and update the abort dialog}
  PageRect : TRect;                   {The clipping rectangle for the page}
begin

 {How many pages to print across and down - you may change this}
  PagesWide := 2;
  PagesHigh := 2;

 {Center the output on the page? (FALSE prints the image at the top left of the page).}
 {Note that on large printouts - some pages may be blank if you choose to center}
 {the printout, as it will truly center the image, and some pages may not contain}
 {any part of the image}
  CenterImageOnPage := TRUE;

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

 {Are we printing something right now?}
  if (Printer.Printing) then begin
    ShowMessage('Already printing... Please try again later!');
    exit;
  end;

 {Load a bitmap}
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
 end;

 {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!');
    FreeMemEx(BitmapInfo);
    FreeMemEx(Bits);
    exit;
  end;

 {create our abort dialog}
  AbortDialog := CreateAbortDialog(Application.Handle,
                                   self);
  if (AbortDialog = nil) then begin
   {error! clean up and bail out!}
    Printer.Abort;
    EnableWindow(self.Handle,
                 TRUE);
    ShowMessage('Abort dialog could not be created!');
    FreeMemEx(BitmapInfo);
    FreeMemEx(Bits);
    exit;
  end;

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

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

 {do some calculations to stretch and position}
 {the image to fit the page (or pages).}
  PageRect.Left := 0;
  PageRect.Top := 0;
  PageRect.Right := PrnPageInfo.AdjustedPageArea.x;
  PageRect.Bottom := PrnPageInfo.AdjustedPageArea.y;
  TotalImageWidth := PagesWide * PrnPageInfo.AdjustedPageArea.x;
  TotalImageHeight := PagesHigh * PrnPageInfo.AdjustedPageArea.y;
  ScaleX := TotalImageWidth / BitmapWidth;
  ScaleY := TotalImageHeight / BitmapHeight;
  if (ScaleX < ScaleY) then begin
    PrintedImageWidth := TotalImageWidth;
    PrintedImageHeight := Trunc(BitmapHeight * ScaleX);
    PrintedImageOffset.x := 0;
    PrintedImageOffset.y := (TotalImageHeight div 2) - (PrintedImageHeight div 2);
  end else begin
    PrintedImageHeight := TotalImageHeight;
    PrintedImageWidth := Trunc(BitmapWidth * ScaleY);
    PrintedImageOffset.x := (TotalImageWidth div 2) - (PrintedImageWidth div 2);
    PrintedImageOffset.y := 0;
  end;
  if (NOT CenterImageOnPage) then begin
    PrintedImageOffset.x := 0;
    PrintedImageOffset.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 callback information}
      AppCallbackData.PageAcross := j;
      AppCallbackData.PageDown := i;

     {construct a caption for the abort dialog (we will}
     {also print this at the top of each printed page).}
      APageCaption := 'Printing Page ' +
                      IntToStr(j) +
                      ':' +
                      IntToStr(i) +
                      ' - 0%';

     {set the abort dialog's caption to give the user a status update}
      AbortDialogSetCaption(AbortDialog,
                            pChar(APageCaption));

     {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);
        FreeMemEx(BitmapInfo);
        FreeMemEx(Bits);
        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 image! We will need to "back up" the offset of where we print}
     {the image to account for printing across multiple pages. No need to fear,}
     {TExcellentImagePrinter will allow us to print up to 2 billion pixels high}
     {and wide, even under Windows 95 and 98!}
     ReturnValue :=
       PrintDIBitmapEx(Printer.Canvas.Handle,
                       -((j - 1) * PrnPageInfo.AdjustedPageArea.x) + PrintedImageOffset.x,
                       -((i - 1) * PrnPageInfo.AdjustedPageArea.y) + PrintedImageOffset.y,
                       PrintedImageWidth,
                       PrintedImageHeight,
                       0,
                       0,
                       BitmapInfo^.bmiHeader.biWidth,
                       BitmapInfo^.bmiHeader.biHeight,
                       BitmapInfo,
                       Bits,
                       0,
                       TRUE,
                       FALSE,
                       PageRect,
                       @AppCallbackFn,
                       PRNDIB_PTR_AS_UINT(@AppCallbackData));
       if (ReturnValue < NOTHING_TO_PRINT) then begin
       {This will happen if the user has canceled the print job}
       {or an error occured. We will not trap the NOTHING_TO_PRINT}
       {error, as when the image is stretched across several pages, it}
       {is possible that a few pages many not contain part of the image}
       {due to page and image centering, and TExcellentImage printer will}
       {report there is nothing to print for those pages. If we have another}
       {kind of error then we will clean up and bail out!}
        RestoreDc(Printer.Canvas.Handle,
                  SaveIndex);
        FreeAbortDialog(AbortDialog);
        Printer.Abort;
        FreeMemEx(BitmapInfo);
        FreeMemEx(Bits);
        EnableWindow(self.Handle,
                     TRUE);
        case (ReturnValue) of
          BAD_PARAMETER : begin
            ShowMessage('BAD_PARAMETER');
          end;
          MEMORY_ALLOC_FAILED : begin
            ShowMessage('MEMORY_ALLOC_FAILED');
          end;
          MEMORY_READ_FAILED : begin
            ShowMessage('MEMORY_READ_FAILED');
          end;
          MEMORY_WRITE_FAILED : begin
            ShowMessage('MEMORY_WRITE_FAILED');
          end;
          USER_ABORT_OR_OTHER_ERROR : begin
            ShowMessage('USER_ABORT_OR_OTHER_ERROR!');
          end;
        end;
        exit;
      end;

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

     {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; {for j := 1 to PagesWide}
  end; {for i := 1 to PagesHigh}

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

Back to Functions and Structures


PrnDIBSetDebugMsg

procedure PrnDIBSetDebugMsg(value : BOOL);

Location: PrnDIB.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 PrnDIBSetAbortDialogHandle() to set the parent window of any messageboxes that are displayed, else the messageboxs 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 TExcellentImagePrinter, but can be also caused by memory corruption in the VCL or your application, especially in multi-threaded applications.

The default value is FALSE.

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetDebugMsg(TRUE);
  PrnDIBSetAbortDialogHandle(self.Handle);
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetAbortDialogHandle

function PrnDIBSetAbortDialogHandle(value : THandle) : THandle;

Location: PrnDIB.pas

This function informs the TExcellentImagePrinter 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 PrnDIBSetDebugMsg() is set to TRUE.

The default value is 0.

Returns:
The previous window handle.

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetDebugMsg(TRUE);
  PrnDIBSetAbortDialogHandle(self.Handle);
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetDebugBlt

procedure PrnDIBSetDebugBlt(value : BOOL);

Location: PrnDIB.pas

This function (when set to FALSE) causes TExcellentImagePrinter 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 PrnDIBSetDebugFrames is set to TRUE.

If you get a crash in the TExcellentImagePrinter unit in a simple test app, then it is likely you have exposed a problem in the TExcellentImagePrinter 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 TExcellentImagePrinter actually caused the problem).

At this point, you should also test the program in question using the PrnDIBSetDebugBltCode function to futher qualify where the problem might be.
The default value is TRUE.

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetDebugBlt(FALSE);
  PrnDIBSetDebugFrames(TRUE);
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetDebugBltCode

procedure PrnDIBSetDebugBltCode(value : BOOL);

Location: PrnDIB.pas

This function (when set to FALSE) causes TExcellentImagePrinter to totally skip its normal code in preparing to output a bitmap chunk. Further, it does not transfer the bitmap to the GDI (ie, you will get a blank sheet of paper, unless the PrnDIBSetDebugFrames is set to TRUE.

If you get a crash in the TExcellentImagePrinter unit in a simple test app, then it is likely you have exposed a problem in the TExcellentImagePrinter 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 TExcellentImagePrinter actually caused the problem).

The default value is TRUE.

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetDebugBltCode(FALSE);
  PrnDIBSetDebugFrames(TRUE);
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetDebugUseDDB

procedure PrnDIBSetDebugUseDDB(value : BOOL);

Location: PrnDIB.pas

This function (when set to TRUE) causes TExcellentImagePrinter 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 TExcellentImagePrinter 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 PrnDIBSetDebugAutoUseDDB() function. A word of warning: Some printers will claim that StretchDIBits() was successful, 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 PrnDIBSetDebugUseDDB() 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 likely 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,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetDebugUseDDB(TRUE);
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetDebugAutoUseDDB

procedure PrnDIBSetDebugAutoUseDDB(value : BOOL);

Location: PrnDIB.pas

Normally, TExcellentImagePrinter uses Device Independent Bitmaps and the Windows API function StretchDIBits() to transfer images. This function (when set to TRUE) causes TExcellentImagePrinter first try using Device Independent Bitmaps and the StretchDIBits() function. If the StretchDIBits() function fails, then TExcellentImagePrinter 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 PrnDIBSetDebugUseDDB() 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 likely 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,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetDebugAutoUseDDB(FALSE);
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetDebugFrames

procedure PrnDIBSetDebugFrames(value : BOOL);

Location: PrnDIB.pas

This function (when set to TRUE) causes TExcellentImagePrinter 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 PrnDIBSetDebugBlt(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,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetDebugFrames(TRUE);
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetSleepValue

procedure PrnDIBSetSleepValue(value : integer);

Location: PrnDIB.pas

This function (when set a value of zero or greater) causes TExcellentImagePrinter 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,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetSleepValue(1000);
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetDebugPaletteNone

procedure PrnDIBSetDebugPaletteNone;

Location: PrnDIB.pas

TExcellentImagePrinter will attempt to use a passed in palette or build and select a palette into the destination device for you, if the device reports that it supports palettes. Using this function sets TExcellentImagePrinter to use default palette handeling behaviour. Generally, most printers do not suppport the use of palettes, and this setting is mainly for use when using TExcellentImagePrinter to print to a Windows memory dc.

Other related fucnctions:

PrnDIBSetDebugPaletteForce
PrnDIBSetDebugPaletteNotAllowed

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetDebugPaletteNone;
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetDebugPaletteForce

procedure PrnDIBSetDebugPaletteForce;

Location: PrnDIB.pas

TExcellentImagePrinter will attempt to use a passed in palette or build and select a palette into the destination device for you, if the device reports that it supports palettes. Using this function sets TExcellentImagePrinter to to force the use of a palette. Generally, most printers do not suppport the use of palettes, and this setting is mainly for use when using TExcellentImagePrinter to print to a Windows memory dc.

Other related functions:

PrnDIBSetDebugPaletteNone
PrnDIBSetDebugPaletteNotAllowed

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetDebugPaletteForce;
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetDebugPaletteNotAllowed

procedure PrnDIBSetDebugPaletteNotAllowed;

Location: PrnDIB.pas

TExcellentImagePrinter will attempt to use a passed in palette or build and select a palette into the destination device for you, if the device reports that it supports palettes. Using this function sets TExcellentImagePrinter to completely disallow the use of palettes. Generally, most printers do not suppport the use of palettes, and this setting is mainly for use when using TExcellentImagePrinter to print to a Windows memory dc.

Other related functions:

PrnDIBSetDebugPaletteNone
PrnDIBSetDebugPaletteForce

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetDebugPaletteNotAllowed;
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetDebugDcSaves

procedure PrnDIBSetDebugDcSaves(value : BOOL);

Location: PrnDIB.pas

TExcellentImagePrinter will attempt to use the Windows API SaveDC() and RestoreDc() functions. It might be possible that this call could fail. Setting this variable to FALSE will cause TExcellentImagePrinter to disregard perfect margins and centering, and will also cause TExcellentImagePrinter not to use the SaveDc(), RestoreDc(), GetWindowOrgEx(), SetWindowOrgEx() and IntersectClipRect() functions. Should setting this variable to TRUE cause a failed print job to print, then it would indicate a serious problem at the print driver level.

The default value is TRUE.

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetDebugDcSaves(FALSE);
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetDebugGdiFlush

procedure PrnDIBSetDebugGdiFlush(value : BOOL);

Location: PrnDIB.pas

TExcellentImagePrinter default behaviour is to use the Windows API call GdiFlush(). Calling this function with a value of FALSE will disable calls to GdiFlush(). Generally, setting this variable is of little help unless you are using threads to produce your print job.

The default value is TRUE.

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetDebugGdiFlush(FALSE);
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetOutputScaleFactor

procedure PrnDIBSetOutputScaleFactor(x : integer;
                                     y : integer); stdcall;

Location: PrnDIB.pas

TExcellentImagePrinter default behaviour is output 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 reliablity, the scale factor should always be less than 8. A scale factor of (1,1) (the default value) outputs 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 appears identical to using the full resolution of the device. This is especially true of photographic images.

The default value is (1,1).

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetOutputScaleFactor(2, 2);
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


PrnDIBSetDoWinScale

procedure PrnDIBSetDoWinScale(value : BOOL); stdcall;

Location: PrnDIB.pas

TExcellentImagePrinter default behaviour is output images pre-scaled to the full resolution of the printer. This can produce large print jobs. This function (when set to true) causes "image chunks" to be sent to the printer for re-scaling. If the image you are printing is to be enlarged, this can amount to a significant savings in print job size. If the image 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 PrnDIBSetOutputScaleFactor() function.

The default value is FALSE.

Example:

uses
  Printers,
  PrnUtils,
  PrnDIB;

var
  BitmapInfo : PBITMAPINFO;      {pointer to a BitmapInfo structure}
  Bits : pointer;                {pointer to the bits}
  BitmapWidth : integer;         {bitmap width}
  BitmapHeight : integer;        {bitmap height}
begin
  if (NOT LoadDIBFromFile('test.bmp',
                          pointer(BitmapInfo),
                          Bits,
                          BitmapWidth,
                          BitmapHeight)) then begin
    ShowMessage('Bitmap load error');
    exit;
  end;
  Printer.BeginDoc;
  PrnDIBSetDoWinScale(TRUE);
  PrintDIBitmap(Printer.Canvas.Handle,
                BitmapInfo,
                Bits,
                TRUE,
                TRUE);
  Printer.EndDoc;
  FreeMemEx(BitmapInfo);
  FreeMemEx(Bits);
  ShowMessage('Printing Completed!');
end;

Back to Functions and Structures


Bitmap Primer:

Windows "Bitmaps" come in two flavors. A Device Dependent Bitmap(DDB), and a Device Independent Bitmap (DIB). A DDB uses a format that is only known to the device that uses it, and should not be directly accessed by an application or another device. DDBstyle bitmaps are very fast, as they are in the native format of the device, however, it is an illegal operation to try to use a DDB bitmap from one device on another device (ie: from the screen to the printer), as the native format each device uses to store bitmaps may be different. If the format is the same on both devices then doing a BLT (pixel copy) operation will be successful, however this practice is highly discouraged. Some device drivers (mainly printers) may be able to detect when you have sent a bitmap based on the screen to the printer, and attempt to print the bitmap anyway, however, this ability is highly specific to certain drivers and driver versions, therefore is not reliable. Note that using StretchDraw or other VCL raster functions to a printer canvas will often send a screen bitmap to the printer, leading to disaster on many printers. Note that this is not the only reason for bitmap printing failures. There are many cavets in bitmap printing to overcome. In the real world of deployed applications, its not as simple to print a bitmap as most examples tend to demonstrate.

As we have already mentioned, a DIB is a device independent bitmap, and can be used with any device. The DIB format is ideal for exchanging and saving bitmap data. A DIB may be encoded in many different formats, however, the formats are well documented, and any decent piece of software should be able to read any of the documented DIB formats (note that the VCL is only partially complient). The different DIB formats may vary in color depth, header encoding, and pixel encoding, however all the DIB formats are very well documented. A DIB consists of between two and five parts, of which, we are only interested in two. The Five parts are:

1) BitmapFileHeader.

2) BitmapInfoHeader (or possibly a BitmapCoreHeader).

3) Possibly a table of bit masks.

4) Possibly a color table.

5) The pixel data.

To use TExcellentImagePrinter, you will need a "pointer" (the address of a block of memory) that holds the BitmapInfoHeader (or BitmapCoreHeader), and a pointer that holds the pixel data for the bitmap you wish to print. Depending on your application, you may alreay have the pointers you wish to use. If not, we have included three functions in the PrnUtils.pas unit to make it very easy for you to get these pointers from any one of the following sources:

1) A Bitmap File (a .bmp file for instance)

2) A bitmap stored in a stream (perhaps from a database or other resource)

3) A TBitmapObject (Image.Picture.Bitmap for example).

Please see the example code and the PrnUtils.pas unit for usage.

Back to Functions and Structures

Validate HTML