Adding an Advanced Print Dialog Box
Other versions of this page are also available for the following:
8/28/2008
If your printer includes advanced functionality, you can add an Advanced button to the Page Setup dialog box. A user can choose Advanced to display another dialog box that allows the user to choose additional printer settings that are not available in the Page Setup dialog box.
You must implement the DrvAdvPageSetupDlg function in the printer driver to make the Advanced button available. The Advanced button remains disabled if the printer driver does not implement this function. When the user chooses Advanced, the operating system (OS) calls DrvAdvPageSetupDlg.
A printer driver that has an export routine declared, such as the following example shows, provides an Advanced Print dialog box.
UINT APIENTRY* DrvAdvPageSetupDlg(LPPAGESETUPDLG lppsd, HWND hwndDlg);
The following table describes each advanced printer driver parameter in DrvAdvPageSetupDlg.
Parameter | Description |
---|---|
lppsd |
Pointer to the PAGESETUPDLG (structure) passed to PageSetupDlg (function) by the application. The members in this structure reflect the settings the user has made in the Print Setup dialog box before the Advanced button was chosen. |
hwndDlg |
Handle to the Print Setup dialog box, which is the parent of any new window created by the printer driver DrvAdvPageSetupDlg function. |
This function executes in the context of the calling application. It communicates user preferences to the Print Setup system through changes to the driver-specific area at the end of the DEVMODE structure referred to by lppsd hDevMode. If the driver-specific area is changed, the driver must update the dmDriverExtra member of the DEVMODE structure, which contains the number of bytes of private driver-data that follow DEVMODE structure. If necessary, the pre-existing DEVMODE structure can be replaced by one allocated by the printer driver itself. The printer driver should use the LocalAlloc function to allocate the new DEVMODE structure, and it should copy the driver-independent part of the old DEVMODE structure into the beginning of the new one. The Print Setup dialog box is responsible for freeing the old DEVMODE structure if a new structure has been allocated.
Upon return from DrvAdvPageSetupDlg, the Print Setup system records all changes to the driver-independent portion of the DEVMODE structure and sets the user interface (UI) items in the Print Setup dialog box appropriately. The behavior of the Print Setup dialog box is undefined if any of the values in the driver-independent part of the DEVMODE structure are out of bounds. The Print Setup system will not affect anything in the driver-dependent part at the end of the DEVMODE structure.
The application calling PageSetupDlg must call LocalFree and release the DEVMODE structure allocated by the printer driver after completion.
The following example shows how the DEVMODE structure is used for a print dialog box.
static DEVMODE dmDef;
BOOL MyPrintDialog()
{
DWORD dwErr;
PAGESETUPDLG psdlg;
HDC hdc = NULL;
int fSuccess;
LPDEVMODE lpdmMyOriginalDevMode = &dmDef;
// The DEVMODE structure provided to PageSetupDlg() through the
// hDevMode member of the PAGESETUPDLG structure is a pointer to a
// static DEVMODE. When PageSetupDlg() returns, DEVMODE may
// have changed.
memset(lpdmMyDevMode, 0, sizeof(DEVMODE));
lpdmMyOriginalDevMode->dmSize = sizeof(dmDef);
lpdmMyOriginalDevMode->dmFields = DM_PRINTQUALITY | DM_ORIENTATION |
DM_PAPERSIZE;
lpdmMyOriginalDevMode->dmPrintQuality = DMRES_HIGH ;
lpdmMyOriginalDevMode->dmOrientation = DMORIENT_PORTRAIT;
lpdmMyOriginalDevMode->dmPaperSize = MyGetLocalePaperSize();
memset(&psdlg, 0, sizeof(PAGESETUPDLG));
psdlg.hDevMode = lpdmMyOriginalDevMode;
psdlg.lStructSize = sizeof(PAGESETUPDLG);
psdlg.hwndOwner = pdoc->hWndTopLevel;
psdlg.hInstance = hInstApp;
psdlg.Flags = PSD_MARGINS ;
MyGetMargins(psdlg.Flags, &psdlg.rtMargin);
fSuccess = PageSetupDlg(&psdlg);
if ( fSuccess ) {
hdc = MyCreatePrinterDC((LPDEVNAMES)psdlg.hDevNames, psdlg.hDevMode);
}
if ( fSuccess && hdc ) {
MyAcceptMargins(psdlg.Flags, &psdlg.rtMargin);
MyPrintDocument(hdc, pdoc, (psdlg.Flags & PSD_RANGESELECTION) ?
PRINT_SELECTION : PRINT_ENTIRE);
}
else {
MyHandlePageSetupDlgError(CommDlgExtendedError());
}
if ( psdlg.hDevNames ) {
LocalFree(psdlg.hDevNames);
psdlg.hDevNames = NULL;
}
// Check to see whether the DEVMODE returned in hDevMode is
// the same one that was provided. If not, assume that
// it was locally allocated by the print driver, and this code is
// responsible for cleaning it up.
if ( psdlg.hDevMode && (lpdmMyOriginalDevMode != psdlg.hDevMode) ) {
LocalFree(psdlg.hDevMode);
}
if (hdc) {
DeleteDC(hdc);
}
}