Problems Printing from C++Builder 6 CLX Applications

By: Brian Long

Abstract: C++Builder 6 has no printing support in CLX applications. This article shows how to fix it.

Problems Printing from BCB6 CLX Apps

Problems Printing from
C++Builder 6 CLX Applications

Brian Long (www.blong.com)

Table of Contents

Click here to download the file associated with this article.


The Problem

I recently wrote an article about a problem in C++Builder 6 that makes all the routines in the Qt.hpp header unusable. Whilst looking into that issue I bumped into another C++Builder 6 CLX application problem.

This time the provided functionality in the TQPrinter class is completely non-functional. Any attempts to call upon the printer object (available through the Printer() function) to perform any printing function or get any printing information yielded disappointing results. For example this code tries to get the printer page size in mm and then in pixels, before invoking the printer setup dialog:

TPrinter *printer = Printer();
const int PrinterPageWidth = printer->PageWidth;// result 0
const int PrinterPageHeight = printer->PageHeight;// result 0
const double mmPerInch = 25.39999999999999;
const double PrinterPageWidthMM =
  PrinterPageWidth * mmPerInch / printer->XDPI;// result NAN
const double PrinterPageHeightMM = 
  PrinterPageHeight * mmPerInch / printer->YDPI;// result NAN
ShowMessage(String().sprintf(
  "Page size (w x h):\n%.0f x %.0f (mm)\n%d x %d (pixels)",
  PrinterPageWidthMM, PrinterPageHeightMM,
  PrinterPageWidth, PrinterPageHeight));
printer->ExecuteSetup();

Unfortunately it produces this unhelpful message and then does nothing more. The setup dialog does not appear.

If you try and access the Qt printing support directly using the CLXDisplay API (the routines in the Qt.hpp header) you will only get Stack Overflows for your trouble, unless you've already fixed the problem, as covered in the other article.

If you get the Qt header working correctly you can call the Qt printing routines directly, as in this code that does the equivalent of the previous code snippet using the Qt API:

TPrinter *printer = Printer();
TQPrintAdapter *printAdapter =
  ynamic_cast<TQPrintAdapter *>(printer->PrintAdapter);
if (printAdapter)
{
  QPaintDeviceMetricsH *metrics = printAdapter->DeviceMetrics;
  // full page size
  QPrinter_setFullPage((QPrinterH *)printer->Handle, true);
  const int PrinterPageWidth =
    QPaintDeviceMetrics_width(metrics);// result 0
  const int PrinterPageHeight =
    QPaintDeviceMetrics_height(metrics);// result 0
  const int PrinterPageWidthMM =
    QPaintDeviceMetrics_widthMM(metrics);// result 0
  const int PrinterPageHeightMM =
    QPaintDeviceMetrics_heightMM(metrics);// result 0
  ShowMessage(String().sprintf(
    "Page size (w x h):\n%d x %d (mm)\n%d x %d (pixels)",
    PrinterPageWidthMM, PrinterPageHeightMM,
    PrinterPageWidth, PrinterPageHeight));
}
QPrinter_setup((QPrinterH *)printer->Handle, NULL);

Unfortunately the problem still hits us. All these routines simply return 0 and so we get exactly the same result: a message full of useless information and no setup dialog.

The Reason

It seems this problem is one that should not be occurring. The same problem was true of Delphi 6 CLX applications in the initial release of the product and after the first Update Pack. It turned out to be due to some internal problems in the Qt interface library (qtintf.dll). This original version shipped with Delphi has version information in it identifying it as version 6.0.0.0.

Delphi 6 Update Pack 2 supplied a new version of this library, version 6.0.6.240, which rectifies the problem. This Update Pack came out about a month after C++Builder was released, but none of the currently released C++Builder 6 Update Packs (and there are at least three of them around, perhaps even four by now) supply the DLL to programmers who do not use Delphi. This means C++Builder 6 CLX applications are using an old, broken version of the DLL and so still have to face the broken printer support.

The Solution

The solution to the problem is simple. Replace your old qtintf.dll with the updated version. You can get the newer version by clicking here. This attachment contains the DLL as well as a trivial Delphi 6 CLX application. The application does nothing interesting, but supplying it legitimises my uploading of the DLL, since the application needs it to run. It also needs the Delphi 6 or C++Builder 6 runtime packages to execute, but only C++Builder 6 programmers are likely to download it so that shouldn't be a problem.

After switching DLLs the behaviour of either section of code from above is to produce this correct information about the printer page setup:

and then invoke the printer setup dialog, which in my case looks like this:

 

Further Reading

About Brian Long

Brian Long used to work at Borland UK, performing a number of duties including Technical Support on all the programming tools. Since leaving in 1995, Brian has been providing training and consultancy on Borland's RAD products ever since, and is now moving into the .NET world.

Besides authoring a Borland Pascal problem-solving book published in 1994, Brian is a regular columnist in The Delphi Magazine and has had numerous articles published in Developer's Review, Computing, Delphi Developer's Journal and EXE Magazine. He was nominated for the Spirit of Delphi 2000 award and was voted Best Speaker at Borland's BorCon 2002 conference in Anaheim, California by the conference delegates.

There are a growing number of conference papers and articles available on Brian's Web site, so feel free to have a browse.

In his spare time (and waiting for his C++ programs to compile) Brian has learnt the art of juggling and making inflatable origami paper frogs.


Server Response from: ETNASC03