INF: How to Create Device-Independent Printing Code

ID Number: Q76260

3.00

WINDOWS

Summary:

Windows provides a device-independent platform for application

developers. Device independence applies to printing as well. To write

code to work with any printer driver, applications must not rely on

any special feature in a printer driver. Instead, applications should

direct all requests through the Windows Graphical Device Interface

(GDI).

More Information:

There are two major classes of printers: raster printers and

PostScript printers. This article is directed towards application

support for raster printers. For information on PostScript printers,

query on the words:

prod(winsdk) and postscript

With the exception of the standard printer escapes, applications

should not rely on any printer escape to be supported in a particular

printer driver.

The standard escapes are: STARTDOC, ENDDOC, NEXTBAND, NEWFRAME,

SETABORTPROC, and ABORTDOC. The remaining escapes are optional for

printer drivers. Applications should use the QUERYESCSUPPORT escape to

test for the support of optional escapes. Applications should not

depend on private knowledge of how a particular driver works.

For example, the DRAWPATTERNRECT escape is available on certain

devices. The following code fragment determines if the DRAWPATTERNRECT

escape is supported on the installed device. If not, an alternative

function, PatBlt(), is used to create the output.

short i;

i = DRAWPATTERNRECT;

if (Escape(hPr, QUERYESCSUPPORT, sizeof(i), (LPSTR)&i, NULL))

Escape(hPr, DRAWPATTERNRECT, sizeof(lpPatRect),

(LPSTR)lpPatRect, NULL);

else

PatBlt(hPr, .....);

Of the remaining escapes, the following are used frequently:

GETPHYSPAGESIZE, GETPRINTINGOFFSET, PASSTHROUGH, and DRAWPATTERNRECT.

An application should minimize the number of escapes that it uses.

Another area of device independence applies to the DeviceMode

function. Applications should not allow the user to change the device

mode settings globally. If the user wants to change the device mode

setting, the Control Panel utility should be used. It is more

appropriate for the device mode to be associated with an application,

a document, or a particular set of pages in a document.

The following code demonstrates the required steps to use

EXTDEVICEMODE:

lpfnExtDeviceMode = GetProcAddress(hDriver, (LPSTR)"EXTDEVICEMODE");

if (lpfnExtDeviceMode != NULL)

{

count = (*lpfnExtDeviceMode)((HWND)NULL,

(HANDLE)hDriver,

(LPDEVMODE)NULL,

(LPSTR)lpPrintType,

(LPSTR)lpPrintPort,

(LPDEVMODE)NULL,

(LPSTR)NULL,

(WORD)0);

hDevModeOut = LocalAlloc(LHND, count);

if (hDevModeOut)

{

lpDevModeOut = LocalLock(hDevModeOut);

lstrcpy(DevModeIn.dmDeviceName, lpPrintType);

DevModeIn.dmSpecVersion = DM_SPECVERSION;

DevModeIn.dmDriverVersion = 0;

DevModeIn.dmSize = sizeof(DEVMODE);

DevModeIn.dmDriverExtra = 0;

DevModeIn.dmFields = DM_ORIENTATION;

DevModeIn.dmOrientation = DMORIENT_LANDSCAPE;

count = (*lpfnExtDeviceMode)((HWND)NULL,

(HANDLE)hDriver,

(LPDEVMODE)lpDevModeOut,

(LPSTR)lpPrintType,

(LPDEVMODE)&DevModeIn,

(LPSTR)NULL,

DM_COPY);

CreateDC(lpPrintDrvier, lpPrintType, lpPrintPort,

(LPSTR)lpDevModeOut);

}

Note that it is very important to query the driver for the size of the

device mode structure. The DEVMODE structure is driver-dependent and

also driver version-dependent.

On a final note, applications should not hard code a driver name or a

device name. Applications should always search in the [Devices]

section of the WIN.INI file for the name of the installed printer.

Explicitly searching for "PSCRIPT.DRV" or "HPPCL.DRV" is strongly

discouraged.