17.5.4 Tailoring Print Settings for Use with the CreateDC Function

To use a printer, your application must first create a printer device context by using the CreateDC function. This function has an optional parameter, lpvInitData, which specifies the print settings to use when creating the printer device context. The simplest way to print is to set lpvInitData to NULL; Windows then creates the device context by using the current print settings for that printer port.

To print using your own settings instead of the current default settings, you can pass CreateDC a DEVMODE structure containing the print settings you want. Windows then creates the device context by using your customized print settings.

When calling the CreateDC function, you should provide only DEVMODE structures that you have received directly from the printer driver. Although it is possible to simply edit a DEVMODE structure and then pass it directly to CreateDC, it is not recommended. CreateDC requires a correct and complete DEVMODE structure. Therefore, any minor inconsistencies in the structure can result in an invalid device context. To ensure that a DEVMODE structure is valid, pass it to the printer driver as input. The driver then provides a complete, correct DEVMODE structure that incorporates your changes; you can safely pass this output structure to CreateDC.

To use particular print settings, you should provide, as input to ExtDeviceMode, a partial DEVMODE structure that contains the settings you want. The driver changes only those settings for which you supply a new value. This means that you can use this method to change a single print setting—for example, changing from portrait to landscape orientation—without affecting the driver's other print settings. In response to ExtDeviceMode, the driver provides as output a complete DEVMODE structure that includes your changes.

To change the print settings, follow these steps:

1.Set up a partial or complete DEVMODE structure that contains the members you want to change.

If you are supplying a partial structure be sure to include all five header members (dmDeviceName, dmSpecVersion, dmDriverVersion, dmSize, and dmDriverExtra). Set the dmDriverVersion and dmDriverExtra members to zero if you are not passing any driver-specific information. Set the dmFields member to indicate which of the device-independent settings you are providing.

For example, to request that a printer driver use landscape orientation with letter-sized paper, you could set up the following DEVMODE structure:

DEVMODE dm;
lstrcpy(dm.dmDeviceName, szDeviceName);
/* Header information */
dm.dmVersion = DM_SPECVERSION;
dm.dmDriverVersion = 0;
dm.dmSize = sizeof(DEVMODE);
dm.dmDriverExtra = 0;
/* Device-independent settings */
dm.dmFields = DM_ORIENTATION | DM_PAPERSIZE;
dm.dmOrientation = DMORIENT_LANDSCAPE;
dm.dmPaperSize = DMPAPER_LETTER;

The first five members make up the structure's header information. The
szDeviceName value is a string that contains the name of the device, such as HP LaserJet Series II. For information about how to retrieve this value from the WIN.INI file, see Chapter 12, “Printing.”

2.Call ExtDeviceMode, including the following information in the parameters:

Parameter Value

lpdmInput A pointer to the buffer that contains the partial or complete DEVMODE structure you are supplying
lpdmOutput A pointer to the output buffer
fwMode DM_MODIFY | DM_COPY

The driver then changes its settings to match those in your input structure and writes the resulting settings to the output buffer as a complete DEVMODE structure.

3.Pass the output DEVMODE structure to CreateDC to create a printer device context that uses the new settings.

After modifying its DEVMODE structure, the driver copies it to the output buffer. The output DEVMODE structure will be a complete structure and will include the changes you specified in your partial structure. Because the driver has just validated your changes, it is safe to pass this output structure to the CreateDC function.