Article ID: 197393
Article Last Modified on 11/15/2006
/*
FUNCTION ModifyDevMode
PURPOSE: Encapsuulate the method of making changes
to a Printer DEVMODE.
ASSUMPTIONS: pDevMode must be a properly initialized
DEVMODE from either PrintDlg(),
GetPrinter(), or DocumentProperties().
*/
BOOL ModifyDevMode(LPTSTR lpszPrinterName, LPDEVMODE pDevMode, int nCopies)
{
LPTSTR pDevice = lpszPrinterName;
HANDLE hPrinter;
DWORD dwRet;
// Open the printer so you can call DocumentProperties.
if (!OpenPrinter( pDevice, &hPrinter, NULL ))
return FALSE; // Must be a bad printer name
/*
* Make changes to the DevMode that are supported.
*/
if (pDevMode->dmFields & DM_COPIES)
{
// Supported, so make the change
pDevMode->dmCopies = nCopies;
}
else
{
// Not supported so exit.
ClosePrinter( hPrinter );
return FALSE;
}
/*
* Merge the new settings with the old.
* This gives the driver a chance to update any private
* portions of the DevMode structure.
*/
dwRet = DocumentProperties( NULL,
hPrinter,
pDevice,
pDevMode, /* Reuse your buffer for output. */
pDevMode, /* Pass your changes to the driver. */
DM_IN_BUFFER | /* Commands to merge your changes */
DM_OUT_BUFFER ); /* and write the result. */
ClosePrinter( hPrinter );
return TRUE;
} /* End of function ModifyDevMode. */
/*
FUNCTION GetUserPrinterDC
PURPOSE: Launches the Printer Common Dialog and initializes the
Copies edit control for that dialog. It does this using the
dmCopies member of the DEVMODE structure to avoid a bug in
Windows 95 that causes the Copies edit control to not be
initialized from the PRINTDLG structure.
*/
HDC GetUserPrinterDC(HWND hWnd, int nCopies)
{
PRINTDLG pd;
LPDEVMODE pDevMode;
LPDEVNAMES pDevNames;
HDC hDC = NULL;
LPTSTR pDevice;
// Initialize the DEVMODE to get the default printer.
ZeroMemory( &pd, sizeof(pd) );
pd.lStructSize = sizeof(pd);
pd.hwndOwner = hWnd;
pd.Flags = PD_RETURNDEFAULT;
// Get a DEVMODE for the default printer.
if (!PrintDlg( &pd ))
return NULL;
//Your number of copies goes into DEVMODE.dmCopies.
pDevMode = (LPDEVMODE)GlobalLock( pd.hDevMode );
pDevNames = (LPDEVNAMES)GlobalLock( pd.hDevNames );
pDevice = (LPTSTR)pDevNames + pDevNames->wDeviceOffset;
if (!ModifyDevMode( pDevice, pDevMode, nCopies ))
{
// Can't initialize dmCopies, so use PRINTDLG, so the code at
// least works on other versions of Windows (OSR 2, 98, NT).
pd.nCopies = nCopies;
}
GlobalUnlock( pd.hDevMode );
GlobalUnlock( pd.hDevNames );
// Setup and get the user's Device Context.
pd.Flags = PD_RETURNDC;
if (PrintDlg( &pd ))
hDC = pd.hDC;
// Cleanup properly.
if (pd.hDevMode)
GlobalFree( pd.hDevMode );
if (pd.hDevNames)
GlobalFree( pd.hDevNames );
// Send it back to the caller.
return hDC;
} /* End of function GetUserPrinterDC. */
An alternative workaround is to use the Print Common Dialog lpfnPrintHook
member to set the Copies edit control to the desired value when the dialog
is initialized. An application can install a dialog hook procedure using
the lpfnPrintHook member of the PRINTDLG structure. Then, when the hook
procedure processes the WM_INITDIALOG message for the Print common dialog
box, it can set the number of copies in the Copies edit control.
/*
FUNCTION PrintHookProc
PURPOSE: Hook Procedure for the PrintDlg Dialog.
Used to override the Dialog's initialization processing
of the Number of Copies edit control.
*/
UINT CALLBACK PrintHookProc(
HWND hdlg,
UINT uiMsg,
WPARAM wParam,
LPARAM lParam )
{
static PRINTDLG *pPD = NULL;
int CopiesEditCtlId = edt3;
// Note: You get the previous edit control ID from the
// Prnsetup.dlg dialog template. edt3 is defined in
// Dlgs.h.
switch ( uiMsg )
{
case WM_INITDIALOG:
{
// In this message you get a pointer to the
// PRINTDLG structure.
pPD = (PRINTDLG *)lParam;
// Extract the desired value for nCopoies.
pPD->nCopies = (WORD)pPD->lCustData;
// Effect it in the edit control.
SetDlgItemInt( hdlg, CopiesEditCtlId, pPD->nCopies, FALSE );
return 1;
}
}
// Otherwise, you didn't handle the message.
return 0;
} /* End of function PrintHookProc. */
/*
FUNCTION GetUserPrinterDC
PURPOSE: Launches the Printer Common Dialog box and
initializes the Copies edit control for that dialog box.
Uses a PrintHookProc to avoid a bug in Windows 95 that
causes the Copies edit control to not be initialized from
the PRINTDLG structure.
*/
HDC GetUserPrinterDC(HWND hWnd, int nCopies)
{
PRINTDLG pd;
HDC hDC = NULL;
// Set up and get the users Device Context.
ZeroMemory( &pd, sizeof(pd) );
pd.lStructSize = sizeof(pd);
pd.hwndOwner = hWnd;
pd.nCopies = nCopies;
pd.Flags = PD_RETURNDC | PD_ENABLEPRINTHOOK;
// Pass the nCopies using custom data so you have it in the
// PrintHookProc after the Dialog has setup its own
// copy of this PRINTDLG structure on WM_INITDIALOG.
pd.lCustData = nCopies;
pd.lpfnPrintHook = PrintHookProc;
if (PrintDlg( &pd ))
hDC = pd.hDC;
// Cleanup properly.
if (pd.hDevMode)
GlobalFree( pd.hDevMode );
if (pd.hDevNames)
GlobalFree( pd.hDevNames );
// Send it back to the caller.
return hDC;
} /* End of function GetUserPrinterDC */
Keywords: kbbug kbcmndlgprint kbfix kbgdi kbprint KB197393