INFO: Working with Long Printer Names


Microsoft Windows operating systems can manage printers with names longer than 32 characters. However, the name of a printer in a DEVMODE structure cannot exceed 32 characters in length. This article discusses this conflict and how Microsoft Windows applications overcome it.

More Information

When a Microsoft Windows application prints, it must identify the target printer by its full name. The DEVMODE structure that was introduced in 16-bit Windows version 3.1 has a limitation of 32 characters for a printer name. However, printer names in Win32 operating systems can be much longer.

On Win32 platforms the full or long printer name is given by the pPrinterName member of the PRINTER_INFO_2 structure or by the DEVNAMES structure. The PRINTER_INFO_2 structure can be obtained from the EnumPrinters function. The DEVNAMES structure can be obtained by a call to either the PrintDlg or PrintDlgEx functions to fill a PRINTDLG(EX) structure. The DEVNAMES structure is managed by a global memory handle returned in the PRINTDLG(EX) structure.

The pPrinterName member of the PRINTER_INFO_2 structure and the name of the device (wDeviceOffset refers to the printer name) in the DEVNAMES structure are pointers to a string buffer. Because they are pointers to a string, they do not have a 32-character limitation and will contain the long printer name of the target printer. See the Platform SDK Documentation for a discussion of the PRINTDLG(EX) structure and the DEVNAMES structure.

Some applications may need to open a printer by name while printing to a printer device context. Such a circumstance occurs when the application is changing the settings of a DEVMODE buffer as described in the following Microsoft Knowledge Base article:

167345 HOWTO: Modify Printer Settings with DocumentProperties()
The long printer name cannot be obtained from a handle to a printer device context or the DEVMODE buffer. The application must keep some independent reference to the printer. A reference to the printer can take the form of a string that contains the long printer name, a DEVNAMES buffer, or a handle to a printer that can be used in a GetPrinter function call.

The GetPrinter function can fill out a single PRINTER_INFO_2 structure much like the EnumPrinters function can retrieve several such structures. Because proper changes to a DEVMODE also require a handle to a printer, such a handle is a convenient reference to the printer.

The long printer name can be used to obtain a handle to a printer through the OpenPrinter function, so the long name is also a convenient reference to the printer. It can be stored separately or as part of a DEVNAMES structure.

The printer name in a DEVNAMES buffer is stored in the extra space allocated beyond the DEVNAMES structure. To locate the printer name string in the DEVNAMES buffer, you can use the wDeviceOffset member to compute a pointer value that is based on the start of the DEVNAMES structure.

The following code fragment demonstrates the technique by creating a printer device context from a DEVNAMES and a DEVMODE structure:

HDC CreateDeviceContext( DEVMODE *pDevMode, DEVNAMES *pDevNames )
LPCTSTR szDriver;
LPCTSTR szDevice;
LPCTSTR szOutput;

szDriver = (LPCTSTR)pDevNames+pDevNames->wDriverOffset;
szDevice = (LPCTSTR)pDevNames+pDevNames->wDeviceOffset;
szOutput = (LPCTSTR)pDevNames+pDevNames->wOutputOffset;

return CreateDC(szDriver, szDevice, szOutput, pDevMode);

ID d'article : 240082 - Dernière mise à jour : 3 mars 2009 - Révision : 1