|
|
/*++
Copyright (c) 1990-1998, Microsoft Corporation All rights reserved.
Module Name:
prnsetup.c
Abstract:
This module implements the Win32 print dialogs.
Revision History:
--*/
// precompiled headers
#include "precomp.h"
#pragma hdrstop
#include "prnsetup.h"
#include "util.h"
//
// The PrintDlgEx routines.
//
extern VOID Print_UnloadLibraries(); extern BOOL Print_NewPrintDlg(PPRINTINFO pPI);
////////////////////////////////////////////////////////////////////////////
//
// PrintDlgA
//
// ANSI entry point for PrintDlg when this code is built UNICODE.
//
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI PrintDlgA( LPPRINTDLGA pPDA) { PRINTINFO PI; BOOL bResult = FALSE; DWORD Flags;
ZeroMemory(&PI, sizeof(PRINTINFO));
if (bResult = ThunkPrintDlg(&PI, pPDA)) { ThunkPrintDlgA2W(&PI);
Flags = pPDA->Flags;
bResult = PrintDlgX(&PI);
if ((bResult) || (Flags & (PD_ENABLEPRINTHOOK | PD_ENABLESETUPHOOK))) { ThunkPrintDlgW2A(&PI); } } FreeThunkPrintDlg(&PI);
return (bResult); }
////////////////////////////////////////////////////////////////////////////
//
// PrintDlg
//
// The PrintDlg function displays a Print dialog box or a Print Setup
// dialog box. The Print dialog box enables the user to specify the
// properties of a particular print job. The Print Setup dialog box
// allows the user to select additional job properties and to configure
// the printer.
//
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI PrintDlg( LPPRINTDLG pPD) { PRINTINFO PI;
ZeroMemory(&PI, sizeof(PRINTINFO));
PI.pPD = pPD; PI.ApiType = COMDLG_WIDE;
return ( PrintDlgX(&PI) ); }
////////////////////////////////////////////////////////////////////////////
//
// ShowErrorMessage
//
// Shows an error message
//
////////////////////////////////////////////////////////////////////////////
static HRESULT ShowErrorMessage( IN const PRINTDLG *pPD, IN const PRINTINFO *pPI, OUT BOOL *pbTryAgain OPTIONAL ) { HRESULT hr = S_OK; BOOL bTryAgain = FALSE; BOOL bPrinterAdded = FALSE;
if (!(pPD->Flags & PD_NOWARNING)) { DWORD dwErr = GetStoredExtendedError();
//
// Only do this for new apps.
//
if ( (pPI->ProcessVersion >= 0x40000) || (dwErr == PDERR_NODEFAULTPRN) || (dwErr == PDERR_PRINTERNOTFOUND) ) { TCHAR szWarning[SCRATCHBUF_SIZE]; TCHAR szTitle[SCRATCHBUF_SIZE]; int iszWarning;
szTitle[0] = TEXT('\0'); if (pPD->hwndOwner) { GetWindowText(pPD->hwndOwner, szTitle, SCRATCHBUF_SIZE); } if (!szTitle[0]) { CDLoadString(g_hinst, iszWarningTitle, szTitle, ARRAYSIZE(szTitle)); }
switch (dwErr) { case ( PDERR_NODEFAULTPRN ) : { //
// Notes: if the app is a 16-bit app, we don't ask the user whether to install a
// new printer. This is because some components may break if we do it.
//
if (IS16BITWOWAPP(pPD)) { iszWarning = iszNoPrnsInstalled; } else { iszWarning = iszNoPrinters; } break; } case ( PDERR_PRINTERNOTFOUND ) : { iszWarning = iszPrnNotFound; break; } case ( CDERR_MEMLOCKFAILURE ) : case ( CDERR_MEMALLOCFAILURE ) : case ( PDERR_LOADDRVFAILURE ) : { iszWarning = iszMemoryError; break; } default : { iszWarning = iszGeneralWarning; break; } }
if (iszWarning == iszNoPrnsInstalled) { FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, ERROR_PRINTER_NOT_FOUND, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)szWarning, ARRAYSIZE(szWarning), NULL); } else { CDLoadString(g_hinst, iszWarning, szWarning, ARRAYSIZE(szWarning)); }
MessageBeep(MB_ICONEXCLAMATION);
if (iszWarning == iszNoPrinters) { //
// If the problem is that there are no printers installed then ask the
// user if he wants to add one, and then launch the add printer wizard.
//
if (IDYES == MessageBox( pPD->hwndOwner, szWarning, szTitle, MB_ICONQUESTION | MB_YESNO)) { hr = InvokeAddPrinterWizardModal(pPD->hwndOwner, &bPrinterAdded);
if (SUCCEEDED(hr) && bPrinterAdded) { //
// A printer was added successfully. Tell the caller to try again.
//
bTryAgain = TRUE; } } } else { //
// This is a fatal error. Just show an error message and bail.
//
MessageBox( pPD->hwndOwner, szWarning, szTitle, MB_ICONEXCLAMATION | MB_OK ); } } }
if (pbTryAgain) { *pbTryAgain = bTryAgain; }
return hr; }
////////////////////////////////////////////////////////////////////////////
//
// PrintDlgX
//
// Worker routine for the PrintDlg api.
//
////////////////////////////////////////////////////////////////////////////
BOOL PrintDlgX( PPRINTINFO pPI) { LPPRINTDLG pPD = pPI->pPD; BOOL nResult = -1; // <0==error, 0==CANCEL, >0==OK
LPDEVMODE pDM = NULL; LPDEVMODE pDevMode = NULL; LPDEVNAMES pDN = NULL; DWORD dwFlags; // old copy
WORD nCopies, nFromPage, nToPage; // old copy
HGLOBAL hDevNames, hDevMode; // old copy
TCHAR szPrinterName[MAX_PRINTERNAME]; // old copy
LONG cbNeeded; DWORD dwResult = 0; BOOL bTryAgain = TRUE;
if (!pPD) { StoreExtendedError(CDERR_INITIALIZATION); return (FALSE); }
if (pPD->lStructSize != sizeof(PRINTDLG)) { StoreExtendedError(CDERR_STRUCTSIZE); return (FALSE); }
if (pPD->hwndOwner && !IsWindow(pPD->hwndOwner)) { StoreExtendedError(CDERR_DIALOGFAILURE); return (FALSE); }
//
// See if the application should get the new look.
//
// Do not allow the new look if they have hooks, templates,
// Invalid hwndOwner,
// they want the setup dialog, or they just want to get the default
// printer.
//
// Also don't allow the new look if we are in the context of
// a 16 bit process.
//
if ( (!(pPI->Status & PI_PRINTDLGX_RECURSE)) && (!pPI->pPSD) && ((!(pPD->Flags & (PD_PAGESETUP | PD_PRINTSETUP | PD_RETURNDEFAULT | PD_ENABLEPRINTHOOK | PD_ENABLESETUPHOOK | PD_ENABLEPRINTTEMPLATE | PD_ENABLESETUPTEMPLATE | PD_ENABLEPRINTTEMPLATEHANDLE | PD_ENABLESETUPTEMPLATEHANDLE)))) && (pPD->hwndOwner && IsWindow(pPD->hwndOwner)) && (!IS16BITWOWAPP(pPD)) ) { //
// Show the new dialog.
//
StoreExtendedError(0);
return Print_NewPrintDlg(pPI); }
//
// Warning! Warning! Warning!
//
// We have to set g_tlsLangID before any call for CDLoadString
//
TlsSetValue(g_tlsLangID, (LPVOID) GetDialogLanguage(pPD->hwndOwner, NULL));
//
// Get the process version of the app for later use.
//
pPI->ProcessVersion = GetProcessVersion(0);
//
// Check if we need to use ExtDeviceMode. We use this
// mode only if a 16 bit app is calling us with a NULL
// devmode.
//
if ((pPD->Flags & CD_WOWAPP) && !pPD->hDevMode) { pPI->bUseExtDeviceMode = TRUE; } else { pPI->bUseExtDeviceMode = FALSE; }
pPD->hDC = 0;
StoreExtendedError(CDERR_GENERALCODES);
//
// Do minimal work when requesting a default printer.
//
if (pPD->Flags & PD_RETURNDEFAULT) { //
// Do not display a warning in this case if it fails.
// MFC 3.1 does not specify PD_NOWARNING, but that's what
// it really wants.
//
nResult = PrintReturnDefault(pPI); PrintClosePrinters(pPI); return (nResult); }
if (!PrintLoadIcons()) { //
// If the icons cannot be loaded, then fail.
//
StoreExtendedError(PDERR_SETUPFAILURE); goto PrintDlgX_DisplayWarning; }
//
// Printer enumeration is delayed until the combobox is dropped down.
// However, if a printer is specified, we must force enumeration in
// order to find the printer so that the correct devmode can be created.
//
if ((pPD->hDevMode) && (pPD->hDevNames) && (pDM = GlobalLock(pPD->hDevMode))) { if (pDN = GlobalLock(pPD->hDevNames)) { dwResult = lstrcmp((LPTSTR)pDM->dmDeviceName, (LPTSTR)pDN + pDN->wDeviceOffset); GlobalUnlock(pPD->hDevNames); } GlobalUnlock(pPD->hDevMode); }
//
// First : Try to open the printer in the DevMode.
//
// Note: The printer name field in the DEVMODE struct is limited to
// 32 chars which may cause this case to fail.
//
if ( (!dwResult) && (!pPI->hCurPrinter) && (pPD->hDevMode) && (pDM = GlobalLock(pPD->hDevMode)) ) { PrintOpenPrinter(pPI, pDM->dmDeviceName); GlobalUnlock(pPD->hDevMode); }
//
// Second : Try to open the printer in the DevNames.
//
if ( (!pPI->hCurPrinter) && (pPD->hDevNames) && (pDN = GlobalLock(pPD->hDevNames)) ) { PrintOpenPrinter(pPI, (LPTSTR)pDN + pDN->wDeviceOffset); GlobalUnlock(pPD->hDevNames); }
for (;;) { //
// Third : Try to open the Default Printer.
//
PrintGetDefaultPrinterName(pPI->szDefaultPrinter, MAX_PRINTERNAME); if (!pPI->hCurPrinter) { if (pPI->szDefaultPrinter[0]) { PrintOpenPrinter(pPI, pPI->szDefaultPrinter); } }
//
// Fourth : Enumerate the Printers and try to open one of those.
//
if (!pPI->hCurPrinter) { if (!PrintEnumAndSelect(pPD->hwndOwner, 0, pPI, NULL, TRUE)) { //
// There are no printers installed in the system.
//
if (SUCCEEDED(ShowErrorMessage(pPD, pPI, &bTryAgain)) && bTryAgain) { //
// The user has installed a printer. Let's try again now.
//
continue; } } }
break; }
if (!bTryAgain && IS16BITWOWAPP(pPD)) { //
// If it's a 16-bit app, we'll return immediately without showing
// warning message. This is because some 16-bit app will crash in
// the common print dialog.
//
return (FALSE); }
//
// Save the original information passed in by the app in case the user
// hits cancel.
//
dwFlags = pPD->Flags; nCopies = pPD->nCopies; nFromPage = pPD->nFromPage; nToPage = pPD->nToPage; hDevNames = pPD->hDevNames; hDevMode = pPD->hDevMode; if ((pPI->pCurPrinter) && (lstrlen(pPI->pCurPrinter->pPrinterName) < ARRAYSIZE(szPrinterName))) { StringCchCopy(szPrinterName, ARRAYSIZE(szPrinterName), pPI->pCurPrinter->pPrinterName); } else { szPrinterName[0] = 0; }
pPD->hDevNames = NULL; pPD->hDevMode = NULL;
//
// Build a copy of the DevNames.
//
PrintBuildDevNames(pPI);
//
// Get the *correct* DevMode.
//
if (hDevMode) { pDevMode = GlobalLock(hDevMode); } else { //
// If it's WOW and the app didn't specify a devmode, get the 16-bit
// devmode out of the registry (ie. win.ini [Windows] device section).
//
if (pPI->bUseExtDeviceMode && pPI->pCurPrinter) { pDevMode = (pPI->pCurPrinter)->pDevMode; if (pDevMode) { cbNeeded = sizeof(DEVMODEW) + pDevMode->dmDriverExtra; goto GotWOWDMSize; }
//
// If a 16-bit devmode isn't available in the registry,
// drop through and get the system default devmode.
//
} }
cbNeeded = DocumentProperties( pPD->hwndOwner, pPI->hCurPrinter, (pPI->pCurPrinter) ? pPI->pCurPrinter->pPrinterName : NULL, NULL, NULL, 0 ); GotWOWDMSize: if ((cbNeeded > 0) && (pPD->hDevMode = GlobalAlloc(GHND, cbNeeded))) { BOOL fSuccess = FALSE;
if (pDM = GlobalLock(pPD->hDevMode)) { if (pPI->bUseExtDeviceMode && !hDevMode) { CopyMemory(pDM, pDevMode, cbNeeded); fSuccess = TRUE; goto GotNewWOWDM; }
fSuccess = DocumentProperties( pPD->hwndOwner, pPI->hCurPrinter, (pPI->pCurPrinter) ? pPI->pCurPrinter->pPrinterName : NULL, pDM, // out
pDevMode, // in
DM_MODIFY | DM_COPY ) == IDOK; GotNewWOWDM: if (pDM->dmFields & DM_COPIES) { if ((hDevMode) || (pPD->Flags & PD_USEDEVMODECOPIES)) { pPD->nCopies = pDM->dmCopies; } else if (pPD->nCopies) { pDM->dmCopies = pPD->nCopies; } } if (pDM->dmFields & DM_COLLATE) { //
// if PD_COLLATE is not set, we also use the setting in
// the returned DEVMODE structure
//
if ((hDevMode) || (pPD->Flags & PD_USEDEVMODECOPIES) || !(pPD->Flags & PD_COLLATE)) { if (pDM->dmCollate == DMCOLLATE_FALSE) { pPD->Flags &= ~PD_COLLATE; pPI->Status &= ~PI_COLLATE_REQUESTED; } else { pPD->Flags |= PD_COLLATE; pPI->Status |= PI_COLLATE_REQUESTED; } } else // in this case (pPD->Flags & PD_COLLATE) must be TRUE
{ pDM->dmCollate = DMCOLLATE_TRUE; } }
GlobalUnlock(pPD->hDevMode); }
if (!fSuccess) { GlobalFree(pPD->hDevMode); pPD->hDevMode = NULL; } }
if (hDevMode) { GlobalUnlock(hDevMode); }
//
// Get the default source string.
//
CDLoadString(g_hinst, iszDefaultSource, szDefaultSrc, ARRAYSIZE(szDefaultSrc));
//
// Call the appropriate dialog routine.
//
switch (pPD->Flags & (PD_PRINTSETUP | PD_PAGESETUP)) { case ( 0 ) : { nResult = PrintDisplayPrintDlg(pPI); break; } case ( PD_PRINTSETUP ) : case ( PD_PAGESETUP ) : { nResult = PrintDisplaySetupDlg(pPI); break; } default : { StoreExtendedError(CDERR_INITIALIZATION); break; } }
if (nResult > 0) { //
// User hit OK, so free the copies of the handles passed in
// by the app.
//
if (hDevMode && (hDevMode != pPD->hDevMode)) { GlobalFree(hDevMode); hDevMode = NULL; } if (hDevNames && (hDevNames != pPD->hDevNames)) { GlobalFree(hDevNames); hDevNames = NULL; }
if (pPD->hDevMode) { //
// Make sure the device name in the devmode is null
// terminated.
//
pDevMode = GlobalLock(pPD->hDevMode); pDevMode->dmDeviceName[CCHDEVICENAME - 1] = 0; GlobalUnlock(pPD->hDevMode); } } else { //
// User hit CANCEL or there was an error, so restore original
// values passed in by the app.
//
pPD->Flags = dwFlags; pPD->nCopies = nCopies; pPD->nFromPage = nFromPage; pPD->nToPage = nToPage; if (pPD->hDevMode && (pPD->hDevMode != hDevMode)) { GlobalFree(pPD->hDevMode); } if (pPD->hDevNames && (pPD->hDevNames != hDevNames)) { GlobalFree(pPD->hDevNames); } pPD->hDevNames = hDevNames; pPD->hDevMode = hDevMode;
//
// If we've been called from Page Setup, then we need to reset
// the current printer.
//
if (pPI->Status & PI_PRINTDLGX_RECURSE) { PrintCancelPrinterChanged(pPI, szPrinterName); } }
//
// Make sure that we are really supposed to be leaving this function
// before we start closing printers and displaying error messages.
//
if (pPI->Status & PI_PRINTDLGX_RECURSE) { return (nResult > 0); }
//
// Close the printers that were opened.
//
PrintClosePrinters(pPI);
//
// Display any error messages.
//
PrintDlgX_DisplayWarning:
if (nResult < 0 && bTryAgain) { //
// Display an error message and ignore the return code since we
// don't care. If bTryAgain is FALSE, this means the user selects
// not to install new printer. Don't show a duplicate error
// message in this case.
//
ShowErrorMessage(pPD, pPI, NULL); }
return (nResult > 0); }
////////////////////////////////////////////////////////////////////////////
//
// PageSetupDlgA
//
// ANSI entry point for PageSetupDlg when this code is built UNICODE.
//
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI PageSetupDlgA( LPPAGESETUPDLGA pPSDA) { PRINTINFO PI; BOOL bResult = FALSE; HANDLE hDevMode; HANDLE hDevNames; LPCSTR pTemplateName;
ZeroMemory(&PI, sizeof(PRINTINFO));
//
// Get the pPDA structure from the pPSDA structure.
//
if (bResult = ThunkPageSetupDlg(&PI, pPSDA)) { //
// Save the original devmode and devnames.
//
hDevMode = pPSDA->hDevMode; hDevNames = pPSDA->hDevNames; pTemplateName = pPSDA->lpPageSetupTemplateName;
//
// Convert the pPDA structure to Unicode (pPI->pPD).
//
if (bResult = ThunkPrintDlg(&PI, PI.pPDA)) { //
// Fill in the pPI->pPD structure.
//
ThunkPrintDlgA2W(&PI);
//
// Copy the Unicode information from the pPD structure to
// the pPSD structure for the call to PageSetupDlgX.
//
(PI.pPSD)->hDevMode = (PI.pPD)->hDevMode; (PI.pPSD)->hDevNames = (PI.pPD)->hDevNames;
(PI.pPSD)->lpPageSetupTemplateName = (PI.pPD)->lpSetupTemplateName;
//
// Call the PageSetupDlgX function to do the work.
//
if (bResult = PageSetupDlgX(&PI)) { //
// Success. Convert the Unicode pPD structure to
// its ANSI equivalent.
//
ThunkPrintDlgW2A(&PI);
//
// Save the ANSI devmode and devnames in the
// pPSD structure to be returned to the caller.
//
pPSDA->hDevMode = (PI.pPDA)->hDevMode; pPSDA->hDevNames = (PI.pPDA)->hDevNames; } else { //
// Failure. Restore the old devmode and devnames.
//
pPSDA->hDevMode = hDevMode; pPSDA->hDevNames = hDevNames; }
//
// Restore the old template name (always).
//
pPSDA->lpPageSetupTemplateName = pTemplateName; } FreeThunkPrintDlg(&PI); } FreeThunkPageSetupDlg(&PI);
return (bResult); }
////////////////////////////////////////////////////////////////////////////
//
// PageSetupDlg
//
// The PageSetupDlg function displays a Page Setup dialog box. This
// dialog box enables the user to specify the page orientation, the
// paper size, the paper source, and the margin settings. The
// appearance of the printed page is shown in the dialog's page preview.
//
////////////////////////////////////////////////////////////////////////////
BOOL WINAPI PageSetupDlg( LPPAGESETUPDLG pPSD) { PRINTINFO PI; BOOL bResult;
ZeroMemory(&PI, sizeof(PRINTINFO));
PI.pPSD = pPSD; PI.ApiType = COMDLG_WIDE;
bResult = PageSetupDlgX(&PI);
if (PI.pPD) { GlobalFree(PI.pPD); }
return (bResult); }
////////////////////////////////////////////////////////////////////////////
//
// PageSetupDlgX
//
// Worker routine for the PageSetupDlg api.
//
// NOTE: Caller of this routine must free pPI->pPD.
//
////////////////////////////////////////////////////////////////////////////
BOOL PageSetupDlgX( PPRINTINFO pPI) { LPPAGESETUPDLG pPSD = pPI->pPSD; BOOL bResult = FALSE; LPPRINTDLG pPD; RECT rtMinMargin; RECT rtMargin; POINT ptPaperSize; DWORD Flags;
if (!pPSD) { StoreExtendedError(CDERR_INITIALIZATION); return (FALSE); }
if (pPSD->lStructSize != sizeof(PAGESETUPDLG)) { StoreExtendedError(CDERR_STRUCTSIZE); return (FALSE); }
if ((pPSD->Flags & PSD_RETURNDEFAULT) && (pPSD->hDevNames || pPSD->hDevMode)) { StoreExtendedError(PDERR_RETDEFFAILURE); return (FALSE); }
//
// Make sure only the PSD_* bits are on. Otherwise, bad things
// will happen.
//
if ((pPSD->Flags & ~(PSD_MINMARGINS | PSD_MARGINS | PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS | PSD_DISABLEMARGINS | PSD_DISABLEPRINTER | PSD_NOWARNING | // must be same as PD_*
PSD_DISABLEORIENTATION | PSD_DISABLEPAPER | PSD_RETURNDEFAULT | // must be same as PD_*
PSD_SHOWHELP | // must be same as PD_*
PSD_ENABLEPAGESETUPHOOK | // must be same as PD_*
PSD_ENABLEPAGESETUPTEMPLATE | // must be same as PD_*
PSD_ENABLEPAGESETUPTEMPLATEHANDLE | // must be same as PD_*
PSD_ENABLEPAGEPAINTHOOK | PSD_DISABLEPAGEPAINTING | CD_WX86APP | PSD_NONETWORKBUTTON)) || // must be same as PD_*
((pPSD->Flags & (PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS)) == (PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS))) { StoreExtendedError(PDERR_INITFAILURE); return (FALSE); }
if ((pPSD->Flags & PSD_MINMARGINS) && (pPSD->Flags & PSD_MARGINS)) { if ( (pPSD->rtMargin.left < pPSD->rtMinMargin.left) || (pPSD->rtMargin.top < pPSD->rtMinMargin.top) || (pPSD->rtMargin.right < pPSD->rtMinMargin.right) || (pPSD->rtMargin.bottom < pPSD->rtMinMargin.bottom) ) { StoreExtendedError(PDERR_INITFAILURE); return (FALSE); } }
if (pPSD->Flags & PSD_ENABLEPAGESETUPHOOK) { if (!pPSD->lpfnPageSetupHook) { StoreExtendedError(CDERR_NOHOOK); return (FALSE); } } else { pPSD->lpfnPageSetupHook = NULL; }
if (pPSD->Flags & PSD_ENABLEPAGEPAINTHOOK) { if (!pPSD->lpfnPagePaintHook) { StoreExtendedError(CDERR_NOHOOK); return (FALSE); } } else { pPSD->lpfnPagePaintHook = NULL; }
if ((pPI->pPD) || (pPI->pPD = GlobalAlloc(GPTR, sizeof(PRINTDLG)))) { pPD = pPI->pPD;
pPD->lStructSize = sizeof(PRINTDLG); pPD->hwndOwner = pPSD->hwndOwner; pPD->Flags = PD_PAGESETUP | (pPSD->Flags & (PSD_NOWARNING | PSD_SHOWHELP | PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGESETUPTEMPLATE | PSD_ENABLEPAGESETUPTEMPLATEHANDLE | CD_WX86APP | PSD_NONETWORKBUTTON)); pPD->hInstance = pPSD->hInstance; pPD->lCustData = pPSD->lCustData; pPD->lpfnSetupHook = pPSD->lpfnPageSetupHook; pPD->lpSetupTemplateName = pPSD->lpPageSetupTemplateName; pPD->hSetupTemplate = pPSD->hPageSetupTemplate;
//
// Save original settings in case the user hits cancel.
//
rtMinMargin = pPSD->rtMinMargin; rtMargin = pPSD->rtMargin; ptPaperSize = pPSD->ptPaperSize; Flags = pPSD->Flags;
//
// Make sure the measure choice is set.
//
if ((pPSD->Flags & (PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS)) == 0) { TCHAR szIMeasure[2];
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IMEASURE, szIMeasure, 2); if (szIMeasure[0] == TEXT('1')) { pPSD->Flags |= PSD_INTHOUSANDTHSOFINCHES; } else { pPSD->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS; } }
//
// Set minimum margins to 0 if not passed in.
//
if (!(pPSD->Flags & PSD_MINMARGINS)) { pPSD->rtMinMargin.left = 0; pPSD->rtMinMargin.top = 0; pPSD->rtMinMargin.right = 0; pPSD->rtMinMargin.bottom = 0; }
//
// Set margins to defaults if not passed in.
//
if (!(pPSD->Flags & PSD_MARGINS)) { LONG MarginDefault = (pPSD->Flags & PSD_INTHOUSANDTHSOFINCHES) ? INCHES_DEFAULT : MMS_DEFAULT;
pPSD->rtMargin.left = MarginDefault; pPSD->rtMargin.top = MarginDefault; pPSD->rtMargin.right = MarginDefault; pPSD->rtMargin.bottom = MarginDefault; }
TransferPSD2PD(pPI);
bResult = PrintDlgX(pPI);
TransferPD2PSD(pPI);
if (!bResult) { //
// Restore original settings when the user hits cancel.
//
pPSD->rtMinMargin = rtMinMargin; pPSD->rtMargin = rtMargin; pPSD->ptPaperSize = ptPaperSize; pPSD->Flags = Flags; } } else { StoreExtendedError(CDERR_MEMALLOCFAILURE); }
return (bResult); }
////////////////////////////////////////////////////////////////////////////
//
// PrintLoadIcons
//
////////////////////////////////////////////////////////////////////////////
BOOL PrintLoadIcons() { //
// See if we need to load the icons.
//
if (bAllIconsLoaded == FALSE) { //
// Load the orientation icons.
//
hIconPortrait = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_PORTRAIT)); hIconLandscape = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_LANDSCAPE));
//
// Load the duplex icons.
//
hIconPDuplexNone = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_P_NONE)); hIconLDuplexNone = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_L_NONE)); hIconPDuplexTumble = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_P_HORIZ)); hIconLDuplexTumble = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_L_VERT)); hIconPDuplexNoTumble = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_P_VERT)); hIconLDuplexNoTumble = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_L_HORIZ));
//
// Load the page setup icons.
//
hIconPSStampP = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_P_PSSTAMP)); hIconPSStampL = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_L_PSSTAMP));
//
// Load the collation images.
//
hIconCollate = LoadImage( g_hinst, MAKEINTRESOURCE(ICO_COLLATE), IMAGE_ICON, 0, 0, LR_SHARED ); hIconNoCollate = LoadImage( g_hinst, MAKEINTRESOURCE(ICO_NO_COLLATE), IMAGE_ICON, 0, 0, LR_SHARED );
bAllIconsLoaded = ( hIconPortrait && hIconLandscape && hIconPDuplexNone && hIconLDuplexNone && hIconPDuplexTumble && hIconLDuplexTumble && hIconPDuplexNoTumble && hIconLDuplexNoTumble && hIconPSStampP && hIconPSStampL && hIconCollate && hIconNoCollate ); }
//
// Return TRUE only if all icons/images were loaded properly.
//
return (bAllIconsLoaded); }
////////////////////////////////////////////////////////////////////////////
//
// PrintDisplayPrintDlg
//
////////////////////////////////////////////////////////////////////////////
int PrintDisplayPrintDlg( PPRINTINFO pPI) { LPPRINTDLG pPD = pPI->pPD; int fGotInput = -1; HANDLE hDlgTemplate = NULL; HANDLE hInstance; UINT uiWOWFlag = 0;
//
// NOTE: The print hook check must be done here rather than in
// PrintDlgX. Old apps that set this flag without the
// PrintHook when calling Print Setup will fail - they
// used to succeed.
//
if (pPD->Flags & PD_ENABLEPRINTHOOK) { if (!pPD->lpfnPrintHook) { StoreExtendedError(CDERR_NOHOOK); return (FALSE); } } else { pPD->lpfnPrintHook = NULL; }
if (pPD->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) { if (pPD->hPrintTemplate) { hDlgTemplate = pPD->hPrintTemplate; hInstance = g_hinst; } else { StoreExtendedError(CDERR_NOTEMPLATE); } } else { LPTSTR pTemplateName = NULL;
if (pPD->Flags & PD_ENABLEPRINTTEMPLATE) { if (pPD->lpPrintTemplateName) { if (pPD->hInstance) { pTemplateName = (LPTSTR)pPD->lpPrintTemplateName; hInstance = pPD->hInstance;
} else { StoreExtendedError(CDERR_NOHINSTANCE); } } else { StoreExtendedError(CDERR_NOTEMPLATE); } } else { hInstance = g_hinst; pTemplateName = MAKEINTRESOURCE(PRINTDLGORD); }
if (pTemplateName) { hDlgTemplate = PrintLoadResource( hInstance, pTemplateName, RT_DIALOG); } }
if (!hDlgTemplate) { return (FALSE); }
if (LockResource(hDlgTemplate)) { glpfnPrintHook = GETPRINTHOOKFN(pPD);
if (IS16BITWOWAPP(pPD)) { uiWOWFlag = SCDLG_16BIT; }
fGotInput = (BOOL)DialogBoxIndirectParamAorW( hInstance, (LPDLGTEMPLATE)hDlgTemplate, pPD->hwndOwner, PrintDlgProc, (LPARAM)pPI, uiWOWFlag );
glpfnPrintHook = NULL; if (fGotInput == -1) { StoreExtendedError(CDERR_DIALOGFAILURE); } } else { StoreExtendedError(CDERR_LOCKRESFAILURE); }
return (fGotInput); }
////////////////////////////////////////////////////////////////////////////
//
// PrintDisplaySetupDlg
//
////////////////////////////////////////////////////////////////////////////
int PrintDisplaySetupDlg( PPRINTINFO pPI) { LPPRINTDLG pPD = pPI->pPD; int fGotInput = -1; HANDLE hDlgTemplate = NULL; HANDLE hInstance; UINT uiWOWFlag = 0;
//
// NOTE: The setup hook check must be done here rather than in
// PrintDlgX. Old apps that set this flag without the
// SetupHook when calling Print will fail - they
// used to succeed.
//
if (pPD->Flags & PD_ENABLESETUPHOOK) { if (!pPD->lpfnSetupHook) { StoreExtendedError(CDERR_NOHOOK); return (FALSE); } } else { pPD->lpfnSetupHook = NULL; }
if (pPD->Flags & PD_ENABLESETUPTEMPLATEHANDLE) { if (pPD->hSetupTemplate) { hDlgTemplate = pPD->hSetupTemplate; hInstance = g_hinst; } else { StoreExtendedError(CDERR_NOTEMPLATE); } } else { LPTSTR pTemplateName = NULL;
if (pPD->Flags & PD_ENABLESETUPTEMPLATE) { if (pPD->lpSetupTemplateName) { if (pPD->hInstance) { pTemplateName = (LPTSTR)pPD->lpSetupTemplateName; hInstance = pPD->hInstance; } else { StoreExtendedError(CDERR_NOHINSTANCE); } } else { StoreExtendedError(CDERR_NOTEMPLATE); } } else { hInstance = g_hinst; pTemplateName = ( (pPD->Flags & PD_PRINTSETUP) ? MAKEINTRESOURCE(PRNSETUPDLGORD) : MAKEINTRESOURCE(PAGESETUPDLGORD) ); }
if (pTemplateName) { hDlgTemplate = PrintLoadResource( hInstance, pTemplateName, RT_DIALOG); } }
if (!hDlgTemplate) { return (FALSE); }
if (LockResource(hDlgTemplate)) { glpfnSetupHook = GETSETUPHOOKFN(pPD);
if (IS16BITWOWAPP(pPD)) { uiWOWFlag = SCDLG_16BIT; }
fGotInput = (BOOL)DialogBoxIndirectParamAorW( hInstance, (LPDLGTEMPLATE)hDlgTemplate, pPD->hwndOwner, PrintSetupDlgProc, (LPARAM)pPI, uiWOWFlag );
glpfnSetupHook = NULL; if (fGotInput == -1) { StoreExtendedError(CDERR_DIALOGFAILURE); } } else { StoreExtendedError(CDERR_LOCKRESFAILURE); }
return (fGotInput); }
////////////////////////////////////////////////////////////////////////////
//
// PrintDlgProc
//
// Print Dialog procedure.
//
////////////////////////////////////////////////////////////////////////////
BOOL_PTR CALLBACK PrintDlgProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam) { PPRINTINFO pPI; LPPRINTDLG pPD; HWND hCtl; BOOL bTest; BOOL_PTR bResult; LPDEVMODE pDM; LPDEVNAMES pDN;
if (pPI = (PPRINTINFO)GetProp(hDlg, PRNPROP)) { if ((pPD = pPI->pPD) && (pPD->lpfnPrintHook)) { LPPRINTHOOKPROC lpfnPrintHook = GETPRINTHOOKFN(pPD);
if (pPI->ApiType == COMDLG_ANSI) { ThunkPrintDlgW2A(pPI); }
if ((bResult = (*lpfnPrintHook)(hDlg, wMsg, wParam, lParam))) { if (pPI->ApiType == COMDLG_ANSI) { ThunkPrintDlgA2W(pPI); } return (bResult); } } } else if (glpfnPrintHook && (wMsg != WM_INITDIALOG) && (bResult = (*glpfnPrintHook)(hDlg, wMsg, wParam, lParam))) {
return (bResult); }
switch (wMsg) { case ( WM_INITDIALOG ) : { DWORD dwResult = 0;
HourGlass(TRUE); SetProp(hDlg, PRNPROP, (HANDLE)lParam); glpfnPrintHook = NULL;
pPI = (PPRINTINFO)lParam; pPD = pPI->pPD; if (pPI->pPSD) { TCHAR szTitle[32]; RECT aRtDlg; RECT aRtGrp; RECT aRtYep; RECT aRtCan; HWND hBtnYep = GetDlgItem(hDlg, IDOK); HWND hBtnCan = GetDlgItem(hDlg, IDCANCEL); RECT aRtWhere; RECT aRtCmmnt; LONG GapHeight, DlgTop;
//
// Save the client coordinate for the top of the dialog.
// Also, save the height of the gap between the bottom of
// the original OK button and the bottom of the original
// dialog.
//
GetWindowRect(hDlg, &aRtDlg); GetWindowRect(hBtnYep, &aRtYep); ScreenToClient(hDlg, (LPPOINT)&aRtDlg.left); ScreenToClient(hDlg, (LPPOINT)&aRtDlg.right); ScreenToClient(hDlg, (LPPOINT)&aRtYep.right); DlgTop = aRtDlg.top; GapHeight = (aRtDlg.bottom - aRtYep.bottom > 0) ? aRtDlg.bottom - aRtYep.bottom : 15;
//
// Display the title of the dialog box.
//
GetWindowText(GetParent(hDlg), szTitle, 32); SetWindowText(hDlg, szTitle);
//
// Get the screen and client coordinates for the dialog,
// the Printer group box, the OK button, and the Cancel
// button. These will be used to reposition the OK,
// Cancel, and Help buttons.
//
GetWindowRect(hDlg, &aRtDlg); GetWindowRect(GetDlgItem(hDlg, ID_PRINT_G_PRINTER), &aRtGrp); GetWindowRect(hBtnYep, &aRtYep); GetWindowRect(hBtnCan, &aRtCan);
//
//If we are in a mirrored Dlg the use the left side.
//
if (IS_WINDOW_RTL_MIRRORED(hDlg)) { aRtDlg.right = aRtDlg.left; } ScreenToClient(hDlg , (LPPOINT)&aRtDlg.right); ScreenToClient(hDlg , (LPPOINT)&aRtGrp.right); MapWindowPoints(NULL, hDlg, (LPPOINT)&aRtYep, 2); aRtYep.right -= aRtYep.left; aRtYep.bottom -= aRtYep.top;
MapWindowPoints(NULL, hDlg, (LPPOINT)&aRtCan, 2); aRtCan.right -= aRtCan.left; aRtCan.bottom -= aRtCan.top;
if (pPD->Flags & PD_SHOWHELP) { HWND hBtnHlp = GetDlgItem(hDlg, ID_BOTH_P_HELP); RECT aRtHlp;
//
// Move the Help button up underneath the
// Printer group box.
//
if (hBtnHlp) { GetWindowRect(hBtnHlp, &aRtHlp); MapWindowPoints(NULL, hDlg, (LPPOINT)&aRtHlp, 2); aRtHlp.right -= aRtHlp.left; aRtHlp.bottom -= aRtHlp.top;
MoveWindow( hBtnHlp, aRtHlp.left, aRtGrp.bottom + 2 * aRtHlp.bottom / 3, aRtHlp.right, aRtHlp.bottom, FALSE ); } }
//
// Move the OK and Cancel buttons up underneath the
// Printer group box.
//
MoveWindow( hBtnYep, aRtYep.left, aRtGrp.bottom + 2 * aRtYep.bottom / 3, aRtYep.right, aRtYep.bottom, FALSE ); MoveWindow( hBtnCan, aRtCan.left, aRtGrp.bottom + 2 * aRtCan.bottom / 3, aRtCan.right, aRtCan.bottom, FALSE );
//
// Resize the dialog.
//
GetWindowRect(hBtnYep, &aRtYep); MapWindowPoints(NULL, hDlg, (LPPOINT)&aRtYep, 2); MoveWindow( hDlg, aRtDlg.left, aRtDlg.top, aRtDlg.right, (aRtYep.bottom - DlgTop) + GapHeight, FALSE );
//
// Hide all other print dlg items.
//
// NOTE: Need to do a SetWindowPos to actually remove
// the window so that the AddNetButton call does
// not think it's there.
//
SetWindowPos( GetDlgItem(hDlg, ID_PRINT_X_TOFILE), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER ); SetWindowPos( GetDlgItem(hDlg, ID_PRINT_X_COLLATE), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER ); SetWindowPos( GetDlgItem(hDlg, ID_PRINT_E_FROM), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER ); SetWindowPos( GetDlgItem(hDlg, ID_PRINT_E_TO), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER ); SetWindowPos( GetDlgItem(hDlg, ID_PRINT_E_COPIES), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER ); SetWindowPos( GetDlgItem(hDlg, ID_PRINT_G_RANGE), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER ); SetWindowPos( GetDlgItem(hDlg, ID_PRINT_G_COPIES), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER ); SetWindowPos( GetDlgItem(hDlg, ID_PRINT_I_COLLATE), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER ); SetWindowPos( GetDlgItem(hDlg, ID_PRINT_R_ALL), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER ); SetWindowPos( GetDlgItem(hDlg, ID_PRINT_R_SELECTION), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER ); SetWindowPos( GetDlgItem(hDlg, ID_PRINT_R_PAGES), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER ); SetWindowPos( GetDlgItem(hDlg, ID_PRINT_S_FROM), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER ); SetWindowPos( GetDlgItem(hDlg, ID_PRINT_S_TO), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER ); SetWindowPos( GetDlgItem(hDlg, ID_PRINT_S_COPIES), NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
//
// Enlarge the comment edit control, since the
// "print to file" check box is hidden.
//
GetWindowRect(GetDlgItem(hDlg, ID_BOTH_S_WHERE), &aRtWhere); GetWindowRect( hCtl = GetDlgItem(hDlg, ID_BOTH_S_COMMENT), &aRtCmmnt ); MapWindowPoints(NULL, hDlg, (LPPOINT)&aRtCmmnt, 2); MoveWindow( hCtl, aRtCmmnt.left, aRtCmmnt.top, aRtWhere.right - aRtWhere.left, aRtWhere.bottom - aRtWhere.top, FALSE );
//
// Add or hide net button, if necessary.
//
if ((pPD->Flags & PD_NONETWORKBUTTON)) { if (hCtl = GetDlgItem(hDlg, ID_BOTH_P_NETWORK)) { EnableWindow(hCtl, FALSE); ShowWindow(hCtl, SW_HIDE); } } else { AddNetButton( hDlg, g_hinst, FILE_BOTTOM_MARGIN, TRUE, FALSE, TRUE);
//
// The button can be added in two ways -
// statically (they have it predefined in their template) and
// dynamically (successful call to AddNetButton).
//
if (!IsNetworkInstalled()) { hCtl = GetDlgItem(hDlg, ID_BOTH_P_NETWORK);
EnableWindow(hCtl, FALSE); ShowWindow(hCtl, SW_HIDE); } } } else { if (pPD->Flags & PD_COLLATE) { pPI->Status |= PI_COLLATE_REQUESTED; } }
if (!PrintInitGeneral(hDlg, ID_PRINT_C_NAME, pPI) || ((dwResult = PrintInitPrintDlg( hDlg, wParam, pPI )) == 0xFFFFFFFF)) { RemoveProp(hDlg, PRNPROP); EndDialog(hDlg, -2); }
HourGlass(FALSE); bResult = (dwResult == 1); return (bResult); } case ( WM_COMMAND ) : { if (!pPI) { return (FALSE); }
bResult = FALSE;
switch (GET_WM_COMMAND_ID(wParam, lParam)) { case ( ID_PRINT_C_NAME ) : // Printer Name combobox
{ if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE) { PrintPrinterChanged(hDlg, ID_PRINT_C_NAME, pPI); } else if ( (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_DROPDOWN) && !(pPI->Status & PI_PRINTERS_ENUMERATED) ) { //
// Enumerate printers if this hasn't been done yet.
//
PrintEnumAndSelect( hDlg, ID_PRINT_C_NAME, pPI, (pPI->pCurPrinter) ? pPI->pCurPrinter->pPrinterName : NULL, TRUE ); }
break; } case ( ID_BOTH_P_PROPERTIES ) : // Properties... button
{ PrintChangeProperties(hDlg, ID_PRINT_C_NAME, pPI);
break; } case ( ID_PRINT_P_SETUP ) : // Setup... button
{ DWORD dwFlags = pPD->Flags; HWND hwndOwner = pPD->hwndOwner;
pPD->Flags |= PD_PRINTSETUP; pPD->Flags &= ~(PD_RETURNDC | PD_RETURNIC); pPI->Status |= PI_PRINTDLGX_RECURSE; pPD->hwndOwner = hDlg;
if (PrintDlgX(pPI)) { if (!PrintInitBannerAndQuality(hDlg, pPI, pPD)) { StoreExtendedError(CDERR_GENERALCODES); } }
pPI->Status &= ~PI_PRINTDLGX_RECURSE; pPD->Flags = dwFlags; pPD->hwndOwner = hwndOwner;
break; } case ( ID_PRINT_R_ALL ) : // Print Range - All
case ( ID_PRINT_R_SELECTION ) : // Print Range - Selection
case ( ID_PRINT_R_PAGES ) : // Print Range - Pages (From, To)
{ CheckRadioButton( hDlg, ID_PRINT_R_ALL, ID_PRINT_R_PAGES, GET_WM_COMMAND_ID(wParam, lParam) );
//
// Only move the the focus to the "From" control when
// the up/down arrow is NOT used.
//
if ( !IS_KEY_PRESSED(VK_UP) && !IS_KEY_PRESSED(VK_DOWN) && ((BOOL)(GET_WM_COMMAND_ID(wParam, lParam) == ID_PRINT_R_PAGES)) ) { SendMessage( hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, ID_PRINT_E_FROM), 1L ); }
break; } case ( ID_PRINT_E_FROM ) : // From (Print Range - Pages)
{ //
// Only enable the "To" control if the "From" control
// contains a value.
//
GetDlgItemInt(hDlg, ID_PRINT_E_FROM, &bTest, FALSE); EnableWindow(GetDlgItem(hDlg, ID_PRINT_S_TO), bTest); EnableWindow(GetDlgItem(hDlg, ID_PRINT_E_TO), bTest);
// FALL THRU...
} case ( ID_PRINT_E_TO ) : // To (Print Range - Pages)
{ if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) { CheckRadioButton( hDlg, ID_PRINT_R_ALL, ID_PRINT_R_PAGES, ID_PRINT_R_PAGES ); }
break; }
case (ID_PRINT_E_COPIES ) : { if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) { BOOL bTest; //
// Save the number of copies.
//
DWORD nCopies = GetDlgItemInt(hDlg, ID_PRINT_E_COPIES, &bTest, FALSE);
//
// If the copy count is > 1, enable collate. Otherwise,
// disable it.
//
if (hCtl = GetDlgItem(hDlg, ID_PRINT_X_COLLATE)) { EnableWindow(hCtl, (nCopies > 1)); }
}
break; }
case ( ID_PRINT_X_COLLATE ) : // Collate check box
{ if (hCtl = GetDlgItem(hDlg, ID_PRINT_I_COLLATE)) { ShowWindow(hCtl, SW_HIDE); SendMessage( hCtl, STM_SETICON, IsDlgButtonChecked(hDlg, ID_PRINT_X_COLLATE) ? (LONG_PTR)hIconCollate : (LONG_PTR)hIconNoCollate, 0L ); ShowWindow(hCtl, SW_SHOW);
if (IsDlgButtonChecked(hDlg, ID_PRINT_X_COLLATE)) { pPI->Status |= PI_COLLATE_REQUESTED; } else { pPI->Status &= ~PI_COLLATE_REQUESTED; } }
break; } case ( ID_BOTH_P_NETWORK ) : // Network... button
{ HANDLE hPrinter; DWORD cbPrinter = 0; PPRINTER_INFO_2 pPrinter = NULL;
hPrinter = (HANDLE)ConnectToPrinterDlg(hDlg, 0); if (hPrinter) { if (!GetPrinter( hPrinter, 2, (LPBYTE)pPrinter, cbPrinter, &cbPrinter )) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { if (pPrinter = LocalAlloc(LPTR, cbPrinter)) { if (!GetPrinter( hPrinter, 2, (LPBYTE)pPrinter, cbPrinter, &cbPrinter )) { StoreExtendedError(PDERR_PRINTERNOTFOUND); } else { SendDlgItemMessage( hDlg, ID_PRINT_C_NAME, CB_RESETCONTENT, 0, 0 ); PrintEnumAndSelect( hDlg, ID_PRINT_C_NAME, pPI, pPrinter->pPrinterName, TRUE ); } } else { StoreExtendedError(CDERR_MEMALLOCFAILURE); } } else { StoreExtendedError(PDERR_SETUPFAILURE); } }
if (!GetStoredExtendedError()) { SendDlgItemMessage( hDlg, ID_PRINT_C_NAME, CB_SETCURSEL, (WPARAM)SendDlgItemMessage( hDlg, ID_PRINT_C_NAME, CB_FINDSTRING, 0, (LPARAM)pPrinter->pPrinterName ), (LPARAM)0 );
PrintPrinterChanged(hDlg, ID_PRINT_C_NAME, pPI); }
LocalFree(pPrinter); ClosePrinter(hPrinter); } break; } case ( ID_BOTH_P_HELP ) : // Help button
{ if (pPI->ApiType == COMDLG_ANSI) { if (msgHELPA && pPD->hwndOwner) { SendMessage( pPD->hwndOwner, msgHELPA, (WPARAM)hDlg, (DWORD_PTR)pPI->pPDA ); } } else { if (msgHELPW && pPD->hwndOwner) { SendMessage( pPD->hwndOwner, msgHELPW, (WPARAM)hDlg, (DWORD_PTR)pPD ); } }
break; } case ( IDOK ) : // OK button
{ bResult = TRUE; if (!(pPI->pPSD)) { pPD->Flags &= ~((DWORD)( PD_PRINTTOFILE | PD_PAGENUMS | PD_SELECTION | PD_COLLATE ));
pPD->nCopies = (WORD)GetDlgItemInt( hDlg, ID_PRINT_E_COPIES, &bTest, FALSE ); if ((!bTest) || (!pPD->nCopies)) { PrintEditError( hDlg, ID_PRINT_E_COPIES, iszCopiesZero ); return (TRUE); }
if (IsDlgButtonChecked(hDlg, ID_PRINT_R_SELECTION)) { pPD->Flags |= PD_SELECTION; } else if (IsDlgButtonChecked(hDlg, ID_PRINT_R_PAGES)) { //
// Check the "From" and "To" values.
//
pPD->Flags |= PD_PAGENUMS; pPD->nFromPage = (WORD)GetDlgItemInt( hDlg, ID_PRINT_E_FROM, &bTest, FALSE ); if (!bTest) { PrintEditError( hDlg, ID_PRINT_E_FROM, iszPageFromError ); return (TRUE); }
pPD->nToPage = (WORD)GetDlgItemInt( hDlg, ID_PRINT_E_TO, &bTest, FALSE ); if (!bTest) { TCHAR szBuf[PAGE_EDIT_SIZE + 1];
if (GetDlgItemText( hDlg, ID_PRINT_E_TO, szBuf, PAGE_EDIT_SIZE + 1 )) { PrintEditError( hDlg, ID_PRINT_E_TO, iszPageToError ); return (TRUE); } else { pPD->nToPage = pPD->nFromPage; } }
if ( (pPD->nFromPage < pPD->nMinPage) || (pPD->nFromPage > pPD->nMaxPage) ) { PrintEditError( hDlg, ID_PRINT_E_FROM, iszPageRangeError, pPD->nMinPage, pPD->nMaxPage ); return (TRUE); } if ( (pPD->nToPage < pPD->nMinPage) || (pPD->nToPage > pPD->nMaxPage) ) { PrintEditError( hDlg, ID_PRINT_E_TO, iszPageRangeError, pPD->nMinPage, pPD->nMaxPage ); return (TRUE); } if (pPD->nFromPage > pPD->nToPage) { PrintEditError( hDlg, ID_PRINT_E_FROM, iszFromToError ); return (TRUE); } } }
HourGlass(TRUE);
if (IsDlgButtonChecked(hDlg, ID_PRINT_X_TOFILE)) { pPD->Flags |= PD_PRINTTOFILE; }
if ( (hCtl = GetDlgItem(hDlg, ID_PRINT_X_COLLATE)) && IsWindowEnabled(hCtl) && IsDlgButtonChecked(hDlg, ID_PRINT_X_COLLATE) ) { pPD->Flags |= PD_COLLATE; }
if (!PrintSetCopies(hDlg, pPI, ID_PRINT_C_NAME)) { HourGlass(FALSE); return (TRUE); }
pDM = NULL; pDN = NULL; if (pPD->hDevMode) { pDM = GlobalLock(pPD->hDevMode); } if (pPD->hDevNames) { pDN = GlobalLock(pPD->hDevNames); } if (pDM && pDN) { DWORD nNum;
if ( GetDlgItem(hDlg, ID_PRINT_C_QUALITY) && (nNum = (DWORD) SendDlgItemMessage( hDlg, ID_PRINT_C_QUALITY, CB_GETCURSEL, 0, 0L )) != CB_ERR ) { pDM->dmPrintQuality = (WORD)SendDlgItemMessage( hDlg, ID_PRINT_C_QUALITY, CB_GETITEMDATA, (WPARAM)nNum, 0L ); }
PrintReturnICDC(pPD, pDN, pDM); } if (pDM) { GlobalUnlock(pPD->hDevMode); } if (pDN) { GlobalUnlock(pPD->hDevNames); }
if (pPD->Flags & CD_WOWAPP) { UpdateSpoolerInfo(pPI); }
// FALL THRU...
} case ( IDCANCEL ) : // Cancel button
case ( IDABORT ) : { HourGlass(TRUE);
glpfnPrintHook = GETPRINTHOOKFN(pPD);
RemoveProp(hDlg, PRNPROP); EndDialog(hDlg, bResult);
HourGlass(FALSE);
break; } default : { return (FALSE); break; } }
break; } case ( WM_MEASUREITEM ) : { PrintMeasureItem(hDlg, (LPMEASUREITEMSTRUCT)lParam); break; } case ( WM_HELP ) : { if (IsWindowEnabled(hDlg)) { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR)aPrintHelpIDs ); } break; } case ( WM_CONTEXTMENU ) : { if (IsWindowEnabled(hDlg)) { WinHelp( (HWND)wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(LPVOID)aPrintHelpIDs ); } break; } case ( WM_CTLCOLOREDIT ) : { if (GetWindowLong((HWND)lParam, GWL_STYLE) & ES_READONLY) { return ( (BOOL_PTR) SendMessage(hDlg, WM_CTLCOLORDLG, wParam, lParam) ); }
// FALL THRU...
} default : { return (FALSE); break; } }
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// PrintSetupDlgProc
//
// Print Setup Dialog proc.
//
////////////////////////////////////////////////////////////////////////////
BOOL_PTR CALLBACK PrintSetupDlgProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam) { PPRINTINFO pPI; LPPRINTDLG pPD = NULL; BOOL_PTR bResult; UINT uCmdId; LPDEVMODE pDM;
if (pPI = (PPRINTINFO)GetProp(hDlg, PRNPROP)) { if ((pPD = pPI->pPD) && (pPD->lpfnSetupHook)) { LPSETUPHOOKPROC lpfnSetupHook = GETSETUPHOOKFN(pPD);
if (pPI->ApiType == COMDLG_ANSI) { ThunkPrintDlgW2A(pPI); TransferPDA2PSD(pPI);
pPI->NestCtr++; bResult = (*lpfnSetupHook)(hDlg, wMsg, wParam, lParam); pPI->NestCtr--;
if (bResult) { TransferPSD2PDA(pPI); ThunkPrintDlgA2W(pPI); if (pPI->NestCtr == 0) { TransferPD2PSD(pPI); } return (bResult); } } else { TransferPD2PSD(pPI);
bResult = (*lpfnSetupHook)(hDlg, wMsg, wParam, lParam);
if (bResult) { TransferPSD2PD(pPI); return (bResult); } } } } else if (glpfnSetupHook && (wMsg != WM_INITDIALOG) && (bResult = (*glpfnSetupHook)(hDlg, wMsg, wParam, lParam))) { return (bResult); }
switch (wMsg) { case ( WM_INITDIALOG ) : { DWORD dwResult = 0;
//
// Disable RTL mirroring on the WHITE-SAMPLE
//
SetWindowLong(GetDlgItem(hDlg, ID_SETUP_W_SAMPLE), GWL_EXSTYLE, GetWindowLong(GetDlgItem(hDlg, ID_SETUP_W_SAMPLE), GWL_EXSTYLE) & ~RTL_MIRRORED_WINDOW); HourGlass(TRUE); SetProp(hDlg, PRNPROP, (HANDLE)lParam); pPI = (PPRINTINFO)lParam; pPI->bKillFocus = FALSE; glpfnSetupHook = NULL;
if (!PrintInitGeneral(hDlg, ID_SETUP_C_NAME, pPI) || ((dwResult = PrintInitSetupDlg( hDlg, wParam, pPI )) == 0xFFFFFFFF)) { RemoveProp(hDlg, PRNPROP); EndDialog(hDlg, FALSE); } else if (pPI->pPSD && (pPI->pPSD->Flags & PSD_RETURNDEFAULT)) { //
// PSD_RETURNDEFAULT goes through the entire initialization
// in order to set rtMinMargin, rtMargin, and ptPaperSize.
// Win95 Notepad relies on this behavior.
//
SendMessage(hDlg, WM_COMMAND, IDOK, 0); }
HourGlass(FALSE); bResult = (dwResult == 1); return (bResult); } case ( WM_COMMAND ) : { if (!pPI) { return (FALSE); }
bResult = FALSE;
switch (uCmdId = GET_WM_COMMAND_ID(wParam, lParam)) { case ( ID_SETUP_C_NAME ) : // Printer Name combobox
{ if ( (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_DROPDOWN) && !(pPI->Status & PI_PRINTERS_ENUMERATED) ) { //
// Enumerate printers if this hasn't been done yet.
//
PrintEnumAndSelect( hDlg, ID_SETUP_C_NAME, pPI, (pPI->pCurPrinter) ? pPI->pCurPrinter->pPrinterName : NULL, TRUE ); } if (GET_WM_COMMAND_CMD(wParam, lParam) != CBN_SELCHANGE) { break; } if ( !GetDlgItem(hDlg, ID_SETUP_R_SPECIFIC) || IsDlgButtonChecked(hDlg, ID_SETUP_R_SPECIFIC) ) { PrintPrinterChanged(hDlg, ID_SETUP_C_NAME, pPI); break; }
uCmdId = ID_SETUP_R_SPECIFIC;
// FALL THRU...
} case ( ID_SETUP_R_DEFAULT ) : // Default printer
case ( ID_SETUP_R_SPECIFIC ) : // Specific printer
{ //
// Sanity check for Publisher bug where user tries to
// set focus to ID_SETUP_R_DEFAULT on exit if the
// dialog has no default printer.
//
if (pPI->hCurPrinter) { HWND hCmb; DWORD dwStyle;
hCmb = GetDlgItem(hDlg, ID_SETUP_C_NAME); if (hCmb && (uCmdId == ID_SETUP_R_DEFAULT)) { if (!(pPI->Status & PI_PRINTERS_ENUMERATED)) { //
// Enumerate printers if this hasn't been
// done yet. Otherwise, the default printer
// may not be found in the list box when
// switching from Specific to Default.
//
PrintEnumAndSelect( hDlg, ID_SETUP_C_NAME, pPI, NULL, TRUE ); }
SendMessage( hCmb, CB_SETCURSEL, (WPARAM)SendMessage( hCmb, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(pPI->szDefaultPrinter) ), (LPARAM)0 ); }
PrintPrinterChanged(hDlg, ID_SETUP_C_NAME, pPI);
CheckRadioButton( hDlg, ID_SETUP_R_DEFAULT, ID_SETUP_R_SPECIFIC, uCmdId);
dwStyle = GetWindowLong(hCmb, GWL_STYLE); if (uCmdId == ID_SETUP_R_DEFAULT) { dwStyle &= ~WS_TABSTOP; } else { dwStyle |= WS_TABSTOP; SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)hCmb, 1L); } SetWindowLong(hCmb, GWL_STYLE, dwStyle); }
break; } case ( ID_BOTH_P_PROPERTIES ) : // Properties... button
{ PrintChangeProperties(hDlg, ID_SETUP_C_NAME, pPI);
break; } case ( ID_SETUP_P_MORE ) : // More... button
{ pDM = GlobalLock(pPD->hDevMode);
AdvancedDocumentProperties( hDlg, pPI->hCurPrinter, (pPI->pCurPrinter) ? pPI->pCurPrinter->pPrinterName : NULL, pDM, pDM );
GlobalUnlock(pPD->hDevMode); SendMessage( hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDOK), 1L );
break; } case ( ID_SETUP_R_PORTRAIT ) : // Portrait
case ( ID_SETUP_R_LANDSCAPE ) : // Landscape
{ if ((pPD->hDevMode) && (pDM = GlobalLock(pPD->hDevMode))) { PrintSetOrientation( hDlg, pPI, pDM, pPI->uiOrientationID, uCmdId ); GlobalUnlock(pPD->hDevMode); }
// FALL THRU ...
} case ( ID_SETUP_R_NONE ) : // None (2-Sided)
case ( ID_SETUP_R_LONG ) : // Long Side (2-Sided)
case ( ID_SETUP_R_SHORT ) : // Short Side (2-Sided)
{ if ((pPD->hDevMode) && (pDM = GlobalLock(pPD->hDevMode))) { PrintSetDuplex(hDlg, pDM, uCmdId); GlobalUnlock(pPD->hDevMode); }
break; } case ( ID_SETUP_C_SIZE ) : // Size combobox
{ UINT Orientation;
if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE) { if ((pPD->hDevMode) && (pDM = GlobalLock(pPD->hDevMode))) { // pDM->dmFields |= DM_PAPERSIZE;
pDM->dmPaperSize = (SHORT)SendMessage( (HWND)lParam, CB_GETITEMDATA, SendMessage( (HWND)lParam, CB_GETCURSEL, 0, 0L ), 0L );
Orientation = IsDlgButtonChecked(hDlg, ID_SETUP_R_PORTRAIT) ? ID_SETUP_R_PORTRAIT : ID_SETUP_R_LANDSCAPE; PrintSetOrientation( hDlg, pPI, pDM, Orientation, Orientation ); GlobalUnlock(pPD->hDevMode); } }
break; } case ( ID_SETUP_C_SOURCE ) : // Source combobox
{ if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE) { if ((pPD->hDevMode) && (pDM = GlobalLock(pPD->hDevMode))) { // pDM->dmFields |= DM_DEFAULTSOURCE;
pDM->dmDefaultSource = (SHORT)SendMessage( (HWND)lParam, CB_GETITEMDATA, SendMessage( (HWND)lParam, CB_GETCURSEL, 0, 0L ), 0L );
GlobalUnlock(pPD->hDevMode); } }
break; } case ( ID_SETUP_E_LEFT ) : // Left (Margins)
case ( ID_SETUP_E_TOP ) : // Top (Margins)
case ( ID_SETUP_E_RIGHT ) : // Right (Margins)
case ( ID_SETUP_E_BOTTOM ) : // Bottom (Margins)
{ if (pPI->bKillFocus) { break; }
switch (GET_WM_COMMAND_CMD(wParam, lParam)) { case ( EN_KILLFOCUS ) : { pPI->bKillFocus = TRUE; PrintSetMargin( hDlg, pPI, uCmdId, *((LONG*)&pPI->pPSD->rtMargin + uCmdId - ID_SETUP_E_LEFT) ); pPI->bKillFocus = FALSE;
break; } case ( EN_CHANGE ) : { HWND hSample;
PrintGetMargin( GET_WM_COMMAND_HWND(wParam, lParam), pPI, *((LONG*)&pPI->pPSD->rtMinMargin + uCmdId - ID_SETUP_E_LEFT), (LONG*)&pPI->pPSD->rtMargin + uCmdId - ID_SETUP_E_LEFT, (LONG*)&pPI->RtMarginMMs + uCmdId - ID_SETUP_E_LEFT );
if (hSample = GetDlgItem(hDlg, ID_SETUP_W_SAMPLE)) { RECT rect;
GetClientRect(hSample, &rect); InflateRect(&rect, -1, -1); InvalidateRect(hSample, &rect, TRUE); }
break; } }
break; } case ( ID_SETUP_P_PRINTER ) : // Printer... button
{ //
// Save a copy of the original values.
//
HWND hwndOwner = pPD->hwndOwner; DWORD dwFlags = pPD->Flags; HINSTANCE hInstance = pPD->hInstance; LPCTSTR lpPrintTemplateName = pPD->lpPrintTemplateName;
//
// Set up pPI so that PrintDlgX can do all the work.
//
pPD->hwndOwner = hDlg; pPD->Flags &= ~( PD_ENABLEPRINTTEMPLATEHANDLE | PD_RETURNIC | PD_RETURNDC | PD_PAGESETUP ); pPD->Flags |= PD_ENABLEPRINTTEMPLATE; pPD->hInstance = g_hinst; pPD->lpPrintTemplateName = MAKEINTRESOURCE(PRINTDLGORD); pPI->Status |= PI_PRINTDLGX_RECURSE;
if (PrintDlgX(pPI)) { PrintUpdateSetupDlg( hDlg, pPI, GlobalLock(pPD->hDevMode), TRUE ); GlobalUnlock(pPD->hDevMode); }
//
// Restore the original values.
//
pPD->hwndOwner = hwndOwner; pPD->Flags = dwFlags; pPD->hInstance = hInstance; pPD->lpPrintTemplateName = lpPrintTemplateName; pPI->Status &= ~PI_PRINTDLGX_RECURSE;
//
// Set the keyboard focus to the OK button.
//
SendMessage( hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDOK), 1L );
HourGlass(FALSE);
break; } case ( ID_BOTH_P_NETWORK ) : // Network... button
{ HANDLE hPrinter; DWORD cbPrinter = 0; PPRINTER_INFO_2 pPrinter = NULL;
hPrinter = (HANDLE)ConnectToPrinterDlg(hDlg, 0); if (hPrinter) { if (!GetPrinter( hPrinter, 2, (LPBYTE)pPrinter, cbPrinter, &cbPrinter )) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { if (pPrinter = LocalAlloc(LPTR, cbPrinter)) { if (!GetPrinter( hPrinter, 2, (LPBYTE)pPrinter, cbPrinter, &cbPrinter )) { StoreExtendedError(PDERR_PRINTERNOTFOUND); } else { SendDlgItemMessage( hDlg, ID_SETUP_C_NAME, CB_RESETCONTENT, 0, 0 ); PrintEnumAndSelect( hDlg, ID_SETUP_C_NAME, pPI, pPrinter->pPrinterName, TRUE ); } } else { StoreExtendedError(CDERR_MEMALLOCFAILURE); } } else { StoreExtendedError(PDERR_SETUPFAILURE); } }
if (!GetStoredExtendedError()) { SendDlgItemMessage( hDlg, ID_SETUP_C_NAME, CB_SETCURSEL, (WPARAM)SendDlgItemMessage( hDlg, ID_SETUP_C_NAME, CB_FINDSTRING, 0, (LPARAM)pPrinter->pPrinterName ), (LPARAM)0 );
PrintPrinterChanged(hDlg, ID_SETUP_C_NAME, pPI); }
LocalFree(pPrinter); ClosePrinter(hPrinter); } break; } case ( ID_BOTH_P_HELP ) : // Help button
{ if (pPI->ApiType == COMDLG_ANSI) { if (msgHELPA && pPD->hwndOwner) { SendMessage( pPD->hwndOwner, msgHELPA, (WPARAM)hDlg, (LPARAM)pPI->pPDA ); } } else { if (msgHELPW && pPD->hwndOwner) { SendMessage( pPD->hwndOwner, msgHELPW, (WPARAM)hDlg, (LPARAM)pPD ); } }
break; } case ( IDOK ) : // OK button
{ LPPAGESETUPDLG pPSD = pPI->pPSD; int i;
if (pPSD) { if ((pPSD->rtMinMargin.left + pPSD->rtMinMargin.right > pPSD->ptPaperSize.x) || (pPSD->rtMinMargin.top + pPSD->rtMinMargin.bottom > pPSD->ptPaperSize.y)) { //
// This is an unprintable case that can happen.
// Let's assume that the driver is at fault
// and accept whatever the user entered.
//
} else if (pPSD->rtMargin.left + pPSD->rtMargin.right > pPSD->ptPaperSize.x) { i = (pPSD->rtMargin.left >= pPSD->rtMargin.right) ? ID_SETUP_E_LEFT : ID_SETUP_E_RIGHT; PrintEditError(hDlg, i, iszBadMarginError); return (TRUE); } else if (pPSD->rtMargin.top + pPSD->rtMargin.bottom > pPSD->ptPaperSize.y) { i = (pPSD->rtMargin.top >= pPSD->rtMargin.bottom) ? ID_SETUP_E_TOP : ID_SETUP_E_BOTTOM; PrintEditError(hDlg, i, iszBadMarginError); return (TRUE); } } else { HourGlass(TRUE); if (!PrintSetCopies(hDlg, pPI, ID_SETUP_C_NAME)) { HourGlass(FALSE); return (TRUE); } }
bResult = TRUE; SetFocus( GetDlgItem(hDlg, IDOK) );
// FALL THRU...
} case ( IDCANCEL ) : // Cancel button
case ( IDABORT ) : { HourGlass(TRUE);
if (bResult) { PrintGetSetupInfo(hDlg, pPD); if (pPD->Flags & CD_WOWAPP) { UpdateSpoolerInfo(pPI); } } else { SetFocus( GetDlgItem(hDlg, IDCANCEL) ); } pPI->bKillFocus = TRUE;
glpfnSetupHook = GETSETUPHOOKFN(pPD);
RemoveProp(hDlg, PRNPROP); EndDialog(hDlg, bResult);
HourGlass(FALSE);
break; } default : { return (FALSE); break; } }
break; } case ( WM_MEASUREITEM ) : { PrintMeasureItem(hDlg, (LPMEASUREITEMSTRUCT)lParam); break; } case ( WM_HELP ) : { if (IsWindowEnabled(hDlg)) { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR)( pPD && (pPD->Flags & PD_PRINTSETUP) ? aPrintSetupHelpIDs : aPageSetupHelpIDs) ); } break; } case ( WM_CONTEXTMENU ) : { if (IsWindowEnabled(hDlg)) { WinHelp( (HWND)wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(LPVOID)( pPD && (pPD->Flags & PD_PRINTSETUP) ? aPrintSetupHelpIDs : aPageSetupHelpIDs) ); } break; } case ( WM_CTLCOLOREDIT ) : { if (GetWindowLong((HWND)lParam, GWL_STYLE) & ES_READONLY) { return ( (BOOL_PTR) SendMessage(hDlg, WM_CTLCOLORDLG, wParam, lParam) ); }
// FALL THRU...
} default : { return (FALSE); break; } }
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// PrintEditMarginProc
//
////////////////////////////////////////////////////////////////////////////
LRESULT PrintEditMarginProc( HWND hWnd, UINT msg, WPARAM wP, LPARAM lP) { if ( (msg == WM_CHAR) && (wP != BACKSPACE) && (wP != CTRL_X_CUT) && (wP != CTRL_C_COPY) && (wP != CTRL_V_PASTE) && (wP != (WPARAM)cIntlDecimal) && ((wP < TEXT('0')) || (wP > TEXT('9'))) ) { MessageBeep(0); return (FALSE); }
return ( CallWindowProc(lpEditMarginProc, hWnd, msg, wP, lP) ); }
////////////////////////////////////////////////////////////////////////////
//
// PrintPageSetupPaintProc
//
////////////////////////////////////////////////////////////////////////////
LRESULT PrintPageSetupPaintProc( HWND hWnd, UINT msg, WPARAM wP, LPARAM lP) { LRESULT lResult; PPRINTINFO pPI; LPPAGESETUPDLG pPSD; HDC hDC; RECT aRt, aRtPage, aRtUser; PAINTSTRUCT aPs; HGDIOBJ hPen, hBr, hFont, hFontGreek; HRGN hRgn; TCHAR szGreekText[] = TEXT("Dheevaeilnorpoefdi lfaocr, \nMoiccsriocsnoafrtf \tbnya\nSFlr acnn IF iynnnaepgmaonc\n F&i nyneelglaanm 'Ox' Mnaalgleenyn i&f QCnoamgpeannnyi FI nxca.r\nFSoaynb Ftrfaonscoirscciom, \rCoafl idfeopronlieav\ne\n"); LPTSTR psGreekText; int i;
if (msg != WM_PAINT) { return ( CallWindowProc(lpStaticProc, hWnd, msg, wP, lP) ); }
hDC = BeginPaint(hWnd, &aPs); GetClientRect(hWnd, &aRt); FillRect(hDC, &aRt, (HBRUSH)GetStockObject(WHITE_BRUSH)); EndPaint(hWnd, &aPs); lResult = 0;
if ( (!(hDC = GetDC(hWnd))) || (!(pPI = (PPRINTINFO)GetProp(GetParent(hWnd), PRNPROP))) ) { return (0); } pPSD = pPI->pPSD;
TransferPD2PSD(pPI); aRtPage = aRt; hPen = (HGDIOBJ)CreatePen(PS_SOLID, 1, RGB(128, 128, 128)); hPen = SelectObject(hDC, hPen);
// Rectangle() does not work here
MoveToEx( hDC, 0 , 0 , NULL ); LineTo( hDC, aRt.right - 1, 0 ); MoveToEx( hDC, 0 , 1 , NULL ); LineTo( hDC, 0 , aRt.bottom - 1 ); DeleteObject(SelectObject(hDC, hPen));
// Rectangle() does not work here
MoveToEx( hDC, aRt.right - 1, 0 , NULL ); LineTo( hDC, aRt.right - 1, aRt.bottom - 1 ); MoveToEx( hDC, 0 , aRt.bottom - 1, NULL ); LineTo( hDC, aRt.right , aRt.bottom - 1 );
SetBkMode(hDC, TRANSPARENT); hPen = (HGDIOBJ)CreatePen(PS_DOT, 1, RGB(128, 128, 128)); hPen = SelectObject(hDC, hPen); hBr = (HGDIOBJ)GetStockObject(NULL_BRUSH); hBr = SelectObject(hDC, hBr);
hFont = hFontGreek = CreateFont( pPI->PtMargins.y, pPI->PtMargins.x, 0, 0, FW_DONTCARE, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, NULL ); hFont = SelectObject(hDC, hFont);
InflateRect(&aRt, -1, -1); aRtUser = aRt; hRgn = CreateRectRgnIndirect(&aRtUser); SelectClipRgn(hDC, hRgn); DeleteObject(hRgn);
if (pPSD->lpfnPagePaintHook) { WORD wFlags; LPPAGEPAINTHOOK lpfnPagePaintHook = GETPAGEPAINTHOOKFN(pPSD);
switch (pPI->dwRotation) { default : { //
// Portrait mode only.
//
wFlags = 0x0000; break; } case ( ROTATE_LEFT ) : { //
// Dot-Matrix (270)
//
wFlags = 0x0001; break; } case ( ROTATE_RIGHT ) : { //
// HP PCL (90)
//
wFlags = 0x0003; break; } } if ( !wFlags || IsDlgButtonChecked(GetParent(hWnd), ID_SETUP_R_PORTRAIT) ) { //
// Paper in portrait.
//
wFlags |= 0x0004; } if (pPI->pPD->Flags & PI_WPAPER_ENVELOPE) { wFlags |= 0x0008; if (aRt.right < aRt.bottom) { //
// Envelope in portrait.
//
wFlags |= 0x0010; } } if ((*lpfnPagePaintHook)( hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(pPI->wPaper, wFlags), (LPARAM)pPSD ) || (*lpfnPagePaintHook)( hWnd, WM_PSD_FULLPAGERECT, (WPARAM)hDC, (LPARAM)(LPRECT)&aRtUser )) { goto NoMorePainting; }
aRtUser = aRt; aRtUser.left += aRtUser.right * pPI->RtMinMarginMMs.left / pPI->PtPaperSizeMMs.x; aRtUser.top += aRtUser.bottom * pPI->RtMinMarginMMs.top / pPI->PtPaperSizeMMs.y; aRtUser.right -= aRtUser.right * pPI->RtMinMarginMMs.right / pPI->PtPaperSizeMMs.x; aRtUser.bottom -= aRtUser.bottom * pPI->RtMinMarginMMs.bottom / pPI->PtPaperSizeMMs.y;
if ((aRtUser.left < aRtUser.right) && (aRtUser.top < aRtUser.bottom) && (aRtUser.left > aRtPage.left) && (aRtUser.top > aRtPage.top) && (aRtUser.right < aRtPage.right) && (aRtUser.bottom < aRtPage.bottom)) { hRgn = CreateRectRgnIndirect(&aRtUser); SelectClipRgn(hDC, hRgn); DeleteObject(hRgn); if ((*lpfnPagePaintHook)( hWnd, WM_PSD_MINMARGINRECT, (WPARAM)hDC, (LPARAM)(LPRECT)&aRtUser )) { goto NoMorePainting; } } }
aRt.left += aRt.right * pPI->RtMarginMMs.left / pPI->PtPaperSizeMMs.x; aRt.top += aRt.bottom * pPI->RtMarginMMs.top / pPI->PtPaperSizeMMs.y; aRt.right -= aRt.right * pPI->RtMarginMMs.right / pPI->PtPaperSizeMMs.x; aRt.bottom -= aRt.bottom * pPI->RtMarginMMs.bottom / pPI->PtPaperSizeMMs.y;
if ( (aRt.left > aRtPage.left) && (aRt.left < aRtPage.right) && (aRt.right < aRtPage.right) && (aRt.right > aRtPage.left) && (aRt.top > aRtPage.top) && (aRt.top < aRtPage.bottom) && (aRt.bottom < aRtPage.bottom) && (aRt.bottom > aRtPage.top) && (aRt.left < aRt.right) && (aRt.top < aRt.bottom) ) { if (pPSD->lpfnPagePaintHook) { LPPAGEPAINTHOOK lpfnPagePaintHook = GETPAGEPAINTHOOKFN(pPSD);
aRtUser = aRt; hRgn = CreateRectRgnIndirect(&aRtUser); SelectClipRgn(hDC, hRgn); DeleteObject(hRgn); if ((*lpfnPagePaintHook)( hWnd, WM_PSD_MARGINRECT, (WPARAM)hDC, (LPARAM)(LPRECT)&aRtUser )) { goto SkipMarginRectangle; } } if (!(pPSD->Flags & PSD_DISABLEPAGEPAINTING)) { Rectangle(hDC, aRt.left, aRt.top, aRt.right, aRt.bottom); }
SkipMarginRectangle:
InflateRect(&aRt, -1, -1); if (pPSD->lpfnPagePaintHook) { LPPAGEPAINTHOOK lpfnPagePaintHook = GETPAGEPAINTHOOKFN(pPSD);
aRtUser = aRt; hRgn = CreateRectRgnIndirect(&aRtUser); SelectClipRgn(hDC, hRgn); DeleteObject(hRgn); if ((*lpfnPagePaintHook)( hWnd, WM_PSD_GREEKTEXTRECT, (WPARAM)hDC, (LPARAM)(LPRECT)&aRtUser )) { goto SkipGreekText; } } if (!(pPSD->Flags & PSD_DISABLEPAGEPAINTING)) { psGreekText = LocalAlloc( LPTR, 10 * (sizeof(szGreekText) + sizeof(TCHAR)) ); for (i = 0; i < 10; i++) { CopyMemory( &(psGreekText[i * (sizeof(szGreekText) / sizeof(TCHAR))]), szGreekText, sizeof(szGreekText) ); } aRt.left++; aRt.right--; aRt.bottom -= (aRt.bottom - aRt.top) % pPI->PtMargins.y; hFontGreek = SelectObject(hDC, hFontGreek); DrawText( hDC, psGreekText, 10 * (sizeof(szGreekText) / sizeof(TCHAR)), &aRt, DT_NOPREFIX | DT_WORDBREAK ); SelectObject(hDC, hFontGreek); LocalFree(psGreekText); } }
SkipGreekText:
InflateRect(&aRtPage, -1, -1); if (pPI->pPD->Flags & PI_WPAPER_ENVELOPE) { int iOrientation;
aRt = aRtPage; if (aRt.right < aRt.bottom) // portrait
// switch (pPI->dwRotation)
{ // default : // no landscape
// case ( ROTATE_LEFT ) : // dot-matrix
// {
// aRt.left = aRt.right - 16;
// aRt.top = aRt.bottom - 32;
// iOrientation = 2;
// break;
// }
// case ( ROTATE_RIGHT ) : // HP PCL
// {
aRt.right = aRt.left + 16; aRt.bottom = aRt.top + 32; iOrientation = 1; // break;
// }
} else // landscape
{ aRt.left = aRt.right - 32; aRt.bottom = aRt.top + 16; iOrientation = 3; } hRgn = CreateRectRgnIndirect(&aRt); SelectClipRgn(hDC, hRgn); DeleteObject(hRgn); if (pPSD->lpfnPagePaintHook) { LPPAGEPAINTHOOK lpfnPagePaintHook = GETPAGEPAINTHOOKFN(pPSD);
aRtUser = aRt; if ((*lpfnPagePaintHook)( hWnd, WM_PSD_ENVSTAMPRECT, (WPARAM)hDC, (LPARAM)(LPRECT)&aRtUser )) { goto SkipEnvelopeStamp; } } if (!(pPSD->Flags & PSD_DISABLEPAGEPAINTING)) { switch (iOrientation) { default : // HP PCL
// case ( 1 ) :
{ DrawIcon(hDC, aRt.left, aRt.top, hIconPSStampP); break; } // case ( 2 ) : // dot-matrix
// {
// DrawIcon(hDC, aRt.left - 16, aRt.top, hIconPSStampP);
// break;
// }
case ( 3 ) : // landscape
{ DrawIcon(hDC, aRt.left, aRt.top, hIconPSStampL); break; } } } }
SkipEnvelopeStamp:;
aRtUser = aRtPage; hRgn = CreateRectRgnIndirect(&aRtUser); SelectClipRgn(hDC, hRgn); DeleteObject(hRgn); if (pPSD->lpfnPagePaintHook) { LPPAGEPAINTHOOK lpfnPagePaintHook = GETPAGEPAINTHOOKFN(pPSD);
if ((*lpfnPagePaintHook)( hWnd, WM_PSD_YAFULLPAGERECT, (WPARAM)hDC, (LPARAM)(LPRECT)&aRtUser )) { goto NoMorePainting; } }
//
// Draw the envelope lines.
//
if ( (!(pPSD->Flags & PSD_DISABLEPAGEPAINTING)) && (pPI->pPD->Flags & PI_WPAPER_ENVELOPE) ) { int iRotation; HGDIOBJ hPenBlack;
aRt = aRtPage; if (aRt.right < aRt.bottom) // portrait
{ // if (pPI->dwRotation == ROTATE_LEFT ) // dot-matrix
// iRotation = 3;
// else // ROTATE_RIGHT // HP PCL
iRotation = 2; } else // landscape
{ iRotation = 1; // normal
}
switch (iRotation) { default : // case ( 1 ) : // normal
{ aRt.right = aRt.left + 32; aRt.bottom = aRt.top + 13; break; } case ( 2 ) : // left
{ aRt.right = aRt.left + 13; aRt.top = aRt.bottom - 32; break; } // case ( 3 ) : // right
// {
// aRt.left = aRt.right - 13;
// aRt.bottom = aRt.top + 32;
// break;
// }
}
InflateRect(&aRt, -3, -3); hPenBlack = SelectObject(hDC, GetStockObject(BLACK_PEN)); switch (iRotation) { case ( 1 ) : // normal
{ MoveToEx(hDC, aRt.left , aRt.top , NULL); LineTo( hDC, aRt.right, aRt.top); MoveToEx(hDC, aRt.left , aRt.top + 3, NULL); LineTo( hDC, aRt.right, aRt.top + 3); MoveToEx(hDC, aRt.left , aRt.top + 6, NULL); LineTo( hDC, aRt.right, aRt.top + 6);
break; } // case ( 2 ) : // left
// case ( 3 ) : // right
default : { MoveToEx( hDC, aRt.left , aRt.top , NULL ); LineTo( hDC, aRt.left , aRt.bottom ); MoveToEx( hDC, aRt.left + 3, aRt.top , NULL ); LineTo( hDC, aRt.left + 3, aRt.bottom ); MoveToEx( hDC, aRt.left + 6, aRt.top , NULL ); LineTo( hDC, aRt.left + 6, aRt.bottom );
break; } } SelectObject(hDC, hPenBlack); }
NoMorePainting:
DeleteObject(SelectObject(hDC, hPen)); SelectObject(hDC, hBr); DeleteObject(SelectObject(hDC, hFont)); TransferPSD2PD(pPI); ReleaseDC(hWnd, hDC);
return (lResult); }
////////////////////////////////////////////////////////////////////////////
//
// PrintLoadResource
//
// This routine loads the resource with the given name and type.
//
////////////////////////////////////////////////////////////////////////////
HANDLE PrintLoadResource( HANDLE hInst, LPTSTR pResName, LPTSTR pType) { HANDLE hResInfo, hRes; LANGID LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
//
// If we are loading a resource from ComDlg32 then use the correct LangID.
//
if (hInst == g_hinst) { LangID = (LANGID) TlsGetValue(g_tlsLangID); }
if (!(hResInfo = FindResourceExFallback(hInst, pType, pResName, LangID))) { StoreExtendedError(CDERR_FINDRESFAILURE); return (NULL); }
if (!(hRes = LoadResource(hInst, hResInfo))) { StoreExtendedError(CDERR_LOADRESFAILURE); return (NULL); }
return (hRes); }
////////////////////////////////////////////////////////////////////////////
//
// PrintGetDefaultPrinterName
//
// This routine gets the name of the default printer and stores it
// in the given buffer.
//
////////////////////////////////////////////////////////////////////////////
VOID PrintGetDefaultPrinterName( LPTSTR pDefaultPrinter, UINT cchSize) { DWORD dwSize; LPTSTR lpsz;
if (pDefaultPrinter[0] != CHAR_NULL) { return; }
//
// First, try to get the default printername from the win.ini file.
//
if (GetProfileString( szTextWindows, szTextDevice, szTextNull, pDefaultPrinter, cchSize )) { lpsz = pDefaultPrinter;
//
// Make sure the string is null-terminated
//
pDefaultPrinter[cchSize - 1] = CHAR_NULL;
while (*lpsz != CHAR_COMMA) { if (!*lpsz++) { pDefaultPrinter[0] = CHAR_NULL; goto GetDefaultFromRegistry; } }
*lpsz = CHAR_NULL; } else { GetDefaultFromRegistry:
//
// Second, try to get it from the registry.
//
dwSize = cchSize * sizeof(TCHAR);
if (RegOpenKeyEx( HKEY_CURRENT_USER, szRegistryPrinter, 0, KEY_READ, &hPrinterKey ) == ERROR_SUCCESS) { RegQueryValueEx( hPrinterKey, szRegistryDefaultValueName, NULL, NULL, (LPBYTE)(pDefaultPrinter), &dwSize );
//
// Make sure the string is null-terminated
//
pDefaultPrinter[cchSize - 1] = CHAR_NULL;
RegCloseKey(hPrinterKey); } } }
////////////////////////////////////////////////////////////////////////////
//
// PrintReturnDefault
//
////////////////////////////////////////////////////////////////////////////
BOOL PrintReturnDefault( PPRINTINFO pPI) { LPPRINTDLG pPD = pPI->pPD; LPDEVNAMES pDN; LPDEVMODE pDM;
StoreExtendedError(CDERR_GENERALCODES);
if (pPD->hDevNames || pPD->hDevMode) { StoreExtendedError(PDERR_RETDEFFAILURE); return (FALSE); }
PrintBuildDevNames(pPI);
if ((pPD->hDevNames) && (pDN = GlobalLock(pPD->hDevNames))) { //
// This is not needed in Win95. An optimization was
// added to DocumentProperties that allows the caller to
// simply pass in the printer name without the printer
// handle.
//
LPTSTR pPrinterName;
pPrinterName = (LPTSTR)pDN + pDN->wDeviceOffset;
if (pPrinterName[0]) { PrintOpenPrinter(pPI, pPrinterName); }
pPD->hDevMode = PrintGetDevMode( 0, pPI->hCurPrinter, pPrinterName, NULL);
if ((pPD->hDevMode) && (pDM = GlobalLock(pPD->hDevMode))) { PrintReturnICDC(pPD, pDN, pDM);
GlobalUnlock(pPD->hDevMode); GlobalUnlock(pPD->hDevNames);
return (TRUE); } GlobalUnlock(pPD->hDevNames); GlobalFree(pPD->hDevNames); pPD->hDevNames = NULL; }
StoreExtendedError(PDERR_NODEFAULTPRN); return (FALSE); }
////////////////////////////////////////////////////////////////////////////
//
// PrintInitGeneral
//
// Initialize (enable/disable) dialog elements general to both PrintDlg
// and SetupDlg.
//
////////////////////////////////////////////////////////////////////////////
BOOL PrintInitGeneral( HWND hDlg, UINT Id, PPRINTINFO pPI) { LPPRINTDLG pPD = pPI->pPD; HWND hCtl;
SetWindowLong( hDlg, GWL_STYLE, GetWindowLong(hDlg, GWL_STYLE) | DS_CONTEXTHELP );
//
// LATER: If we don't enumerate here, there will only be ONE item
// in the list box. As a result, we won't catch the
// keyboard strokes within the list box (eg. arrow keys,
// pgup, pgdown, etc). Need to subclass the combo boxes
// to catch these key strokes so that the printers can be
// enumerated.
//
if (!PrintEnumAndSelect( hDlg, Id, pPI, (pPI->pCurPrinter) ? pPI->pCurPrinter->pPrinterName : NULL, (!(pPI->Status & PI_PRINTERS_ENUMERATED)) )) { goto InitGeneral_ConstructFailure; }
PrintUpdateStatus(hDlg, pPI);
//
// See if the Help button should be hidden.
//
if (!(pPD->Flags & PD_SHOWHELP)) { if (hCtl = GetDlgItem(hDlg, ID_BOTH_P_HELP)) { EnableWindow(hCtl, FALSE); ShowWindow(hCtl, SW_HIDE);
//
// Move the window out of this spot so that no overlap
// will be detected when adding the network button.
//
MoveWindow(hCtl, -8000, -8000, 20, 20, FALSE); } }
return (TRUE);
InitGeneral_ConstructFailure:
if (!GetStoredExtendedError()) { StoreExtendedError(PDERR_INITFAILURE); }
return (FALSE); }
////////////////////////////////////////////////////////////////////////////
//
// PrintInitPrintDlg
//
// Initialize PRINT DLG-specific dialog stuff.
//
// Returns 0xFFFFFFFF if the dialog should be ended.
// Otherwise, returns 1/0 (TRUE/FALSE) depending on focus.
//
////////////////////////////////////////////////////////////////////////////
DWORD PrintInitPrintDlg( HWND hDlg, WPARAM wParam, PPRINTINFO pPI) { LPPRINTDLG pPD = pPI->pPD; WORD wCheckID; HWND hCtl;
//
// Set the number of copies.
//
pPD->nCopies = max(pPD->nCopies, 1); pPD->nCopies = min(pPD->nCopies, MAX_COPIES); SetDlgItemInt(hDlg, ID_PRINT_E_COPIES, pPD->nCopies, FALSE);
if ( !(pPI->pPSD) && (hCtl = GetDlgItem(hDlg, ID_PRINT_E_COPIES)) && (GetWindowLong(hCtl, GWL_STYLE) & WS_VISIBLE) ) { //
// "9999" is the maximum value.
//
Edit_LimitText(hCtl, COPIES_EDIT_SIZE);
CreateUpDownControl( WS_CHILD | WS_BORDER | WS_VISIBLE | UDS_ALIGNRIGHT | UDS_SETBUDDYINT | UDS_NOTHOUSANDS | UDS_ARROWKEYS, 0, 0, 0, 0, hDlg, IDC_COPIES_UDARROW, g_hinst, hCtl, MAX_COPIES, 1, pPD->nCopies );
//
// Adjust the width of the copies edit control using the current
// font and the scroll bar width. This is necessary to handle the
// the up down control from encroching on the space in the edit
// control when we are in High Contrast (extra large) mode.
//
SetCopiesEditWidth(hDlg, hCtl); }
if (!PrintInitBannerAndQuality(hDlg, pPI, pPD)) { if (!GetStoredExtendedError()) { StoreExtendedError(PDERR_INITFAILURE); } return (0xFFFFFFFF); }
if (!(pPD->Flags & PD_SHOWHELP)) { if (hCtl = GetDlgItem(hDlg, ID_BOTH_P_HELP)) { EnableWindow(hCtl, FALSE); ShowWindow(hCtl, SW_HIDE);
//
// Move the window out of this spot so that no overlap
// will be detected when adding the network button.
//
MoveWindow(hCtl, -8000, -8000, 20, 20, FALSE); } }
if (hCtl = GetDlgItem(hDlg, ID_PRINT_X_TOFILE)) { if (pPD->Flags & PD_PRINTTOFILE) { CheckDlgButton(hDlg, ID_PRINT_X_TOFILE, TRUE); }
if (pPD->Flags & PD_HIDEPRINTTOFILE) { EnableWindow(hCtl, FALSE); ShowWindow(hCtl, SW_HIDE); } else if (pPD->Flags & PD_DISABLEPRINTTOFILE) { EnableWindow(hCtl, FALSE); } }
if (pPD->Flags & PD_NOPAGENUMS) { EnableWindow(GetDlgItem(hDlg, ID_PRINT_R_PAGES), FALSE); EnableWindow(GetDlgItem(hDlg, ID_PRINT_S_FROM), FALSE); EnableWindow(GetDlgItem(hDlg, ID_PRINT_E_FROM), FALSE); EnableWindow(GetDlgItem(hDlg, ID_PRINT_S_TO), FALSE); EnableWindow(GetDlgItem(hDlg, ID_PRINT_E_TO), FALSE);
//
// Don't allow disabled button checked.
//
pPD->Flags &= ~((DWORD)PD_PAGENUMS); } else { //
// Some apps (marked 3.1) do not pass in valid ranges.
// (e.g. Corel Ventura)
//
if ((pPI->ProcessVersion < 0x40000) || (!(pPD->Flags & PD_PAGENUMS))) { if (pPD->nFromPage != 0xFFFF) { if (pPD->nFromPage < pPD->nMinPage) { pPD->nFromPage = pPD->nMinPage; } else if (pPD->nFromPage > pPD->nMaxPage) { pPD->nFromPage = pPD->nMaxPage; } } if (pPD->nToPage != 0xFFFF) { if (pPD->nToPage < pPD->nMinPage) { pPD->nToPage = pPD->nMinPage; } else if (pPD->nToPage > pPD->nMaxPage) { pPD->nToPage = pPD->nMaxPage; } } }
if ( pPD->nMinPage > pPD->nMaxPage || ( pPD->nFromPage != 0xFFFF && ( pPD->nFromPage < pPD->nMinPage || pPD->nFromPage > pPD->nMaxPage ) ) || ( pPD->nToPage != 0xFFFF && ( pPD->nToPage < pPD->nMinPage || pPD->nToPage > pPD->nMaxPage ) ) ) { StoreExtendedError(PDERR_INITFAILURE); return (0xFFFFFFFF); }
if (pPD->nFromPage != 0xFFFF) { SetDlgItemInt(hDlg, ID_PRINT_E_FROM, pPD->nFromPage, FALSE); if (pPD->nToPage != 0xFFFF) { SetDlgItemInt(hDlg, ID_PRINT_E_TO, pPD->nToPage, FALSE); } } else { EnableWindow(GetDlgItem(hDlg, ID_PRINT_S_TO), FALSE); EnableWindow(GetDlgItem(hDlg, ID_PRINT_E_TO), FALSE); }
if (pPD->nMinPage == pPD->nMaxPage) { EnableWindow(GetDlgItem(hDlg, ID_PRINT_R_PAGES), FALSE); EnableWindow(GetDlgItem(hDlg, ID_PRINT_S_FROM), FALSE); EnableWindow(GetDlgItem(hDlg, ID_PRINT_E_FROM), FALSE); EnableWindow(GetDlgItem(hDlg, ID_PRINT_S_TO), FALSE); EnableWindow(GetDlgItem(hDlg, ID_PRINT_E_TO), FALSE);
//
// Don't allow disabled button checked.
//
pPD->Flags &= ~((DWORD)(PD_PAGENUMS | PD_COLLATE)); pPI->Status &= ~PI_COLLATE_REQUESTED; EnableWindow(GetDlgItem(hDlg, ID_PRINT_X_COLLATE), FALSE); ShowWindow(GetDlgItem(hDlg, ID_PRINT_X_COLLATE), SW_HIDE); } }
if (pPD->Flags & PD_NOSELECTION) { HWND hRad = GetDlgItem(hDlg, ID_PRINT_R_SELECTION);
if (hRad) { EnableWindow(hRad, FALSE); }
//
// Don't allow disabled button checked.
//
pPD->Flags &= ~((DWORD)PD_SELECTION); }
if (pPD->Flags & PD_PAGENUMS) { wCheckID = ID_PRINT_R_PAGES; } else if (pPD->Flags & PD_SELECTION) { wCheckID = ID_PRINT_R_SELECTION; } else { // PD_ALL
wCheckID = ID_PRINT_R_ALL; }
CheckRadioButton(hDlg, ID_PRINT_R_ALL, ID_PRINT_R_PAGES, (int)wCheckID);
//
// Subclass the integer only edit controls.
//
if (!(pPI->pPSD)) { if (hCtl = GetDlgItem(hDlg, ID_PRINT_E_FROM)) { //
// "99999" is the maximum value.
//
Edit_LimitText(hCtl, PAGE_EDIT_SIZE); } if (hCtl = GetDlgItem(hDlg, ID_PRINT_E_TO)) { //
// "99999" is the maximum value.
//
Edit_LimitText(hCtl, PAGE_EDIT_SIZE); } }
if (pPD->lpfnPrintHook) { LPPRINTHOOKPROC lpfnPrintHook = GETPRINTHOOKFN(pPD);
if (pPI->ApiType == COMDLG_ANSI) { DWORD dwHookRet;
ThunkPrintDlgW2A(pPI); dwHookRet = (*lpfnPrintHook)( hDlg, WM_INITDIALOG, wParam, (LONG_PTR)pPI->pPDA ) != 0; if (dwHookRet) { ThunkPrintDlgA2W(pPI); }
return (dwHookRet); } else { return ( (*lpfnPrintHook)( hDlg, WM_INITDIALOG, wParam, (LONG_PTR)pPD ) ) != 0; } }
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// PrintInitSetupDlg
//
// Initialize SETUP-specific dialog stuff.
//
// Returns 0xFFFFFFFF if the dialog should be ended.
// Otherwise, returns 1/0 (TRUE/FALSE) depending on focus.
//
////////////////////////////////////////////////////////////////////////////
DWORD PrintInitSetupDlg( HWND hDlg, WPARAM wParam, PPRINTINFO pPI) { LPPRINTDLG pPD = pPI->pPD; LPDEVMODE pDM = NULL; HWND hCtl; LPPAGESETUPDLG pPSD = pPI->pPSD; UINT Orientation;
if (!pPD->hDevMode || !(pDM = GlobalLock(pPD->hDevMode))) { StoreExtendedError(CDERR_MEMLOCKFAILURE); goto InitSetupDlg_ConstructFailure; }
if (hCtl = GetDlgItem(hDlg, ID_SETUP_C_SIZE)) { PrintInitPaperCombo( pPI, hCtl, GetDlgItem(hDlg, ID_SETUP_S_SIZE), pPI->pCurPrinter, pDM, DC_PAPERNAMES, CCHPAPERNAME, DC_PAPERS ); }
//
// Provide backward compatibility for old-style-template sources
// ID_SETUP_C_SOURCE.
//
if (hCtl = GetDlgItem(hDlg, ID_SETUP_C_SOURCE)) { PrintInitPaperCombo( pPI, hCtl, GetDlgItem(hDlg, ID_SETUP_S_SOURCE), pPI->pCurPrinter, pDM, DC_BINNAMES, CCHBINNAME, DC_BINS ); }
//
// Set the edit field lengths and other setup stuff for margins.
// This must be called before PrintSetMargin, which is called in
// PrintSetOrientation.
//
PrintSetupMargins(hDlg, pPI);
PrintInitOrientation(hDlg, pPI, pDM); Orientation = pDM->dmOrientation + ID_SETUP_R_PORTRAIT - DMORIENT_PORTRAIT; PrintSetOrientation( hDlg, pPI, pDM, Orientation, Orientation );
PrintInitDuplex(hDlg, pDM); PrintSetDuplex( hDlg, pDM, pDM->dmDuplex + ID_SETUP_R_NONE - DMDUP_SIMPLEX );
GlobalUnlock(pPD->hDevMode);
if (pPSD) { if (pPSD->Flags & PSD_DISABLEORIENTATION) { EnableWindow(GetDlgItem(hDlg, ID_SETUP_R_PORTRAIT), FALSE ); EnableWindow(GetDlgItem(hDlg, ID_SETUP_R_LANDSCAPE), FALSE ); } if (pPSD->Flags & PSD_DISABLEPAPER) { EnableWindow(GetDlgItem(hDlg, ID_SETUP_S_SIZE), FALSE ); EnableWindow(GetDlgItem(hDlg, ID_SETUP_C_SIZE), FALSE ); EnableWindow(GetDlgItem(hDlg, ID_SETUP_S_SOURCE), FALSE ); EnableWindow(GetDlgItem(hDlg, ID_SETUP_C_SOURCE), FALSE ); } if (pPSD->Flags & PSD_DISABLEMARGINS) { EnableWindow(GetDlgItem(hDlg, ID_SETUP_S_LEFT), FALSE ); EnableWindow(GetDlgItem(hDlg, ID_SETUP_E_LEFT), FALSE ); EnableWindow(GetDlgItem(hDlg, ID_SETUP_S_RIGHT), FALSE ); EnableWindow(GetDlgItem(hDlg, ID_SETUP_E_RIGHT), FALSE ); EnableWindow(GetDlgItem(hDlg, ID_SETUP_S_TOP), FALSE ); EnableWindow(GetDlgItem(hDlg, ID_SETUP_E_TOP), FALSE ); EnableWindow(GetDlgItem(hDlg, ID_SETUP_S_BOTTOM), FALSE ); EnableWindow(GetDlgItem(hDlg, ID_SETUP_E_BOTTOM), FALSE ); } if (pPSD->Flags & PSD_DISABLEPRINTER) { EnableWindow(GetDlgItem(hDlg, ID_SETUP_P_PRINTER), FALSE ); } }
if (hCtl = GetDlgItem(hDlg, ID_SETUP_W_SAMPLE)) { lpStaticProc = (WNDPROC)SetWindowLongPtr( hCtl, GWLP_WNDPROC, (LONG_PTR)PrintPageSetupPaintProc ); }
if ((pPD->Flags & PD_NONETWORKBUTTON)) { if (hCtl = GetDlgItem(hDlg, ID_BOTH_P_NETWORK)) { EnableWindow(hCtl, FALSE); ShowWindow(hCtl, SW_HIDE); } } else if (!(pPI->pPSD)) { AddNetButton( hDlg, ((pPD->Flags & PD_ENABLESETUPTEMPLATE) ? pPD->hInstance : g_hinst), FILE_BOTTOM_MARGIN, (pPD->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLESETUPTEMPLATEHANDLE)) ? FALSE : TRUE, FALSE, TRUE );
//
// The button can be added in two ways -
// statically (they have it predefined in their template) and
// dynamically (successful call to AddNetButton).
//
if (!IsNetworkInstalled()) { hCtl = GetDlgItem(hDlg, ID_BOTH_P_NETWORK);
EnableWindow(hCtl, FALSE); ShowWindow(hCtl, SW_HIDE); } }
if (!(pPD->Flags & PD_SHOWHELP)) { if (hCtl = GetDlgItem(hDlg, ID_BOTH_P_HELP)) { EnableWindow(hCtl, FALSE); ShowWindow(hCtl, SW_HIDE);
//
// Move the window out of this spot so that no overlap
// will be detected when adding the network button.
//
MoveWindow(hCtl, -8000, -8000, 20, 20, FALSE); } }
//
// Provide backward compatibility for old-style-template radio buttons.
//
if (hCtl = GetDlgItem(hDlg, ID_SETUP_R_DEFAULT)) { TCHAR szBuf[MAX_DEV_SECT]; TCHAR szDefFormat[MAX_DEV_SECT];
if (pPI->szDefaultPrinter[0]) { if (!CDLoadString( g_hinst, iszDefCurOn, szDefFormat, ARRAYSIZE(szDefFormat) )) { StoreExtendedError(CDERR_LOADSTRFAILURE); goto InitSetupDlg_ConstructFailure; }
wnsprintf(szBuf, ARRAYSIZE(szBuf), szDefFormat, pPI->szDefaultPrinter); } else { szBuf[0] = CHAR_NULL; EnableWindow(hCtl, FALSE); } SetDlgItemText(hDlg, ID_SETUP_S_DEFAULT, szBuf);
if ( pPI->pCurPrinter && pPI->pCurPrinter->pPrinterName && !lstrcmp(pPI->pCurPrinter->pPrinterName, pPI->szDefaultPrinter) ) { CheckRadioButton( hDlg, ID_SETUP_R_DEFAULT, ID_SETUP_R_SPECIFIC, ID_SETUP_R_DEFAULT ); } else { CheckRadioButton( hDlg, ID_SETUP_R_DEFAULT, ID_SETUP_R_SPECIFIC, ID_SETUP_R_SPECIFIC ); } }
if (pPD->lpfnSetupHook) { DWORD dwHookRet; LPSETUPHOOKPROC lpfnSetupHook = GETSETUPHOOKFN(pPD);
if (pPI->ApiType == COMDLG_ANSI) { ThunkPrintDlgW2A(pPI); TransferPDA2PSD(pPI);
pPI->NestCtr++; dwHookRet = (*lpfnSetupHook)( hDlg, WM_INITDIALOG, wParam, (pPI->pPSD) ? (LONG_PTR)pPI->pPSD : (LONG_PTR)pPI->pPDA ) != 0; pPI->NestCtr--;
if (dwHookRet) { TransferPSD2PDA(pPI); ThunkPrintDlgA2W(pPI); if (pPI->NestCtr == 0) { TransferPD2PSD(pPI); } } } else { TransferPD2PSD(pPI); dwHookRet = (*lpfnSetupHook)( hDlg, WM_INITDIALOG, wParam, (pPI->pPSD) ? (LONG_PTR)pPI->pPSD : (LONG_PTR)pPD ) != 0; TransferPSD2PD(pPI); }
return (dwHookRet); }
return (TRUE);
InitSetupDlg_ConstructFailure:
if (!GetStoredExtendedError()) { StoreExtendedError(PDERR_INITFAILURE); }
return (0xFFFFFFFF); }
////////////////////////////////////////////////////////////////////////////
//
// PrintUpdateSetupDlg
//
// Update the print setup and page setup dialogs with the new settings.
//
////////////////////////////////////////////////////////////////////////////
VOID PrintUpdateSetupDlg( HWND hDlg, PPRINTINFO pPI, LPDEVMODE pDM, BOOL fResetContent) { HWND hCtl; UINT Count; UINT Orientation = 0;
//
// Update the Size combo box.
//
if (hCtl = GetDlgItem(hDlg, ID_SETUP_C_SIZE)) { if (fResetContent) { PrintInitPaperCombo( pPI, hCtl, GetDlgItem(hDlg, ID_SETUP_S_SIZE), pPI->pCurPrinter, pDM, DC_PAPERNAMES, CCHPAPERNAME, DC_PAPERS ); //
// PrintInitPaperCombo will turn off the hour glass cursor, so
// turn it back on.
//
HourGlass(TRUE); } else { Count = (UINT) SendMessage(hCtl, CB_GETCOUNT, 0, 0); while (Count != 0) { Count--; if (pDM->dmPaperSize == (SHORT)SendMessage( hCtl, CB_GETITEMDATA, Count, 0 ) ) { break; } }
SendMessage( hCtl, CB_SETCURSEL, Count, 0 ); } }
//
// Update the Source combo box.
//
if (hCtl = GetDlgItem(hDlg, ID_SETUP_C_SOURCE)) { if (fResetContent) { PrintInitPaperCombo( pPI, hCtl, GetDlgItem(hDlg, ID_SETUP_S_SOURCE), pPI->pCurPrinter, pDM, DC_BINNAMES, CCHBINNAME, DC_BINS ); //
// PrintInitPaperCombo will turn off the hour glass cursor, so
// turn it back on.
//
HourGlass(TRUE); } else { Count = (UINT) SendMessage(hCtl, CB_GETCOUNT, 0, 0); while (Count != 0) { Count--; if (pDM->dmDefaultSource == (SHORT)SendMessage( hCtl, CB_GETITEMDATA, Count, 0 ) ) { break; } }
SendMessage( hCtl, CB_SETCURSEL, Count, 0 ); } }
//
// Update the Orientation radio buttons.
//
if (GetDlgItem(hDlg, ID_SETUP_R_PORTRAIT)) { Orientation = pDM->dmOrientation + ID_SETUP_R_PORTRAIT - DMORIENT_PORTRAIT; PrintSetOrientation( hDlg, pPI, pDM, IsDlgButtonChecked(hDlg, ID_SETUP_R_PORTRAIT) ? ID_SETUP_R_PORTRAIT : ID_SETUP_R_LANDSCAPE, Orientation ); }
//
// Update the Duplex radio buttons.
//
if (GetDlgItem(hDlg, ID_SETUP_R_NONE)) { PrintSetDuplex( hDlg, pDM, pDM->dmDuplex + ID_SETUP_R_NONE - DMDUP_SIMPLEX ); }
//
// Update the page setup sample picture.
//
if ((Orientation == 0) && (hCtl = GetDlgItem(hDlg, ID_SETUP_W_SAMPLE))) { Orientation = pDM->dmOrientation + ID_SETUP_R_PORTRAIT - DMORIENT_PORTRAIT; PrintUpdatePageSetup( hDlg, pPI, pDM, 0, Orientation ); }
//
// Update the Default/Specific Printer radio buttons.
//
if (hCtl = GetDlgItem(hDlg, ID_SETUP_R_DEFAULT)) { if ( pPI->pCurPrinter && pPI->pCurPrinter->pPrinterName && !lstrcmp(pPI->pCurPrinter->pPrinterName, pPI->szDefaultPrinter) ) { CheckRadioButton( hDlg, ID_SETUP_R_DEFAULT, ID_SETUP_R_SPECIFIC, ID_SETUP_R_DEFAULT ); } else { CheckRadioButton( hDlg, ID_SETUP_R_DEFAULT, ID_SETUP_R_SPECIFIC, ID_SETUP_R_SPECIFIC ); } } }
////////////////////////////////////////////////////////////////////////////
//
// PrintSetCopies
//
// Sets the appropriate number of copies in the PrintDlg structure and
// in the DevMode structure.
//
////////////////////////////////////////////////////////////////////////////
BOOL PrintSetCopies( HWND hDlg, PPRINTINFO pPI, UINT Id) { LPPRINTDLG pPD = pPI->pPD; LPDEVMODE pDM; DWORD dwMaxCopies; DWORD dwCollate; BOOL bAllowCollate;
if ( (pPD->hDevMode) && (pDM = GlobalLock(pPD->hDevMode)) ) { //
// If we're coming from a WOW app, we need to only set
// the copies in the devmode if the PD_USEDEVMODECOPIES
// flag is set.
//
if (IS16BITWOWAPP(pPD)) { if (pPD->Flags & PD_USEDEVMODECOPIES) { pDM->dmCopies = pPD->nCopies; pPD->nCopies = 1; } else { pDM->dmCopies = 1; }
return (TRUE); }
if ( (!(pDM->dmFields & DM_COPIES)) || ((!(pPI->pPSD)) && (pPI->ProcessVersion < 0x40000) && (!(pPD->Flags & PD_USEDEVMODECOPIES))) ) { LeaveInfoInPD: //
// The driver cannot do copies, so leave the
// copy/collate info in the pPD.
//
pDM->dmCopies = 1; SetField(pDM, dmCollate, DMCOLLATE_FALSE); } else if ( (pDM->dmSpecVersion < 0x0400) || (!(pDM->dmFields & DM_COLLATE)) ) { //
// The driver can do copies, but not collate.
// Where the info goes depends on the PD_COLLATE flag.
//
if (pPD->Flags & PD_COLLATE) { goto LeaveInfoInPD; } else { goto PutInfoInDevMode; } } else { PutInfoInDevMode: //
// Make sure we have a current printer.
//
if (!pPI->pCurPrinter) { goto LeaveInfoInPD; }
//
// Make sure the driver can support the number
// of copies requested and collation.
//
dwMaxCopies = DeviceCapabilities( pPI->pCurPrinter->pPrinterName, pPI->pCurPrinter->pPortName, DC_COPIES, NULL, NULL );
//
// If DeviceCapabilities() returns error, set the copy number to 1
//
if ((dwMaxCopies < 1) || (dwMaxCopies == (DWORD)(-1))) { dwMaxCopies = 1; } if (dwMaxCopies < pPD->nCopies) { if (pPD->Flags & PD_USEDEVMODECOPIES) { PrintEditError( hDlg, (Id == ID_PRINT_C_NAME) ? ID_PRINT_E_COPIES : ID_BOTH_P_PROPERTIES, iszTooManyCopies, dwMaxCopies );
GlobalUnlock(pPD->hDevMode); return (FALSE); }
goto LeaveInfoInPD; }
dwCollate = DeviceCapabilities( pPI->pCurPrinter->pPrinterName, pPI->pCurPrinter->pPortName, DC_COLLATE, NULL, NULL );
bAllowCollate = ((dwCollate < 1) || (dwCollate == (DWORD)-1)) ? FALSE : TRUE;
//
// The driver can do both copies and collate,
// so move the info to the devmode.
//
pDM->dmCopies = pPD->nCopies; SetField( pDM, dmCollate, (bAllowCollate && (pPD->Flags & PD_COLLATE)) ? DMCOLLATE_TRUE : DMCOLLATE_FALSE ); pPD->nCopies = 1; pPD->Flags &= ~PD_COLLATE; }
GlobalUnlock(pPD->hDevMode); }
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// PrintSetMinMargins
//
////////////////////////////////////////////////////////////////////////////
VOID PrintSetMinMargins( HWND hDlg, PPRINTINFO pPI, LPDEVMODE pDM) { LPPAGESETUPDLG pPSD = pPI->pPSD; HDC hDC; RECT rtMinMargin;
if (!pPSD) { return; }
if (pPSD->Flags & PSD_MINMARGINS) { //
// Convert passed in margins to 10th of MMs.
//
if (pPSD->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) { pPI->RtMinMarginMMs.left = pPSD->rtMinMargin.left / 10; pPI->RtMinMarginMMs.top = pPSD->rtMinMargin.top / 10; pPI->RtMinMarginMMs.right = pPSD->rtMinMargin.right / 10; pPI->RtMinMarginMMs.bottom = pPSD->rtMinMargin.bottom / 10; } else // PSD_INTHOUSANDTHSOFINCHES
{ pPI->RtMinMarginMMs.left = pPSD->rtMinMargin.left * MMS_PER_INCH / 100; pPI->RtMinMarginMMs.top = pPSD->rtMinMargin.top * MMS_PER_INCH / 100; pPI->RtMinMarginMMs.right = pPSD->rtMinMargin.right * MMS_PER_INCH / 100; pPI->RtMinMarginMMs.bottom = pPSD->rtMinMargin.bottom * MMS_PER_INCH / 100; } } else { //
// Default to no minimum if we can't get the info.
//
pPI->RtMinMarginMMs.left = 0; pPI->RtMinMarginMMs.top = 0; pPI->RtMinMarginMMs.right = 0; pPI->RtMinMarginMMs.bottom = 0; pPSD->rtMinMargin.left = 0; pPSD->rtMinMargin.top = 0; pPSD->rtMinMargin.right = 0; pPSD->rtMinMargin.bottom = 0;
//
// Calculate new min margins from driver.
//
if (hDC = CreateIC(NULL, pDM->dmDeviceName, NULL, pDM)) { //
// These are in PIXELS.
//
int nPageWidth = GetDeviceCaps(hDC, PHYSICALWIDTH); int nPageHeight = GetDeviceCaps(hDC, PHYSICALHEIGHT); int nPrintWidth = GetDeviceCaps(hDC, HORZRES); int nPrintHeight = GetDeviceCaps(hDC, VERTRES); int nOffsetWidth = GetDeviceCaps(hDC, PHYSICALOFFSETX); int nOffsetHeight = GetDeviceCaps(hDC, PHYSICALOFFSETY); int nPerInchWidth = GetDeviceCaps(hDC, LOGPIXELSX); int nPerInchHeight = GetDeviceCaps(hDC, LOGPIXELSY);
//
// Calculate min margins in PIXELS.
//
rtMinMargin.left = nOffsetWidth; rtMinMargin.top = nOffsetHeight; rtMinMargin.right = nPageWidth - nPrintWidth - nOffsetWidth; rtMinMargin.bottom = nPageHeight - nPrintHeight - nOffsetHeight;
//
// Convert to 10ths of MMs.
//
if (nPerInchWidth && nPerInchHeight) { pPI->RtMinMarginMMs.left = rtMinMargin.left * MMS_PER_INCH / nPerInchWidth / 10; pPI->RtMinMarginMMs.top = rtMinMargin.top * MMS_PER_INCH / nPerInchHeight / 10; pPI->RtMinMarginMMs.right = rtMinMargin.right * MMS_PER_INCH / nPerInchHeight / 10; pPI->RtMinMarginMMs.bottom = rtMinMargin.bottom * MMS_PER_INCH / nPerInchHeight / 10; }
if (pPSD->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) { //
// Convert to 100ths of MMs.
//
pPSD->rtMinMargin.left = pPI->RtMinMarginMMs.left / 10; pPSD->rtMinMargin.top = pPI->RtMinMarginMMs.top / 10; pPSD->rtMinMargin.right = pPI->RtMinMarginMMs.right / 10; pPSD->rtMinMargin.bottom = pPI->RtMinMarginMMs.bottom / 10; } else // PSD_INTHOUSANDTHSOFINCHES
{ //
// Convert to 1000ths of inches.
//
if (nPerInchWidth && nPerInchHeight) { pPSD->rtMinMargin.left = rtMinMargin.left * 1000 / nPerInchWidth; pPSD->rtMinMargin.top = rtMinMargin.top * 1000 / nPerInchHeight; pPSD->rtMinMargin.right = rtMinMargin.right * 1000 / nPerInchHeight; pPSD->rtMinMargin.bottom = rtMinMargin.bottom * 1000 / nPerInchHeight; } }
DeleteDC(hDC); } } }
////////////////////////////////////////////////////////////////////////////
//
// PrintSetupMargins
//
////////////////////////////////////////////////////////////////////////////
VOID PrintSetupMargins( HWND hDlg, PPRINTINFO pPI) { TCHAR szMars[32]; TCHAR szText[16]; int ids[4] = { ID_SETUP_E_LEFT, ID_SETUP_E_TOP, ID_SETUP_E_RIGHT, ID_SETUP_E_BOTTOM }; int i; HWND hEdt;
//
// Margins are only available from the PageSetupDlg.
//
if (!(pPI->pPSD)) { return; }
for (i = 0; i < 4; i++) { if (hEdt = GetDlgItem(hDlg, ids[i])) { //
// "999999" is the maximum value.
//
SendMessage(hEdt, EM_LIMITTEXT, MARGIN_EDIT_SIZE, 0);
lpEditMarginProc = (WNDPROC)SetWindowLongPtr( hEdt, GWLP_WNDPROC, (LONG_PTR)PrintEditMarginProc );
} }
if (!GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, szText, 16 )) { cIntlDecimal = CHAR_DOT; } else { cIntlDecimal = szText[0]; }
switch (pPI->pPSD->Flags & (PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS)) { case ( PSD_INHUNDREDTHSOFMILLIMETERS ) : { CDLoadString(g_hinst, iszMarginsMillimeters, szMars, ARRAYSIZE(szMars)); CDLoadString(g_hinst, iszMillimeters, cIntlMeasure, ARRAYSIZE(cIntlMeasure));
break; } case ( PSD_INTHOUSANDTHSOFINCHES ) : { CDLoadString(g_hinst, iszMarginsInches, szMars, ARRAYSIZE(szMars)); CDLoadString(g_hinst, iszInches, cIntlMeasure, ARRAYSIZE(cIntlMeasure));
break; } }
cchIntlMeasure = lstrlen(cIntlMeasure);
SetWindowText(GetDlgItem(hDlg, ID_SETUP_G_MARGINS), szMars); pPI->PtMargins.x = 2 * (IS_KEY_PRESSED(pPI->PtMargins.x / 4) && IS_KEY_PRESSED(pPI->PtMargins.y / 4) ? sizeof(WCHAR) : sizeof(CHAR)); pPI->PtMargins.y = 2 * pPI->PtMargins.x; }
////////////////////////////////////////////////////////////////////////////
//
// PrintSetMargin
//
////////////////////////////////////////////////////////////////////////////
VOID PrintSetMargin( HWND hDlg, PPRINTINFO pPI, UINT Id, LONG lValue) { HWND hEdt; TCHAR szText[32]; TCHAR szILZero[2]; LONG lFract;
if (hEdt = GetDlgItem(hDlg, Id)) { switch (pPI->pPSD->Flags & (PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS)) { case ( PSD_INHUNDREDTHSOFMILLIMETERS ) : { lFract = lValue % 100; StringCchPrintf( szText, ARRAYSIZE(szText), lFract ? TEXT("%lu%c%02lu") : TEXT("%lu"), lValue / 100, cIntlDecimal, lFract ); break; } case ( PSD_INTHOUSANDTHSOFINCHES ) : { lFract = lValue % 1000; StringCchPrintf( szText, ARRAYSIZE(szText), lFract ? TEXT("%lu%c%03lu") : TEXT("%lu"), lValue / 1000, cIntlDecimal, lFract ); break; } }
//
// Remove trailing zeros off of fraction.
//
if (lFract) { LPTSTR pStr = szText + lstrlen(szText) - 1;
while (*pStr == TEXT('0')) { *pStr-- = TEXT('\0'); } }
//
// Determine if a leading zero is to be used and write the
// text to the edit window.
//
if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILZERO, szILZero, 2)) { szILZero[0] = TEXT('0'); } SetWindowText( hEdt, szText + (szText[0] == TEXT('0') && szText[1] == cIntlDecimal && szILZero[0] == TEXT('0')) ); } }
////////////////////////////////////////////////////////////////////////////
//
// PrintGetMargin
//
////////////////////////////////////////////////////////////////////////////
VOID PrintGetMargin( HWND hEdt, PPRINTINFO pPI, LONG lMin, LONG *plMargin, LONG *plSample) { //
// The buffer will concatinate "000" at the end, so the buffer
// size should be equal or bigger than MARGIN_EDIT_SIZE + 3 +1.
//
TCHAR szText[MARGIN_EDIT_SIZE + 3 +1] = {0}; TCHAR *pText; TCHAR *pFrac;
//
// Set the buffer size to ARRAYSIZE(szText) - 3 since we need to
// reserve 3 chars for concatination of "000" later. If
// GetWindowText fails, we don't mind since the buffer was
// filled with 0 at first. The function will finally set *plMargin
// and *plSample as 0 and return.
//
GetWindowText(hEdt, szText, ARRAYSIZE(szText) - 3); *plMargin = ConvertStringToInteger(szText);
for (pText = szText; *pText;) { if (*pText++ == cIntlDecimal) { break; } }
for (pFrac = pText; *pFrac; pFrac++) { if (*pFrac == cIntlMeasure[0]) { *pFrac = CHAR_NULL; break; }
if (*pFrac == cIntlDecimal) { *pFrac = CHAR_NULL; break; } }
//
// Don't check the return from StringCchCat, since
// we will recalculate *plMargin and *plSample anyway
//
StringCchCat(szText, ARRAYSIZE(szText), TEXT("000"));
switch (pPI->pPSD->Flags & (PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS)) { case ( PSD_INTHOUSANDTHSOFINCHES ) : { //
// In 1000ths of inches.
//
*plMargin *= 1000; pText[3] = CHAR_NULL; *plMargin += ConvertStringToInteger(pText); *plMargin = max(lMin, *plMargin);
//
// In 10ths of MMs.
//
*plSample = *plMargin * MMS_PER_INCH / 1000;
break; } case ( PSD_INHUNDREDTHSOFMILLIMETERS ) : { //
// In 100ths of MMs.
//
*plMargin *= 100 ; pText[2] = CHAR_NULL; *plMargin += ConvertStringToInteger(pText); *plMargin = max(lMin, *plMargin);
//
// In 10ths of MMs.
//
*plSample = *plMargin / 10;
break; } } }
////////////////////////////////////////////////////////////////////////////
//
// PrintInitBannerAndQuality
//
// Reset PRINT DLG items dependent upon which printer was selected.
// Assumes that pPD->hDevNames is non-NULL. pPD->hDevMode non-NULL.
//
////////////////////////////////////////////////////////////////////////////
BOOL PrintInitBannerAndQuality( HWND hDlg, PPRINTINFO pPI, LPPRINTDLG pPD) { HWND hCtl; BOOL bResult = TRUE; LPDEVMODE pDM = NULL; LPDEVNAMES pDN = NULL; TCHAR szText[MAX_DEV_SECT];
//
// ID_PRINT_S_DEFAULT is from one of the old templates.
//
if (GetDlgItem(hDlg, ID_PRINT_S_DEFAULT)) { if (!pPD->hDevNames || !(pDN = GlobalLock(pPD->hDevNames))) { StoreExtendedError(CDERR_MEMLOCKFAILURE); return (FALSE); }
if (PrintCreateBanner(hDlg, pDN, szText, MAX_DEV_SECT)) { SetDlgItemText(hDlg, ID_PRINT_S_DEFAULT, szText); } else { //
// PrintCreateBanner sets the extended error.
//
bResult = FALSE; }
GlobalUnlock(pPD->hDevNames); }
//
// If the driver says it can do copies, pay attention to what the
// app requested. If it cannot do copies, check & disable the
// checkbox.
//
if (pPD->hDevMode) { if (!(pDM = GlobalLock(pPD->hDevMode))) { StoreExtendedError(CDERR_MEMLOCKFAILURE); return (FALSE); }
//
// Enable print quality, if it exists.
//
if (hCtl = GetDlgItem(hDlg, ID_PRINT_S_QUALITY)) { EnableWindow(hCtl, TRUE); } if (hCtl = GetDlgItem(hDlg, ID_PRINT_C_QUALITY)) { EnableWindow(hCtl, TRUE);
PrintInitQuality( hCtl, pDM->dmSpecVersion <= 0x0300 ? 0L : pPD, pDM->dmPrintQuality ); }
//
// If PD_USEDEVMODECOPIES(COLLATE), disable collate if the driver
// cannot collate.
//
if (hCtl = GetDlgItem(hDlg, ID_PRINT_X_COLLATE)) { if ( pDM->dmFields & DM_COLLATE || !(pPD->Flags & PD_USEDEVMODECOPIES) ) { EnableWindow(hCtl, TRUE); CheckDlgButton( hDlg, ID_PRINT_X_COLLATE, (pPI->Status & PI_COLLATE_REQUESTED) ? TRUE : FALSE ); } else { EnableWindow(hCtl, FALSE); CheckDlgButton(hDlg, ID_PRINT_X_COLLATE, FALSE); } }
//
// If PD_USEDEVMODECOPIES(COLLATE), disable copies if the driver
// cannot copy.
//
if (hCtl = GetDlgItem(hDlg, ID_PRINT_E_COPIES)) { if ( pDM->dmFields & DM_COPIES || !(pPD->Flags & PD_USEDEVMODECOPIES) ) { SetDlgItemInt(hDlg, ID_PRINT_E_COPIES, pPD->nCopies, FALSE); EnableWindow(hCtl, TRUE); } else { SetDlgItemInt(hDlg, ID_PRINT_E_COPIES, 1, FALSE); EnableWindow(hCtl, FALSE); } }
//
// Display the appropriate collate icon.
//
if (hCtl = GetDlgItem(hDlg, ID_PRINT_I_COLLATE)) { SetWindowLong( hCtl, GWL_STYLE, GetWindowLong(hCtl, GWL_STYLE) | SS_CENTERIMAGE ); ShowWindow(hCtl, SW_HIDE); SendMessage( hCtl, STM_SETICON, IsDlgButtonChecked(hDlg, ID_PRINT_X_COLLATE) ? (LONG_PTR)hIconCollate : (LONG_PTR)hIconNoCollate, 0L ); ShowWindow(hCtl, SW_SHOW); }
GlobalUnlock(pPD->hDevMode); } else { //
// Disable the print quality, collate, and copies.
//
if (hCtl = GetDlgItem(hDlg, ID_PRINT_S_QUALITY)) { EnableWindow(hCtl, FALSE); } if (hCtl = GetDlgItem(hDlg, ID_PRINT_C_QUALITY)) { EnableWindow(hCtl, FALSE); } if (hCtl = GetDlgItem(hDlg, ID_PRINT_X_COLLATE)) { EnableWindow(hCtl, FALSE); } if (hCtl = GetDlgItem(hDlg, ID_PRINT_E_COPIES)) { EnableWindow(hCtl, FALSE); } }
return (bResult); }
////////////////////////////////////////////////////////////////////////////
//
// PrintCreateBanner
//
// Create "Printer: Prn on Port" or "Printer: System Printer (Prn)".
//
////////////////////////////////////////////////////////////////////////////
BOOL PrintCreateBanner( HWND hDlg, LPDEVNAMES pDN, LPTSTR psBanner, UINT cchBanner) { if (GetDlgItem(hDlg, ID_BOTH_S_PRINTER)) { psBanner[0] = CHAR_NULL; } else if (!CDLoadString( g_hinst, iszPrinter, psBanner, cchBanner )) { goto LoadStrFailure; }
if (pDN->wDefault & DN_DEFAULTPRN) { TCHAR szSysPrn[MAX_DEV_SECT];
if (!CDLoadString(g_hinst, iszSysPrn, szSysPrn, ARRAYSIZE(szSysPrn))) { goto LoadStrFailure; } StringCchCat(psBanner, cchBanner, (LPTSTR)szSysPrn); StringCchCat(psBanner, cchBanner, (LPTSTR)pDN + pDN->wDeviceOffset); StringCchCat(psBanner, cchBanner, (LPTSTR)TEXT(")")); } else { TCHAR szPrnOnPort[64];
if (!CDLoadString(g_hinst, iszPrnOnPort, szPrnOnPort, ARRAYSIZE(szPrnOnPort))) { goto LoadStrFailure; } StringCchCat(psBanner, cchBanner, (LPTSTR)pDN + pDN->wDeviceOffset); StringCchCat(psBanner, cchBanner, (LPTSTR)szPrnOnPort); StringCchCat(psBanner, cchBanner, (LPTSTR)pDN + pDN->wOutputOffset); }
return (TRUE);
LoadStrFailure:
StoreExtendedError(CDERR_LOADSTRFAILURE); return (FALSE); }
////////////////////////////////////////////////////////////////////////////
//
// PrintInitQuality
//
// Initializes the Printer Quality Combobox.
//
// Assumes pPD structure filled by caller. If non-NULL, it's a 3.1 or
// later driver. If NULL, fill with default for 3.0.
//
////////////////////////////////////////////////////////////////////////////
VOID PrintInitQuality( HANDLE hCmb, LPPRINTDLG pPD, SHORT nQuality) { SHORT nStringID; SHORT i; TCHAR szBuf[64]; LPDEVMODE pDM = NULL; LPDEVNAMES pDN = NULL;
SendMessage(hCmb, CB_RESETCONTENT, 0, 0L);
//
// Enum print qualities.
//
if (pPD && pPD->hDevMode && pPD->hDevNames) { HANDLE hPrnQ; // Memory handle for print qualities
DWORD dw; // return from DC_ENUMRESOLUTIONS
LPLONG pLong; // Pointer to pairs of longs
LPTSTR psDevice; LPTSTR psPort;
pDM = GlobalLock(pPD->hDevMode); pDN = GlobalLock(pPD->hDevNames);
if (pDM->dmSpecVersion < 0x030A) { goto EnumResNotSupported; }
psDevice = (LPTSTR)pDN + pDN->wDeviceOffset; psPort = (LPTSTR)pDN + pDN->wOutputOffset;
dw = DeviceCapabilities( psDevice, psPort, DC_ENUMRESOLUTIONS, NULL, NULL ); if (!dw || (dw == (DWORD)(-1))) { goto EnumResNotSupported; }
hPrnQ = GlobalAlloc(GHND, dw * 2 * sizeof(LONG)); if (!hPrnQ) { goto EnumResNotSupported; }
if (pLong = GlobalLock(hPrnQ)) { dw = DeviceCapabilities( psDevice, psPort, DC_ENUMRESOLUTIONS, (LPTSTR)pLong, 0 );
for (nStringID = 0, i = (SHORT)(LOWORD(dw) - 1); i >= 0; i--) { DWORD xRes, yRes;
if ((xRes = pLong[i * 2]) != (yRes = pLong[i * 2 + 1]) ) { StringCchPrintf(szBuf, ARRAYSIZE(szBuf), TEXT("%ld dpi x %ld dpi"), xRes, yRes); } else { StringCchPrintf(szBuf, ARRAYSIZE(szBuf), TEXT("%ld dpi"), yRes); }
SendMessage(hCmb, CB_INSERTSTRING, 0, (LONG_PTR)(LPTSTR)szBuf); SendMessage(hCmb, CB_SETITEMDATA, 0, xRes);
if ( ((SHORT)xRes == nQuality) && ( (wWinVer < 0x030A) || !pDM->dmYResolution || (pDM->dmYResolution == (SHORT)yRes) ) ) { nStringID = i; } } GlobalUnlock(hPrnQ); } GlobalFree(hPrnQ);
SendMessage(hCmb, CB_SETCURSEL, (WPARAM)nStringID, 0L); } else { EnumResNotSupported:
for ( i = -1, nStringID = iszDraftPrnQ; nStringID >= iszHighPrnQ; i--, nStringID-- ) { if (!CDLoadString(g_hinst, nStringID, szBuf, ARRAYSIZE(szBuf))) { return; } SendMessage(hCmb, CB_INSERTSTRING, 0, (LONG_PTR)(LPTSTR)szBuf); SendMessage(hCmb, CB_SETITEMDATA, 0, MAKELONG(i, 0)); }
if ((nQuality >= 0) || (nQuality < -4)) { //
// Set to HIGH.
//
nQuality = -4; } SendMessage(hCmb, CB_SETCURSEL, (WPARAM)(nQuality + 4), 0L); }
if (pDM) { GlobalUnlock(pPD->hDevMode); } if (pDN) { GlobalUnlock(pPD->hDevNames); } }
////////////////////////////////////////////////////////////////////////////
//
// PrintChangeProperties
//
// Puts up the dialog to modify the properties.
//
////////////////////////////////////////////////////////////////////////////
VOID PrintChangeProperties( HWND hDlg, UINT Id, PPRINTINFO pPI) { LPPRINTDLG pPD = pPI->pPD; LPDEVMODE pDM; LONG cbNeeded; HANDLE hDevMode; WORD nCopies, nCollate; BOOL bTest; HWND hCtl;
//
// There must be a devmode already.
//
if (!pPD->hDevMode) { return; }
//
// Get the number of bytes needed for the devmode.
//
cbNeeded = DocumentProperties( hDlg, pPI->hCurPrinter, (pPI->pCurPrinter) ? pPI->pCurPrinter->pPrinterName : NULL, NULL, NULL, 0 );
//
// Reallocate the devmode to be sure there is enough room in it, and
// then put up the document properties dialog box.
//
if ( (cbNeeded > 0) && (hDevMode = GlobalReAlloc(pPD->hDevMode, cbNeeded, GHND)) && (pDM = GlobalLock(hDevMode)) ) { //
// This is done here to make sure that the ReAlloc succeeded
// before trashing the old hDevMode.
//
pPD->hDevMode = hDevMode;
//
// Set the number of copies and collation in the devmode before
// calling DocumentProperties, if appropriate.
//
nCopies = pDM->dmCopies; nCollate = pDM->dmCollate; if (Id == ID_PRINT_C_NAME) { //
// Get the number of copies from the edit control.
//
pDM->dmCopies = (WORD)GetDlgItemInt( hDlg, ID_PRINT_E_COPIES, &bTest, FALSE ); if ((!bTest) || (!pDM->dmCopies)) { pDM->dmCopies = nCopies; }
//
// Get the collation from the check box.
//
if ( (hCtl = GetDlgItem(hDlg, ID_PRINT_X_COLLATE)) && IsWindowEnabled(hCtl) ) { SetField( pDM, dmCollate, (IsDlgButtonChecked(hDlg, ID_PRINT_X_COLLATE)) ? DMCOLLATE_TRUE : DMCOLLATE_FALSE ); } } else // ID_SETUP_C_NAME
{ if ( (pDM->dmFields & DM_COPIES) && (pPI->ProcessVersion < 0x40000) && (!(pPD->Flags & PD_USEDEVMODECOPIES)) && (pPD->nCopies) ) { pDM->dmCopies = pPD->nCopies;
if (pDM->dmFields & DM_COLLATE) { //
// DM_COLLATE was specified, so dmCollate exists.
//
pDM->dmCollate = (pPD->Flags & PD_COLLATE) ? DMCOLLATE_TRUE : DMCOLLATE_FALSE; } } }
//
// Put up the Document Properties dialog box.
//
if (DocumentProperties( hDlg, pPI->hCurPrinter, (pPI->pCurPrinter) ? pPI->pCurPrinter->pPrinterName : NULL, pDM, pDM, DM_PROMPT | DM_MODIFY | DM_COPY ) == IDOK) { //
// Save the new number of copies and collation, if appropriate.
//
if (pDM->dmFields & DM_COPIES) { pPD->nCopies = pDM->dmCopies; } if (pDM->dmFields & DM_COLLATE) { if (pDM->dmCollate == DMCOLLATE_FALSE) { pPD->Flags &= ~PD_COLLATE; pPI->Status &= ~PI_COLLATE_REQUESTED; } else { pPD->Flags |= PD_COLLATE; pPI->Status |= PI_COLLATE_REQUESTED; } }
//
// Update the dialog.
//
if (Id == ID_PRINT_C_NAME) { //
// Update the print dialog with the new info.
//
PrintInitBannerAndQuality(hDlg, pPI, pPD); } else // ID_SETUP_C_NAME
{ //
// Update the print setup dialog with the new info.
//
PrintUpdateSetupDlg(hDlg, pPI, pDM, FALSE); } } else { //
// Operation cancelled. Restore the number of copies
// and the collation in the devmode.
//
pDM->dmCopies = nCopies; SetField(pDM, dmCollate, nCollate); }
GlobalUnlock(pPD->hDevMode);
SendMessage( hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDOK), 1L ); } }
////////////////////////////////////////////////////////////////////////////
//
// PrintPrinterChanged
//
////////////////////////////////////////////////////////////////////////////
VOID PrintPrinterChanged( HWND hDlg, UINT Id, PPRINTINFO pPI) { LPPRINTDLG pPD = pPI->pPD; HANDLE hDM = NULL; LPDEVMODE pDM = NULL; LPDEVMODE pDMOld = NULL; HWND hCtl; UINT Orientation; LONG cbSize; DWORD dmSize;
HourGlass(TRUE);
//
// Close the old printer, if necessary.
//
if (pPI->hCurPrinter) { ClosePrinter(pPI->hCurPrinter); pPI->hCurPrinter = 0; }
//
// Get the current printer from the combo box.
//
if (Id && (hCtl = GetDlgItem(hDlg, Id))) { TCHAR szPrinter[MAX_PRINTERNAME]; DWORD ctr;
ComboBoxGetLBText( hCtl, (DWORD)SendMessage(hCtl, CB_GETCURSEL, 0, 0), szPrinter, ARRAYSIZE(szPrinter) );
pPI->pCurPrinter = NULL; for (ctr = 0; ctr < pPI->cPrinters; ctr++) { if (!lstrcmp(pPI->pPrinters[ctr].pPrinterName, szPrinter)) { pPI->pCurPrinter = &pPI->pPrinters[ctr]; break; } } if (!pPI->pCurPrinter) { HourGlass(FALSE); return; } }
//
// Open the current printer.
//
OpenPrinter(pPI->pCurPrinter->pPrinterName, &pPI->hCurPrinter, NULL);
//
// Build the device names.
//
PrintBuildDevNames(pPI);
//
// Get the devmode information.
//
cbSize = DocumentProperties( hDlg, pPI->hCurPrinter, pPI->pCurPrinter->pPrinterName, NULL, NULL, 0 ); if (cbSize > 0) { hDM = GlobalAlloc(GHND, cbSize);
//
// Get the default DevMode for the new printer.
//
if (hDM && (pDM = GlobalLock(hDM)) && (DocumentProperties( hDlg, pPI->hCurPrinter, pPI->pCurPrinter->pPrinterName, pDM, NULL, DM_COPY ) == IDOK)) { //
// See if we need to merge in old DevMode settings.
//
if (pPD->hDevMode && (pDMOld = GlobalLock(pPD->hDevMode))) { //
// Reset the PaperSource back to the Document Default.
//
if (pDM->dmFields & DM_DEFAULTSOURCE) { pDMOld->dmFields |= DM_DEFAULTSOURCE; pDMOld->dmDefaultSource = pDM->dmDefaultSource; } else { pDMOld->dmFields &= ~DM_DEFAULTSOURCE; }
//
// Copy relevant info from the old devmode to the new
// devmode.
//
dmSize = min(pDM->dmSize, pDMOld->dmSize); if (dmSize > FIELD_OFFSET(DEVMODE, dmFields)) { CopyMemory( &(pDM->dmFields), &(pDMOld->dmFields), dmSize - FIELD_OFFSET(DEVMODE, dmFields) ); }
//
// Free the old devmode.
//
GlobalUnlock(pPD->hDevMode); GlobalFree(pPD->hDevMode); }
//
// Save the new DevMode in the pPD structure.
//
pPD->hDevMode = hDM;
//
// Get the newly merged DevMode.
//
pDM->dmFields = pDM->dmFields & (DM_ORIENTATION | DM_PAPERSIZE | DM_PAPERLENGTH | DM_PAPERWIDTH | DM_SCALE | DM_COPIES | DM_COLLATE | DM_FORMNAME | DM_DEFAULTSOURCE); DocumentProperties( hDlg, pPI->hCurPrinter, pPI->pCurPrinter->pPrinterName, pDM, pDM, DM_MODIFY | DM_COPY ); GlobalUnlock(hDM); } else if (hDM) { if (pDM) { GlobalUnlock(hDM); } GlobalFree(hDM); } }
//
// Fill in the appropriate information for the rest of the
// Print or Print Setup dialog box.
//
if (Id == ID_PRINT_C_NAME) { PrintInitBannerAndQuality(hDlg, pPI, pPD); } else // ID_SETUP_C_NAME
{ if (pPD->hDevMode && (pDM = GlobalLock(pPD->hDevMode))) { if (hCtl = GetDlgItem(hDlg, ID_SETUP_C_SIZE)) { PrintInitPaperCombo( pPI, hCtl, GetDlgItem(hDlg, ID_SETUP_S_SIZE), pPI->pCurPrinter, pDM, DC_PAPERNAMES, CCHPAPERNAME, DC_PAPERS ); }
if (hCtl = GetDlgItem(hDlg, ID_SETUP_C_SOURCE)) { PrintInitPaperCombo( pPI, hCtl, GetDlgItem(hDlg, ID_SETUP_S_SOURCE), pPI->pCurPrinter, pDM, DC_BINNAMES, CCHBINNAME, DC_BINS ); }
PrintInitOrientation(hDlg, pPI, pDM); Orientation = (pDM->dmOrientation == DMORIENT_PORTRAIT) ? ID_SETUP_R_PORTRAIT : ID_SETUP_R_LANDSCAPE; PrintSetOrientation(hDlg, pPI, pDM, Orientation, Orientation);
PrintInitDuplex(hDlg, pDM); PrintSetDuplex( hDlg, pDM, pDM->dmDuplex + ID_SETUP_R_NONE - DMDUP_SIMPLEX );
GlobalUnlock(pPD->hDevMode); } }
//
// Update the status information.
//
PrintUpdateStatus(hDlg, pPI);
HourGlass(FALSE); }
////////////////////////////////////////////////////////////////////////////
//
// PrintCancelPrinterChanged
//
// Opens the old printer since the user hit cancel. The devmode and
// devnames structures have already been set back to the old ones.
//
////////////////////////////////////////////////////////////////////////////
VOID PrintCancelPrinterChanged( PPRINTINFO pPI, LPTSTR pPrinterName) { LPPRINTDLG pPD = pPI->pPD; PPRINTER_INFO_2 pCurPrinter;
//
// Make sure we have a previous printer and a devmode.
//
if ((pPrinterName[0] == 0) || (!pPD->hDevMode)) { return; }
//
// Turn on the hour glass.
//
HourGlass(TRUE);
//
// Find the current printer in the list.
//
pCurPrinter = PrintSearchForPrinter(pPI, pPrinterName); if (!pCurPrinter) { HourGlass(FALSE); return; }
//
// Close the old printer, if necessary.
//
if (pPI->hCurPrinter) { ClosePrinter(pPI->hCurPrinter); pPI->hCurPrinter = 0; }
//
// Save the current printer.
//
pPI->pCurPrinter = pCurPrinter;
//
// Open the current printer.
//
OpenPrinter(pPI->pCurPrinter->pPrinterName, &pPI->hCurPrinter, NULL);
//
// Turn off the hour glass.
//
HourGlass(FALSE); }
////////////////////////////////////////////////////////////////////////////
//
// PrintUpdateStatus
//
////////////////////////////////////////////////////////////////////////////
VOID PrintUpdateStatus( HWND hDlg, PPRINTINFO pPI) { TCHAR szSeparator[] = TEXT("; "); TCHAR szText[256]; TCHAR szJobs[64]; LPDEVMODE pDM; UINT Length; DWORD dwStatus; int ctr; TCHAR *ps; BOOL bFound;
//
// Update the printer status information in the dialog.
//
if (!GetDlgItem(hDlg, ID_BOTH_S_STATUS) || (!pPI->pCurPrinter)) { return; }
//
// ---------------------- Update Status ----------------------
//
szText[0] = CHAR_NULL;
if (pPI->pCurPrinter->Attributes & PRINTER_ATTRIBUTE_DEFAULT) { CDLoadString(g_hinst, iszStatusDefaultPrinter, szText, ARRAYSIZE(szText)); }
Length = lstrlen(szText); dwStatus = pPI->pCurPrinter->Status; for (ctr = 0; ctr++ < 32; dwStatus = dwStatus >> 1) { if (dwStatus & 1) { INT ilen = lstrlen(szText);
CDLoadString( g_hinst, iszStatusReady + ctr, szText + ilen, ARRAYSIZE(szText) - ilen); } }
if (szText[Length]) { if (CDLoadString(g_hinst, iszStatusDocumentsWaiting, szJobs, ARRAYSIZE(szJobs))) { StringCchPrintf( szText + lstrlen(szText), ARRAYSIZE(szText) - lstrlen(szText), szJobs, pPI->pCurPrinter->cJobs ); } } else { CDLoadString(g_hinst, iszStatusReady, szText + Length, ARRAYSIZE(szText) - Length); }
SetDlgItemText(hDlg, ID_BOTH_S_STATUS, szText); UpdateWindow(GetDlgItem(hDlg, ID_BOTH_S_STATUS));
//
// ---------------------- Update Type ----------------------
//
if (pPI->pCurPrinter->pDriverName) { StringCchCopy(szText, ARRAYSIZE(szText), pPI->pCurPrinter->pDriverName); } else { szText[0] = CHAR_NULL; }
if (pPI->pPD->hDevMode && (pDM = GlobalLock(pPI->pPD->hDevMode))) { if (pDM->dmSpecVersion < 0x0400) { StringCchCat(szText, ARRAYSIZE(szText), TEXT(" (3.x)")); // old driver designation
} GlobalUnlock(pPI->pPD->hDevMode); }
SetDlgItemText(hDlg, ID_BOTH_S_TYPE, szText); UpdateWindow(GetDlgItem(hDlg, ID_BOTH_S_TYPE));
//
// ---------------------- Update Location ----------------------
//
if (pPI->pCurPrinter->pLocation && pPI->pCurPrinter->pLocation[0]) { bFound = FALSE; StringCchCopy(szText, ARRAYSIZE(szText), pPI->pCurPrinter->pLocation); for (ps = szText; *ps; ps++) { if (ps[0] == TEXT('\r') && ps[1] == TEXT('\n')) { *ps++ = CHAR_SEMICOLON; *ps = CHAR_SPACE; } else { bFound = TRUE; } } if (!bFound) { goto ShowPortName; } } else { ShowPortName: if (pPI->pCurPrinter->pPortName) { StringCchCopy(szText, ARRAYSIZE(szText), pPI->pCurPrinter->pPortName); } else { szText[0] = CHAR_NULL; } }
EnableWindow(GetDlgItem(hDlg, ID_BOTH_S_WHERE), szText[0]); SetDlgItemText(hDlg, ID_BOTH_S_WHERE, szText); UpdateWindow(GetDlgItem(hDlg, ID_BOTH_S_WHERE));
//
// ---------------------- Update Comment ----------------------
//
if (pPI->pCurPrinter->pComment && pPI->pCurPrinter->pComment[0]) { bFound = FALSE; StringCchCopy(szText, ARRAYSIZE(szText), pPI->pCurPrinter->pComment); for (ps = szText; *ps; ps++) { if (ps[0] == TEXT('\r') && ps[1] == TEXT('\n')) { *ps++ = CHAR_SEMICOLON; *ps = CHAR_SPACE; } else { bFound = TRUE; } } if (!bFound) { //
// This is needed in case the comment field only has a
// carriage return in it. Without this check, it will
// show a ";" in the comment field. In this case, it
// should show "" in the comment field.
//
szText[0] = CHAR_NULL; } } else { szText[0] = CHAR_NULL; }
EnableWindow(GetDlgItem(hDlg, ID_BOTH_S_COMMENT), szText[0]); SetDlgItemText(hDlg, ID_BOTH_S_COMMENT, szText); UpdateWindow(GetDlgItem(hDlg, ID_BOTH_S_COMMENT)); }
////////////////////////////////////////////////////////////////////////////
//
// PrintGetSetupInfo
//
// Purpose: Retrieve info from Print Setup dialog elements
// Assumes: hDevMode handle to valid DEVMODE structure
// Returns: TRUE if hDevMode valid, FALSE otherwise
//
////////////////////////////////////////////////////////////////////////////
BOOL PrintGetSetupInfo( HWND hDlg, LPPRINTDLG pPD) { LPDEVMODE pDM = NULL; LPDEVNAMES pDN = NULL; HWND hCmb; int nInd;
if ( !pPD->hDevMode || !(pDM = GlobalLock(pPD->hDevMode)) ) { return (FALSE); }
// Don't need to do this - this is kept up to date.
// pDM->dmFields |= DM_ORIENTATION;
if (hCmb = GetDlgItem(hDlg, ID_SETUP_C_SIZE)) { nInd = (int) SendMessage(hCmb, CB_GETCURSEL, 0, 0L); if (nInd != CB_ERR) { // pDM->dmFields |= DM_PAPERSIZE;
pDM->dmPaperSize = (SHORT)SendMessage( hCmb, CB_GETITEMDATA, nInd, 0 ); { // pDM->dmFields |= DM_FORMNAME;
ComboBoxGetLBText( hCmb, nInd, pDM->dmFormName, ARRAYSIZE(pDM->dmFormName) );
} } }
if (hCmb = GetDlgItem(hDlg, ID_SETUP_C_SOURCE)) { nInd = (int) SendMessage(hCmb, CB_GETCURSEL, 0 , 0L); if (nInd != CB_ERR) { // pDM->dmFields |= DM_DEFAULTSOURCE;
pDM->dmDefaultSource = (SHORT)SendMessage( hCmb, CB_GETITEMDATA, nInd, 0 ); } }
if ( (pPD->hDevNames) && (pDN = GlobalLock(pPD->hDevNames)) ) { PrintReturnICDC(pPD, pDN, pDM); GlobalUnlock(pPD->hDevNames); }
GlobalUnlock(pPD->hDevMode);
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// PrintSearchForPrinter
//
// Returns the pointer to the PRINTER_INFO_2 structure for the printer
// with the name pPrinterName.
//
////////////////////////////////////////////////////////////////////////////
PPRINTER_INFO_2 PrintSearchForPrinter( PPRINTINFO pPI, LPCTSTR lpsPrinterName) { DWORD ctr;
//
// Search for the printer.
//
for (ctr = 0; ctr < pPI->cPrinters; ctr++) { if (!lstrcmp(pPI->pPrinters[ctr].pPrinterName, lpsPrinterName)) { //
// Found it.
//
return (&pPI->pPrinters[ctr]); } }
//
// Did not find the printer.
//
return (NULL); }
////////////////////////////////////////////////////////////////////////////
//
// PrintGetExtDeviceMode
//
////////////////////////////////////////////////////////////////////////////
VOID PrintGetExtDeviceMode( HWND hDlg, PPRINTINFO pPI) { DWORD ctr; LPDEVMODEA pDMA; LPDEVMODEW pDMW; int iResult; CHAR szPrinterNameA[MAX_PRINTERNAME];
if (!pPI->bUseExtDeviceMode) { return; }
//
// Allocate the array to hold whether or not a new devmode has been
// allocated for each of the printers.
//
// This is necessary because if the call to ExtDeviceMode fails, then
// nothing was allocated. The one that is currently in the pPrinters
// array is actually part of the big pPrinters array (from the call
// to GetPrinter - it wants one giant buffer).
//
if (pPI->cPrinters) { if (pPI->pAllocInfo) { GlobalFree(pPI->pAllocInfo); } pPI->pAllocInfo = (LPBOOL)GlobalAlloc( GPTR, pPI->cPrinters * sizeof(BOOL) ); }
if (pPI->pAllocInfo) { //
// If we were called from a WOW app with a NULL devmode,
// then call ExtDeviceMode to get a default devmode.
//
for (ctr = 0; ctr < pPI->cPrinters; ctr++) { //
// Convert the printer name from Unicode to ANSI.
//
SHUnicodeToAnsi(pPI->pPrinters[ctr].pPrinterName, szPrinterNameA, ARRAYSIZE(szPrinterNameA));
//
// Call ExtDeviceMode with 0 flags to find out the
// size of the devmode structure we need.
//
iResult = ExtDeviceMode( hDlg, NULL, NULL, szPrinterNameA, NULL, NULL, NULL, 0 ); if (iResult < 0) { continue; }
//
// Allocate the space.
//
pDMA = GlobalAlloc(GPTR, iResult); if (!pDMA) { continue; }
//
// Call ExtDeviceMode to get the dummy devmode structure.
//
iResult = ExtDeviceMode( hDlg, NULL, pDMA, szPrinterNameA, NULL, NULL, NULL, DM_COPY ); if (iResult < 0) { GlobalFree(pDMA); continue; }
//
// Call AllocateUnicodeDevMode to allocate and copy the unicode
// version of this ANSI dev mode.
//
pDMW = AllocateUnicodeDevMode(pDMA); if (!pDMW) { GlobalFree(pDMA); continue; }
//
// Store the pointer to the new devmode in the old pointer
// position. We don't have to worry about freeing the
// current contents of pPrinter[ctr].pDevMode before sticking
// in the new pointer because in reality the pPrinter memory
// buffer is just one long allocation (the memory pDevmode
// points to is part of the pPrinters buffer). So, when the
// buffer is freed at the end, the old devmode will be freed
// with it.
//
pPI->pPrinters[ctr].pDevMode = pDMW; pPI->pAllocInfo[ctr] = TRUE;
//
// Free the ANSI dev mode.
//
GlobalFree(pDMA); } } }
////////////////////////////////////////////////////////////////////////////
//
// PrintEnumAndSelect
//
// This routine enumerates the LOCAL and CONNECTED printers.
// It is called at initialization and when a new printer is
// added via the NETWORK... button.
//
// If the second parameter is set, the first parameter is overridden.
// When the second parameter is NULL, the first parameter is used.
// In this case, if the first parameter is greater than the total
// number of printers enumerated, then the last one in the list is
// selected.
//
////////////////////////////////////////////////////////////////////////////
BOOL PrintEnumAndSelect( HWND hDlg, UINT Id, PPRINTINFO pPI, LPTSTR lpsPrinterToSelect, BOOL bEnumPrinters) { HWND hCtl = ((hDlg && Id) ? GetDlgItem(hDlg, Id) : 0); LPPRINTDLG pPD = pPI->pPD; TCHAR szPrinter[MAX_PRINTERNAME]; DWORD cbNeeded; DWORD cReturned; DWORD ctr; PPRINTER_INFO_2 pPrinters = NULL;
//
// Enumerate the printers, if necessary.
//
if (bEnumPrinters) { Print_Enumerate: //
// Save lpsPrinterToSelect in a local before it gets freed.
//
if (lpsPrinterToSelect) { lstrcpyn(szPrinter, lpsPrinterToSelect, ARRAYSIZE(szPrinter)); lpsPrinterToSelect = szPrinter; }
//
// Close and free any open printers.
//
PrintClosePrinters(pPI);
//
// Clear out the error code.
//
StoreExtendedError(CDERR_GENERALCODES);
//
// Enumerate the printers.
//
if (!EnumPrinters( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &cbNeeded, &cReturned )) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { if (pPrinters = GlobalAlloc(GPTR, cbNeeded)) { if (EnumPrinters( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 2, (LPBYTE)pPrinters, cbNeeded, &cbNeeded, &cReturned )) { pPI->cPrinters = cReturned; pPI->pPrinters = pPrinters; pPI->Status |= PI_PRINTERS_ENUMERATED; } else { StoreExtendedError(PDERR_NODEFAULTPRN); } } else { StoreExtendedError(CDERR_MEMALLOCFAILURE); } } else { StoreExtendedError(PDERR_NODEFAULTPRN); } } else { StoreExtendedError(PDERR_NODEFAULTPRN); }
if (GetStoredExtendedError()) { if (pPrinters) { GlobalFree(pPrinters); } return (FALSE); }
//
// Make modifications for a WOW app.
//
if (pPI->bUseExtDeviceMode) { PrintGetExtDeviceMode(hDlg, pPI); }
//
// Try the selected printer.
//
if (lpsPrinterToSelect) { pPI->pCurPrinter = PrintSearchForPrinter(pPI, lpsPrinterToSelect); }
//
// Open the current printer.
//
if (pPI->pCurPrinter) { //
// Open the current printer.
//
OpenPrinter(pPI->pCurPrinter->pPrinterName, &pPI->hCurPrinter, NULL); } else { //
// If there isn't a current printer, try the printers in
// the list until either one is found that can be opened or
// until there are no more printers in the list.
//
for (ctr = 0; ctr < pPI->cPrinters; ctr++) { pPI->pCurPrinter = &pPI->pPrinters[ctr];
//
// Try to open the printer.
//
if (OpenPrinter( pPI->pCurPrinter->pPrinterName, &pPI->hCurPrinter, NULL )) { break; } } } } else { //
// If there isn't a current printer, then try to enumerate.
// This means something isn't setup properly.
//
if ((!pPI->pCurPrinter) || (!pPI->pPrinters)) { goto Print_Enumerate; } }
if (hCtl) { //
// Reset the contents of the list box.
//
SendMessage(hCtl, CB_RESETCONTENT, 0, 0);
//
// Add all of the printer name strings to the list box.
//
for (ctr = 0; ctr < pPI->cPrinters; ctr++) { SendMessage( hCtl, CB_ADDSTRING, 0, (LPARAM)pPI->pPrinters[ctr].pPrinterName ); }
//
// Set the current selection in the list box.
//
SendMessage( hCtl, CB_SETCURSEL, SendMessage( hCtl, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pPI->pCurPrinter->pPrinterName ), 0L ); }
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// PrintBuildDevNames
//
////////////////////////////////////////////////////////////////////////////
VOID PrintBuildDevNames( PPRINTINFO pPI) { LPPRINTDLG pPD = pPI->pPD; LPTSTR pPrinterName = NULL; LPTSTR pPortName = NULL; TCHAR szBuffer[MAX_PATH]; TCHAR szPort[MAX_PATH]; LPTSTR pStr; LPDEVNAMES pDN; DWORD cbDevNames; HANDLE hPrinter ; PPRINTER_INFO_2 pPrinter = NULL;
//
// If this is called from PrintReturnDefault, there is no
// PrinterInfo (pPI->pCurPrinter) because the printers were not
// enumerated. So, build the DEVNAME from win.ini.
//
pStr = szBuffer; if (!pPI->pCurPrinter) { //
// Get the default printer from the "Windows" section of win.ini.
// (eg. device=\\server\local,winspool,Ne00:)
//
if ( (pPD->Flags & PD_RETURNDEFAULT) && GetProfileString( szTextWindows, szTextDevice, szTextNull, szBuffer, ARRAYSIZE(szBuffer) ) ) { //
// Make sure null-terminated.
//
szBuffer[ARRAYSIZE(szBuffer) - 1] = CHAR_NULL;
// Examples of szBuffer:
// "My Local Printer,winspool,LPT1:" or
// "\\server\local,winspool,Ne00:"
//
// Skip leading space (if any).
//
while (*pStr == CHAR_SPACE) { pStr++; }
//
// First token is the printer name.
//
pPrinterName = pStr;
while (*pStr && *pStr != CHAR_COMMA) { pStr++; }
//
// NULL terminate the printer name.
//
*pStr++ = CHAR_NULL;
// For Newer Apps return the port name from the PRINT_INFO_2 structure.
// For older apps return the short port name give in the win.ini
if (pPI->ProcessVersion >= 0x40000) { //Newer App
if (OpenPrinter(pPrinterName, &hPrinter, NULL)) { if (pPrinter = PrintGetPrinterInfo2(hPrinter)) { StringCchCopy(szPort, ARRAYSIZE(szPort), pPrinter->pPortName); pPortName = szPort; GlobalFree(pPrinter); } ClosePrinter(hPrinter);
} else { //Unable to Open Printer so return
return ; } } else {
//Old App
//
// Skip the driver name (second token).
//
while (*pStr && *pStr++ != CHAR_COMMA) { ; }
//
// Skip leading space (if any).
//
while (*pStr == CHAR_SPACE) { pStr++; }
//
// Third (and last) token is the port name.
//
pPortName = pStr; } } else { return; } } else { //
// Get the printer name from the PrinterInfo2 structure
// for the current printer.
//
pPrinterName = pPI->pCurPrinter->pPrinterName;
//
// Newer Apps:
// Get the port name from the PrinterInfo2 structure for the
// current printer. Want to use the PrinterInfo2 structure
// for newer apps so that we can support multiple ports for
// one printer.
//
// Older Apps:
// First try to get the port name from the "devices" section
// of win.ini. If that fails, then use the PrinterInfo2
// structure for the current printer.
//
// This needs to use the "devices" section first due to a bug
// in AutoCAD. AutoCAD only allows 13 characters for the port
// name and it does not check the length when it tries to copy
// it to its own buffer.
//
if ( (pPI->ProcessVersion < 0x40000) && (GetProfileString( szTextDevices, pPrinterName, szTextNull, szBuffer, ARRAYSIZE(szBuffer) )) ) { //
// Make sure null-terminated.
//
szBuffer[ARRAYSIZE(szBuffer) - 1] = CHAR_NULL;
if ( !(pPortName = StrChr(szBuffer, CHAR_COMMA)) || (!((++pPortName)[0])) ) { //
// Get the port name from the PrinterInfo2 structure
// for the current printer.
//
pPortName = pPI->pCurPrinter->pPortName; } } else { pPortName = pPI->pCurPrinter->pPortName; } }
if (pPortName && pPrinterName) { //
// Compute the size of the DevNames structure.
//
cbDevNames = lstrlen(szDriver) + 1 + lstrlen(pPortName) + 1 + lstrlen(pPrinterName) + 1 + DN_PADDINGCHARS;
cbDevNames *= sizeof(TCHAR); cbDevNames += sizeof(DEVNAMES);
//
// Allocate the new DevNames structure.
//
pDN = NULL; if (pPD->hDevNames) { HANDLE handle;
handle = GlobalReAlloc(pPD->hDevNames, cbDevNames, GHND);
//Make sure the Realloc succeeded.
if (handle) { pPD->hDevNames = handle; } else { //Realloc didn't succeed. Free the old the memory
pPD->hDevNames = GlobalFree(pPD->hDevNames); } } else { pPD->hDevNames = GlobalAlloc(GHND, cbDevNames); }
//
// Fill in the DevNames structure with the appropriate information.
//
if ( (pPD->hDevNames) && (pDN = GlobalLock(pPD->hDevNames)) ) { pDN->wDriverOffset = sizeof(DEVNAMES) / sizeof(TCHAR); StringCchCopy((LPTSTR)pDN + pDN->wDriverOffset, lstrlen(szDriver) + 1, szDriver);
pDN->wDeviceOffset = pDN->wDriverOffset + lstrlen(szDriver) + 1; StringCchCopy((LPTSTR)pDN + pDN->wDeviceOffset, lstrlen(pPrinterName) + 1, pPrinterName);
pDN->wOutputOffset = pDN->wDeviceOffset + lstrlen(pPrinterName) + 1; StringCchCopy((LPTSTR)pDN + pDN->wOutputOffset, lstrlen(pPortName) + 1, pPortName);
if ( (pPD->Flags & PD_RETURNDEFAULT) || !lstrcmp(pPrinterName, pPI->szDefaultPrinter) ) { pDN->wDefault = DN_DEFAULTPRN; } else { pDN->wDefault = 0; }
GlobalUnlock(pPD->hDevNames); } } }
////////////////////////////////////////////////////////////////////////////
//
// PrintGetDevMode
//
// Create and/or fill DEVMODE structure.
//
////////////////////////////////////////////////////////////////////////////
HANDLE PrintGetDevMode( HWND hDlg, HANDLE hPrinter, LPTSTR lpsDeviceName, HANDLE hDevMode) { LONG cbNeeded; LPDEVMODE pDM;
cbNeeded = DocumentProperties( hDlg, hPrinter, lpsDeviceName, (PDEVMODE)NULL, (PDEVMODE)NULL, 0 );
if (cbNeeded > 0) { if (hDevMode) { HANDLE h = GlobalReAlloc(hDevMode, cbNeeded, GHND);
//Make sure realloc succeeded.
if (h) { hDevMode = h; } else { //Realloc didn't succeed. Free the memory occupied
GlobalFree(hDevMode); hDevMode = NULL; }
} else { hDevMode = GlobalAlloc(GHND, cbNeeded); }
if (hDevMode && (pDM = GlobalLock(hDevMode))) { if (DocumentProperties( hDlg, hPrinter, lpsDeviceName, pDM, NULL, DM_COPY ) != IDOK) { StoreExtendedError(PDERR_NODEFAULTPRN); GlobalUnlock(hDevMode); GlobalFree(hDevMode); return (NULL); }
GlobalUnlock(hDevMode); } else { if (hDevMode) { StoreExtendedError(CDERR_MEMLOCKFAILURE); GlobalFree(hDevMode); } else { StoreExtendedError(CDERR_MEMALLOCFAILURE); } return (NULL); } } else { DWORD dwErrCode;
hDevMode = NULL; dwErrCode = GetLastError();
if ( (dwErrCode == ERROR_UNKNOWN_PRINTER_DRIVER) || (dwErrCode == ERROR_MOD_NOT_FOUND) ) { if (hDlg) { PrintEditError(hDlg, 0, iszUnknownDriver, lpsDeviceName); } } }
return (hDevMode); }
////////////////////////////////////////////////////////////////////////////
//
// PrintReturnICDC
//
// Retrieve either the hDC or the hIC if either flag is set.
// Assumes the PD_PRINTOFILE flag is appropriately set.
//
////////////////////////////////////////////////////////////////////////////
VOID PrintReturnICDC( LPPRINTDLG pPD, LPDEVNAMES pDN, LPDEVMODE pDM) { if (pPD->Flags & PD_PRINTTOFILE) { //
// We are sure the destination buffer is large enough here. When we do the
// GlobalAlloc/GlobalRealloc in PrintBuildDevNames(), the buffer size has
// DN_PADDINGCHARS(16) characters for padding. Since the size of szFilePort
// is 5 and wOutPutOffest is placed at the end of the memory, the padding
// chars could be used to store szFilePort. So unless we change the order
// of offsets in DEVNAMES, we are safe here.
//
StringCchCopy((LPTSTR)pDN + pDN->wOutputOffset, lstrlen(szFilePort) + 1, szFilePort); }
//
// The dmCollate field wasn't part of the Win3.1 DevMode struct. The way
// 16-bit apps achieved collation was by checking the PD_COLLATE flag in
// the PrintDlg struct. The app would then figure out the page printing
// order to achieve collation. So what we're doing here is making sure
// that PD_COLLATE is the only collation mechanism for 16-bit apps. If we
// let DM_COLLATE get into the DC we'd end up with the driver trying to
// collate a job that the app is already trying to collate!
//
if ((pPD->Flags & CD_WOWAPP) && pDM) { if (pDM->dmFields & DM_COLLATE) { pPD->Flags |= PD_COLLATE; }
// these should always be off for WOW apps
pDM->dmCollate = DMCOLLATE_FALSE; pDM->dmFields &= ~DM_COLLATE; }
switch (pPD->Flags & (PD_RETURNDC | PD_RETURNIC)) { case ( PD_RETURNIC ) : { pPD->hDC = CreateIC( (LPTSTR)pDN + pDN->wDriverOffset, (LPTSTR)pDN + pDN->wDeviceOffset, (LPTSTR)pDN + pDN->wOutputOffset, pDM); if (pPD->hDC) { break; }
// else fall thru...
} case ( PD_RETURNDC ) : case ( PD_RETURNDC | PD_RETURNIC ) : { //
// PD_RETURNDC has priority if they are both set.
//
pPD->hDC = CreateDC( (LPTSTR)pDN + pDN->wDriverOffset, (LPTSTR)pDN + pDN->wDeviceOffset, (LPTSTR)pDN + pDN->wOutputOffset, pDM ); break; } } }
////////////////////////////////////////////////////////////////////////////
//
// PrintMeasureItem
//
////////////////////////////////////////////////////////////////////////////
VOID PrintMeasureItem( HANDLE hDlg, LPMEASUREITEMSTRUCT mis) { HDC hDC; TEXTMETRIC TM; HANDLE hFont;
if (hDC = GetDC(hDlg)) { hFont = (HANDLE)SendMessage(hDlg, WM_GETFONT, 0, 0L); if (!hFont) { hFont = GetStockObject(SYSTEM_FONT); } hFont = SelectObject(hDC, hFont); GetTextMetrics(hDC, &TM); mis->itemHeight = (WORD)TM.tmHeight; SelectObject(hDC, hFont); ReleaseDC(hDlg, hDC); } }
////////////////////////////////////////////////////////////////////////////
//
// PrintInitOrientation
//
// Enable/Disable Paper Orientation controls
//
// NOTE: If the driver doesn't support orientation AND is smart
// enough to tell us about it, disable the appropriate dialog items.
// "Smart enough" means the driver must support DC_ORIENTATION in its
// DeviceCapabilities routine. This was introduced for 3.1, hence the
// version test. NotBadDriver() may need to be incorporated if a
// problem driver is found in testing.
//
////////////////////////////////////////////////////////////////////////////
VOID PrintInitOrientation( HWND hDlg, PPRINTINFO pPI, LPDEVMODE pDM) { BOOL bEnable = TRUE; HWND hCtl; HDC hDC; int iHeight; PPRINTER_INFO_2 pPrinter = pPI->pCurPrinter;
if (!pPrinter) { return; }
if (pDM->dmSpecVersion >= 0x030A) { pPI->dwRotation = DeviceCapabilities( pPrinter->pPrinterName, pPrinter->pPortName, DC_ORIENTATION, NULL, pDM ); switch (pPI->dwRotation) { case ( ROTATE_LEFT ) : case ( ROTATE_RIGHT ) : { bEnable = TRUE; break; } default : { pPI->dwRotation = 0; bEnable = FALSE; pDM->dmOrientation = DMORIENT_PORTRAIT; CheckRadioButton( hDlg, ID_SETUP_R_PORTRAIT, ID_SETUP_R_LANDSCAPE, ID_SETUP_R_PORTRAIT ); break; } } }
if ( (pDM->dmOrientation != DMORIENT_PORTRAIT) && (pDM->dmOrientation != DMORIENT_LANDSCAPE) ) { pDM->dmOrientation = DMORIENT_PORTRAIT; }
if (hCtl = GetDlgItem(hDlg, ID_SETUP_R_LANDSCAPE)) { //
// Landscape
//
if ( !( (pPI->pPSD) && (pPI->pPSD->Flags & PSD_DISABLEORIENTATION) ) ) { EnableWindow(hCtl, bEnable); } } if (hCtl = GetDlgItem(hDlg, ID_SETUP_I_ORIENTATION)) { //
// Orientation of icon.
//
SetWindowLong( hCtl, GWL_STYLE, GetWindowLong(hCtl, GWL_STYLE) | SS_CENTERIMAGE ); }
if ( (!pPI->RtSampleXYWH.left) && (hCtl = GetDlgItem(hDlg, ID_SETUP_W_SAMPLE)) ) { GetWindowRect(hCtl, (LPRECT)&pPI->RtSampleXYWH); ScreenToClient(hDlg, (LPPOINT)&pPI->RtSampleXYWH.left); ScreenToClient(hDlg, (LPPOINT)&pPI->RtSampleXYWH.right);
iHeight = pPI->RtSampleXYWH.bottom - pPI->RtSampleXYWH.top; pPI->RtSampleXYWH.bottom = iHeight;
if (hDC = GetDC(0)) { iHeight = iHeight * GetDeviceCaps(hDC, LOGPIXELSX) / GetDeviceCaps(hDC, LOGPIXELSY); ReleaseDC(0, hDC); }
pPI->RtSampleXYWH.left = (pPI->RtSampleXYWH.left + pPI->RtSampleXYWH.right - iHeight) / 2; pPI->RtSampleXYWH.right = iHeight; } }
////////////////////////////////////////////////////////////////////////////
//
// PrintSetOrientation
//
// Switch icon, check button, for Portrait or LandScape printing mode.
//
////////////////////////////////////////////////////////////////////////////
VOID PrintSetOrientation( HWND hDlg, PPRINTINFO pPI, LPDEVMODE pDM, UINT uiOldId, UINT uiNewId) { BOOL bPortrait; HWND hIcn;
bPortrait = (uiNewId == ID_SETUP_R_PORTRAIT);
pDM->dmOrientation = ( bPortrait ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE );
CheckRadioButton(hDlg, ID_SETUP_R_PORTRAIT, ID_SETUP_R_LANDSCAPE, uiNewId);
if (hIcn = GetDlgItem(hDlg, ID_SETUP_I_ORIENTATION)) { ShowWindow(hIcn, SW_HIDE); SendMessage( hIcn, STM_SETICON, bPortrait ? (LONG_PTR)hIconPortrait : (LONG_PTR)hIconLandscape, 0L ); ShowWindow(hIcn, SW_SHOW); }
//
// Update the page setup dialog, if necessary.
//
if (pPI->pPSD) { PrintUpdatePageSetup(hDlg, pPI, pDM, uiOldId, uiNewId); } }
////////////////////////////////////////////////////////////////////////////
//
// PrintUpdatePageSetup
//
// Update the page setup information.
//
////////////////////////////////////////////////////////////////////////////
VOID PrintUpdatePageSetup( HWND hDlg, PPRINTINFO pPI, LPDEVMODE pDM, UINT uiOldId, UINT uiNewId) { BOOL bPortrait = (uiNewId == ID_SETUP_R_PORTRAIT); LPPAGESETUPDLG pPSD = pPI->pPSD; LPPRINTDLG pPD = pPI->pPD; HWND hWndSample; HWND hWndShadowRight; HWND hWndShadowBottom; HWND hWndSize; LONG lTemp;
if (!pPSD) { return; }
if (uiOldId != uiNewId) { RECT aRtMinMargin = pPSD->rtMinMargin; RECT aRtMargin = pPSD->rtMargin; HWND hWndLeft = GetDlgItem(hDlg, ID_SETUP_E_LEFT); HWND hWndTop = GetDlgItem(hDlg, ID_SETUP_E_TOP); HWND hWndRight = GetDlgItem(hDlg, ID_SETUP_E_RIGHT); HWND hWndBottom = GetDlgItem(hDlg, ID_SETUP_E_BOTTOM); TCHAR szLeft [8]; TCHAR szTop [8]; TCHAR szRight [8]; TCHAR szBottom[8];
GetWindowText(hWndLeft, szLeft, 8); GetWindowText(hWndTop, szTop, 8); GetWindowText(hWndRight, szRight, 8); GetWindowText(hWndBottom, szBottom, 8);
switch (uiNewId + pPI->dwRotation) { case ( ID_SETUP_R_PORTRAIT + ROTATE_RIGHT ) : // HP PCL
case ( ID_SETUP_R_LANDSCAPE + ROTATE_LEFT ) : // dot-matrix
{ pPSD->rtMinMargin.left = aRtMinMargin.top; pPSD->rtMinMargin.top = aRtMinMargin.right; pPSD->rtMinMargin.right = aRtMinMargin.bottom; pPSD->rtMinMargin.bottom = aRtMinMargin.left;
pPSD->rtMargin.left = aRtMargin.top; pPSD->rtMargin.top = aRtMargin.right; pPSD->rtMargin.right = aRtMargin.bottom; pPSD->rtMargin.bottom = aRtMargin.left;
SetWindowText(hWndLeft, szTop); SetWindowText(hWndRight, szBottom); SetWindowText(hWndTop, szRight); SetWindowText(hWndBottom, szLeft);
break; } case ( ID_SETUP_R_PORTRAIT + ROTATE_LEFT ) : // dot-matrix
case ( ID_SETUP_R_LANDSCAPE + ROTATE_RIGHT ) : // HP PCL
{ pPSD->rtMinMargin.left = aRtMinMargin.bottom; pPSD->rtMinMargin.top = aRtMinMargin.left; pPSD->rtMinMargin.right = aRtMinMargin.top; pPSD->rtMinMargin.bottom = aRtMinMargin.right;
pPSD->rtMargin.left = aRtMargin.bottom; pPSD->rtMargin.top = aRtMargin.left; pPSD->rtMargin.right = aRtMargin.top; pPSD->rtMargin.bottom = aRtMargin.right;
SetWindowText(hWndLeft, szBottom); SetWindowText(hWndRight, szTop); SetWindowText(hWndTop, szLeft); SetWindowText(hWndBottom, szRight);
break; } } } pPI->uiOrientationID = uiNewId;
//
// Update ptPaperSize.
//
pPI->PtPaperSizeMMs.x = 0; pPI->PtPaperSizeMMs.y = 0; pPD->Flags &= ~PI_WPAPER_ENVELOPE;
if ((hWndSize = GetDlgItem(hDlg, ID_SETUP_C_SIZE)) && (pPI->pCurPrinter)) { PPRINTER_INFO_2 pPrinter = pPI->pCurPrinter; DWORD dwNumber; LPWORD lpPapers; LPPOINT lpPaperSize; int nInd; DWORD i;
dwNumber = DeviceCapabilities( pPrinter->pPrinterName, pPrinter->pPortName, DC_PAPERS, NULL, pDM ); if ( dwNumber && (dwNumber != (DWORD)-1) && (lpPapers = LocalAlloc( LPTR, dwNumber * (sizeof(WORD) + sizeof(POINT)) * 2 )) ) { lpPaperSize = (LPPOINT)(lpPapers + dwNumber * 2);
DeviceCapabilities( pPrinter->pPrinterName, pPrinter->pPortName, DC_PAPERS, (LPTSTR)lpPapers, pDM ); DeviceCapabilities( pPrinter->pPrinterName, pPrinter->pPortName, DC_PAPERSIZE, (LPTSTR)lpPaperSize, pDM );
if ((nInd = (int) SendMessage(hWndSize, CB_GETCURSEL, 0, 0)) != CB_ERR) { pPI->wPaper = (WORD)SendMessage( hWndSize, CB_GETITEMDATA, nInd, 0 ); pDM->dmPaperSize = pPI->wPaper; } else { pPI->wPaper = pDM->dmPaperSize; }
ComboBoxGetLBText( hWndSize, nInd, pDM->dmFormName, ARRAYSIZE(pDM->dmFormName) );
switch (pPI->wPaper) { case ( DMPAPER_ENV_9 ) : case ( DMPAPER_ENV_10 ) : case ( DMPAPER_ENV_11 ) : case ( DMPAPER_ENV_12 ) : case ( DMPAPER_ENV_14 ) : case ( DMPAPER_ENV_DL ) : case ( DMPAPER_ENV_C5 ) : case ( DMPAPER_ENV_C3 ) : case ( DMPAPER_ENV_C4 ) : case ( DMPAPER_ENV_C6 ) : case ( DMPAPER_ENV_C65 ) : case ( DMPAPER_ENV_B4 ) : case ( DMPAPER_ENV_B5 ) : case ( DMPAPER_ENV_B6 ) : case ( DMPAPER_ENV_ITALY ) : case ( DMPAPER_ENV_MONARCH ) : case ( DMPAPER_ENV_PERSONAL ) : case ( DMPAPER_ENV_INVITE ) : case ( DMPAPER_JENV_KAKU2 ) : case ( DMPAPER_JENV_KAKU3 ) : case ( DMPAPER_JENV_CHOU3 ) : case ( DMPAPER_JENV_CHOU4 ) : case ( DMPAPER_JENV_KAKU2_ROTATED ) : case ( DMPAPER_JENV_KAKU3_ROTATED ) : case ( DMPAPER_JENV_CHOU3_ROTATED ) : case ( DMPAPER_JENV_CHOU4_ROTATED ) : case ( DMPAPER_JENV_YOU4 ) : case ( DMPAPER_JENV_YOU4_ROTATED ) : case ( DMPAPER_PENV_1 ) : case ( DMPAPER_PENV_2 ) : case ( DMPAPER_PENV_3 ) : case ( DMPAPER_PENV_4 ) : case ( DMPAPER_PENV_5 ) : case ( DMPAPER_PENV_6 ) : case ( DMPAPER_PENV_7 ) : case ( DMPAPER_PENV_8 ) : case ( DMPAPER_PENV_9 ) : case ( DMPAPER_PENV_10 ) : case ( DMPAPER_PENV_1_ROTATED ) : case ( DMPAPER_PENV_2_ROTATED ) : case ( DMPAPER_PENV_3_ROTATED ) : case ( DMPAPER_PENV_4_ROTATED ) : case ( DMPAPER_PENV_5_ROTATED ) : case ( DMPAPER_PENV_6_ROTATED ) : case ( DMPAPER_PENV_7_ROTATED ) : case ( DMPAPER_PENV_8_ROTATED ) : case ( DMPAPER_PENV_9_ROTATED ) : case ( DMPAPER_PENV_10_ROTATED ) : { pPD->Flags |= PI_WPAPER_ENVELOPE; break; } }
for (i = 0; i < dwNumber; i++) { if (lpPapers[i] == pPI->wPaper) { //
// In tenths of MMs.
//
*(LPPOINT)&pPI->PtPaperSizeMMs = lpPaperSize[i]; break; } }
LocalFree(lpPapers); } }
//
// If the paper size could not be found, use something reasonable
// (eg. letter).
//
if (!pPI->PtPaperSizeMMs.x) { pPI->PtPaperSizeMMs.x = 85 * MMS_PER_INCH / 10; } if (!pPI->PtPaperSizeMMs.y) { pPI->PtPaperSizeMMs.y = 11 * MMS_PER_INCH; }
//
// Rotate envelopes as needed.
//
if ( (pPD->Flags & PI_WPAPER_ENVELOPE) && (!pPI->dwRotation) && (pPI->PtPaperSizeMMs.x < pPI->PtPaperSizeMMs.y) ) { lTemp = pPI->PtPaperSizeMMs.x; pPI->PtPaperSizeMMs.x = pPI->PtPaperSizeMMs.y; pPI->PtPaperSizeMMs.y = lTemp; }
//
// Maintain everything in accordance with the orientation
// so that apps have to do as little work as possible.
//
if (!bPortrait) { lTemp = pPI->PtPaperSizeMMs.x; pPI->PtPaperSizeMMs.x = pPI->PtPaperSizeMMs.y; pPI->PtPaperSizeMMs.y = lTemp; }
//
// Set up return ptPaperSize value.
//
if (pPSD->Flags & PSD_INTHOUSANDTHSOFINCHES) { pPSD->ptPaperSize.x = pPI->PtPaperSizeMMs.x * 1000 / MMS_PER_INCH; pPSD->ptPaperSize.y = pPI->PtPaperSizeMMs.y * 1000 / MMS_PER_INCH; } else // PSD_INHUNDREDTHSOFMILLIMETERS
{ pPSD->ptPaperSize.x = pPI->PtPaperSizeMMs.x * 10; pPSD->ptPaperSize.y = pPI->PtPaperSizeMMs.y * 10; }
//
// Update RtMinMarginMMs and rtMinMargin for new papersize/orientation.
//
PrintSetMinMargins(hDlg, pPI, pDM);
//
// Don't let margins overlap (page might have shrunk).
//
if (pPSD->rtMargin.left + pPSD->rtMargin.right > pPSD->ptPaperSize.x) { lTemp = (pPD->Flags & PSD_INTHOUSANDTHSOFINCHES) ? 1000 : MMS_PER_INCH; pPSD->rtMargin.left = (pPSD->ptPaperSize.x - lTemp) / 2; pPSD->rtMargin.right = (pPSD->ptPaperSize.x - lTemp) / 2; } if (pPSD->rtMargin.top + pPSD->rtMargin.bottom > pPSD->ptPaperSize.y) { lTemp = (pPD->Flags & PSD_INTHOUSANDTHSOFINCHES) ? 1000 : MMS_PER_INCH; pPSD->rtMargin.top = (pPSD->ptPaperSize.y - lTemp) / 2; pPSD->rtMargin.bottom = (pPSD->ptPaperSize.y - lTemp) / 2; }
//
// There are new minimal margins, so adjust rtMargin
// (min margins might have grown).
//
if (pPSD->rtMargin.left < pPSD->rtMinMargin.left) pPSD->rtMargin.left = pPSD->rtMinMargin.left; if (pPSD->rtMargin.top < pPSD->rtMinMargin.top) pPSD->rtMargin.top = pPSD->rtMinMargin.top; if (pPSD->rtMargin.right < pPSD->rtMinMargin.right) pPSD->rtMargin.right = pPSD->rtMinMargin.right; if (pPSD->rtMargin.bottom < pPSD->rtMinMargin.bottom) pPSD->rtMargin.bottom = pPSD->rtMinMargin.bottom;
//
// The margins were adjusted, so update the ui.
//
PrintSetMargin(hDlg, pPI, ID_SETUP_E_LEFT, pPSD->rtMargin.left); PrintSetMargin(hDlg, pPI, ID_SETUP_E_TOP, pPSD->rtMargin.top); PrintSetMargin(hDlg, pPI, ID_SETUP_E_RIGHT, pPSD->rtMargin.right); PrintSetMargin(hDlg, pPI, ID_SETUP_E_BOTTOM, pPSD->rtMargin.bottom);
//
// Update the sample window size & shadow.
//
if ( (hWndSample = GetDlgItem(hDlg, ID_SETUP_W_SAMPLE)) && (hWndShadowRight = GetDlgItem(hDlg, ID_SETUP_W_SHADOWRIGHT)) && (hWndShadowBottom = GetDlgItem(hDlg, ID_SETUP_W_SHADOWBOTTOM)) ) { int iWidth = pPI->PtPaperSizeMMs.x; int iLength = pPI->PtPaperSizeMMs.y; int iExtent; RECT aRtSampleXYWH = pPI->RtSampleXYWH; int iX = aRtSampleXYWH.right / 16; int iY = aRtSampleXYWH.bottom / 16;
if (iWidth > iLength) { iExtent = aRtSampleXYWH.bottom * iLength / iWidth; aRtSampleXYWH.top += (aRtSampleXYWH.bottom - iExtent) / 2; aRtSampleXYWH.bottom = iExtent; } else { iExtent = aRtSampleXYWH.right * iWidth / iLength; aRtSampleXYWH.left += (aRtSampleXYWH.right - iExtent) / 2; aRtSampleXYWH.right = iExtent; }
SetWindowPos( hWndSample, 0, aRtSampleXYWH.left, aRtSampleXYWH.top, aRtSampleXYWH.right, aRtSampleXYWH.bottom, SWP_NOZORDER );
SetWindowPos( hWndShadowRight, 0, aRtSampleXYWH.left + aRtSampleXYWH.right, aRtSampleXYWH.top + iY, iX, aRtSampleXYWH.bottom, SWP_NOZORDER );
SetWindowPos( hWndShadowBottom, 0, aRtSampleXYWH.left + iX, aRtSampleXYWH.top + aRtSampleXYWH.bottom, aRtSampleXYWH.right, iY, SWP_NOZORDER );
InvalidateRect(hWndSample, NULL, TRUE); UpdateWindow(hDlg); UpdateWindow(hWndSample); UpdateWindow(hWndShadowRight); UpdateWindow(hWndShadowBottom); } }
////////////////////////////////////////////////////////////////////////////
//
// PrintInitDuplex
//
// Enable/Disable Paper Duplexing controls.
//
// Returns TRUE iff buttons used to be disabled, now enabled.
// Returns FALSE otherwise.
//
////////////////////////////////////////////////////////////////////////////
VOID PrintInitDuplex( HWND hDlg, LPDEVMODE pDM) { BOOL bEnable; HWND hCtl;
bEnable = (pDM->dmFields & DM_DUPLEX);
if (hCtl = GetDlgItem(hDlg, ID_SETUP_G_DUPLEX)) { EnableWindow(hCtl, bEnable); } if (hCtl = GetDlgItem(hDlg, ID_SETUP_R_NONE)) { EnableWindow(hCtl, bEnable); } if (hCtl = GetDlgItem(hDlg, ID_SETUP_R_LONG)) { EnableWindow(hCtl, bEnable); } if (hCtl = GetDlgItem(hDlg, ID_SETUP_R_SHORT)) { EnableWindow(hCtl, bEnable); }
if (hCtl = GetDlgItem(hDlg, ID_SETUP_I_DUPLEX)) { SetWindowLong( hCtl, GWL_STYLE, GetWindowLong(hCtl, GWL_STYLE) | SS_CENTERIMAGE ); if (!bEnable) { ShowWindow(hCtl, SW_HIDE); SendMessage(hCtl, STM_SETICON, (LONG_PTR)hIconPDuplexNone, 0L); ShowWindow(hCtl, SW_SHOW); } } }
////////////////////////////////////////////////////////////////////////////
//
// PrintSetDuplex
//
// This routine will operate on pDocDetails->pDMInput PSDEVMODE structure,
// making sure that is a structure we know about and can handle.
//
// If the pd doesn't have DM_DUPLEX caps then just display the appropriate
// paper icon for DMDUP_SIMPLEX (case where nRad = ID_SETUP_R_NONE).
//
// If nRad = 0, update icon but don't change radio button.
//
////////////////////////////////////////////////////////////////////////////
VOID PrintSetDuplex( HWND hDlg, LPDEVMODE pDM, UINT nRad) { BOOL bPortrait; HANDLE hDuplexIcon; HWND hCtl;
bPortrait = (pDM->dmOrientation == DMORIENT_PORTRAIT);
if (!(pDM->dmFields & DM_DUPLEX)) { nRad = ID_SETUP_R_NONE; }
//
// Boundary checking - default to ID_SETUP_R_NONE.
//
if (GetDlgItem(hDlg, ID_SETUP_R_NONE)) { if ((nRad < ID_SETUP_R_NONE) || (nRad > ID_SETUP_R_SHORT)) { if (IsDlgButtonChecked(hDlg, ID_SETUP_R_SHORT)) { nRad = ID_SETUP_R_SHORT; } else if (IsDlgButtonChecked(hDlg, ID_SETUP_R_LONG)) { nRad = ID_SETUP_R_LONG; } else { nRad = ID_SETUP_R_NONE; } } else { CheckRadioButton(hDlg, ID_SETUP_R_NONE, ID_SETUP_R_SHORT, nRad); } }
if (hCtl = GetDlgItem(hDlg, ID_SETUP_I_DUPLEX)) { switch (nRad) { case ( ID_SETUP_R_LONG ) : // Long Side - 2 sided printing
{ pDM->dmDuplex = DMDUP_VERTICAL; hDuplexIcon = bPortrait ? hIconPDuplexNoTumble : hIconLDuplexTumble;
break; } case ( ID_SETUP_R_SHORT ) : // Short Side - 2 sided printing
{ pDM->dmDuplex = DMDUP_HORIZONTAL; hDuplexIcon = bPortrait ? hIconPDuplexTumble : hIconLDuplexNoTumble;
break; } default : // None - 2 sided printing
{ pDM->dmDuplex = DMDUP_SIMPLEX; hDuplexIcon = bPortrait ? hIconPDuplexNone : hIconLDuplexNone;
break; } }
//
// Set the appropriate icon.
//
ShowWindow(hCtl, SW_HIDE); SendMessage(hCtl, STM_SETICON, (LONG_PTR)hDuplexIcon, 0L); ShowWindow(hCtl, SW_SHOW); } }
////////////////////////////////////////////////////////////////////////////
//
// PrintInitPaperCombo
//
////////////////////////////////////////////////////////////////////////////
VOID PrintInitPaperCombo( PPRINTINFO pPI, HWND hCmb, HWND hStc, PPRINTER_INFO_2 pPrinter, LPDEVMODE pDM, WORD fwCap1, WORD cchSize1, WORD fwCap2) { DWORD cStr1, cStr2, cRet1, cRet2, i; LPTSTR lpsOut1; LPWORD lpwOut2; BOOL fFill;
HourGlass(TRUE);
SendMessage(hCmb, CB_RESETCONTENT, 0, 0L);
cStr1 = DeviceCapabilities( pPrinter->pPrinterName, pPrinter->pPortName, fwCap1, NULL, pDM );
cStr2 = DeviceCapabilities( pPrinter->pPrinterName, pPrinter->pPortName, fwCap2, NULL, pDM );
//
// Check for error from DeviceCapabilities calls. If either
// call failed, simply set cStr1 to be 0 so that the windows will be
// disabled and nothing will be initialized.
//
if ((cStr1 == (DWORD)(-1)) || (cStr2 == (DWORD)(-1))) { cStr1 = 0; }
fFill = (cStr1 > 0) && (cStr1 == cStr2);
if (!((pPI->pPSD) && (pPI->pPSD->Flags & PSD_DISABLEPAPER))) { //
// If no entries, disable hCmb and hStc.
//
EnableWindow(hCmb, fFill); EnableWindow(hStc, fFill); }
if (fFill) { lpsOut1 = LocalAlloc(LPTR, cStr1 * cchSize1 * sizeof(TCHAR));
lpwOut2 = LocalAlloc(LPTR, cStr2 * sizeof(WORD));
if (lpsOut1 && lpwOut2) { cRet1 = DeviceCapabilities( pPrinter->pPrinterName, pPrinter->pPortName, fwCap1, (LPTSTR)lpsOut1, pDM );
cRet2 = DeviceCapabilities( pPrinter->pPrinterName, pPrinter->pPortName, fwCap2, (LPTSTR)lpwOut2, pDM );
if ((pPI->dwRotation = DeviceCapabilities( pPrinter->pPrinterName, pPrinter->pPortName, DC_ORIENTATION, NULL, pDM )) == (DWORD)(-1)) { pPI->dwRotation = 0; }
if ((cRet1 == cStr1) && (cRet2 == cStr2)) { LPTSTR lpsT1 = lpsOut1; LPWORD lpwT2 = lpwOut2; int nInd; LPTSTR lpFound = NULL; LPTSTR lpFirst = NULL;
for (i = 0; i < cRet1; i++, lpsT1 += cchSize1, lpwT2++) { //
// Look for a blank name entry.
//
if (!*lpsT1) { //
// Blank entry, so ignore.
//
continue; }
//
// Add the string to the list box.
//
nInd = (int) SendMessage( hCmb, CB_ADDSTRING, 0, (LPARAM)lpsT1 ); if (nInd != CB_ERR) { //
// Set the data associated with the string that
// was just added to the list box.
//
SendMessage( hCmb, CB_SETITEMDATA, nInd, (LPARAM)*lpwT2 );
//
// See if this item should be selected.
//
if (!lpFound) { if (!lpFirst) { lpFirst = lpsT1; }
if ( (fwCap1 == DC_PAPERNAMES) && (pDM->dmFields & DM_PAPERSIZE) && (pDM->dmPaperSize == (SHORT)*lpwT2) ) { lpFound = lpsT1; } else if ( (fwCap1 == DC_BINNAMES) && (pDM->dmFields & DM_DEFAULTSOURCE) && (pDM->dmDefaultSource == (SHORT)*lpwT2) ) { lpFound = lpsT1; } } } }
//
// Set the appropriate selection.
//
if (lpFound) { SendMessage( hCmb, CB_SETCURSEL, SendMessage( hCmb, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)lpFound ), 0 ); } else { if (fwCap1 == DC_PAPERNAMES) { //
// Check for a default FORM name.
//
if (!( (pDM->dmFields & DM_FORMNAME) && ((nInd = (int) SendMessage( hCmb, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)pDM->dmFormName )) != CB_ERR) )) { //
// Always select the first *enumerated* entry
// if no other selection was found.
//
SendMessage( hCmb, CB_SETCURSEL, (lpFirst) ? SendMessage( hCmb, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)lpFirst ) : 0, 0 ); } else { //
// Save the paper size since the form name exists
// in the list box.
//
// pDM->dmFields |= DM_PAPERSIZE;
pDM->dmPaperSize = (SHORT)SendMessage( hCmb, CB_GETITEMDATA, nInd, 0 ); } } else { //
// Set the SOURCE to the Default if it exists.
//
nInd = (int) SendMessage( hCmb, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)szDefaultSrc ); if (nInd != CB_ERR) { // pDM->dmFields |= DM_DEFAULTSOURCE;
pDM->dmDefaultSource = (SHORT)SendMessage( hCmb, CB_GETITEMDATA, nInd, 0 ); } else { //
// Always select the first *enumerated* entry
// if no other selection was found.
//
SendMessage( hCmb, CB_SETCURSEL, (lpFirst) ? SendMessage( hCmb, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)lpFirst ) : 0, 0 ); } } } } } if (lpsOut1) { LocalFree((HLOCAL)lpsOut1); }
if (lpwOut2) { LocalFree((HLOCAL)lpwOut2); } }
HourGlass(FALSE); }
////////////////////////////////////////////////////////////////////////////
//
// PrintEditError
//
// Set focus to an edit control and select the entire contents.
// This is generally used when an improper value was found at OK time.
//
// Assumes edit control not disabled.
//
////////////////////////////////////////////////////////////////////////////
VOID PrintEditError( HWND hDlg, int Id, UINT MessageId, ...) { HWND hEdit; TCHAR pszTitle[MAX_PATH]; TCHAR pszFormat[MAX_PATH]; TCHAR pszMessage[MAX_PATH];
//
// Put up the error message box.
//
if ( GetWindowText(hDlg, pszTitle, ARRAYSIZE(pszTitle)) && CDLoadString(g_hinst, MessageId, pszFormat, ARRAYSIZE(pszFormat)) ) { va_list ArgList;
va_start(ArgList, MessageId); wvnsprintf(pszMessage, ARRAYSIZE(pszMessage), pszFormat, ArgList); va_end(ArgList); MessageBeep(MB_ICONEXCLAMATION); MessageBox(hDlg, pszMessage, pszTitle, MB_ICONEXCLAMATION | MB_OK); }
//
// Highlight the invalid value.
//
if (hEdit = ((Id == 0) ? NULL : GetDlgItem(hDlg, Id))) { SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)hEdit, 1L); SendMessage(hEdit, EM_SETSEL, (WPARAM)0, (LPARAM)-1); } }
////////////////////////////////////////////////////////////////////////////
//
// PrintOpenPrinter
//
// If the OpenPrinter call is successful, this sets hPrinter, pPrinter,
// cPrinters, and pCurPrinter.
//
////////////////////////////////////////////////////////////////////////////
VOID PrintOpenPrinter( PPRINTINFO pPI, LPTSTR pPrinterName) { if (OpenPrinter(pPrinterName, &pPI->hCurPrinter, NULL)) { if (pPI->pPrinters = PrintGetPrinterInfo2(pPI->hCurPrinter)) { pPI->cPrinters = 1;
if (pPI->bUseExtDeviceMode) { PrintGetExtDeviceMode(NULL, pPI); } } pPI->pCurPrinter = pPI->pPrinters; } else { //
// Cannot trust the OpenPrinter call.
//
pPI->hCurPrinter = NULL; } }
////////////////////////////////////////////////////////////////////////////
//
// PrintClosePrinters
//
////////////////////////////////////////////////////////////////////////////
BOOL PrintClosePrinters( PPRINTINFO pPI) { if (pPI->hCurPrinter) { ClosePrinter(pPI->hCurPrinter); pPI->hCurPrinter = 0; } pPI->pCurPrinter = NULL;
FreePrinterArray(pPI);
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// UpdateSpoolerInfo
//
////////////////////////////////////////////////////////////////////////////
VOID UpdateSpoolerInfo( PPRINTINFO pPI) { LPDEVMODEA pDMA; CHAR szPrinterNameA[33]; LPDEVMODEW pDMW;
//
// Get a pointer to the devmode structure.
//
pDMW = GlobalLock(pPI->pPD->hDevMode); if ((!pDMW) || (!pPI->pCurPrinter)) { return; }
//
// Convert the printer name from Unicode to ANSI.
//
SHUnicodeToAnsi(pPI->pCurPrinter->pPrinterName, szPrinterNameA, ARRAYSIZE(szPrinterNameA));
//
// Allocate and convert the Unicode devmode to ANSI.
//
pDMA = AllocateAnsiDevMode(pDMW); if (!pDMA) { GlobalUnlock(pPI->pPD->hDevMode); return; }
//
// Update the spooler's information.
//
ExtDeviceMode( NULL, NULL, NULL, szPrinterNameA, NULL, pDMA, NULL, DM_UPDATE | DM_MODIFY );
//
// Free the buffer.
//
GlobalFree(pDMA); GlobalUnlock(pPI->pPD->hDevMode); }
////////////////////////////////////////////////////////////////////////////
//
// PrintGetPrinterInfo2
//
////////////////////////////////////////////////////////////////////////////
PPRINTER_INFO_2 PrintGetPrinterInfo2( HANDLE hPrinter) { PPRINTER_INFO_2 pPrinter = NULL; DWORD cbPrinter = 0;
StoreExtendedError(CDERR_GENERALCODES);
if (!GetPrinter(hPrinter, 2, NULL, 0, &cbPrinter) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { if (pPrinter = GlobalAlloc(GPTR, cbPrinter)) { if (!GetPrinter( hPrinter, 2, (LPBYTE)pPrinter, cbPrinter, &cbPrinter )) { GlobalFree(pPrinter); pPrinter = NULL; StoreExtendedError(PDERR_PRINTERNOTFOUND); } } else { StoreExtendedError(CDERR_MEMALLOCFAILURE); } } else { StoreExtendedError(PDERR_SETUPFAILURE); }
return (pPrinter); }
////////////////////////////////////////////////////////////////////////////
//
// ConvertStringToInteger
//
// Converts a string to an integer. Stops at the first non digit.
//
////////////////////////////////////////////////////////////////////////////
int ConvertStringToInteger( LPCTSTR pSrc) { int Number = 0; BOOL bNeg = FALSE;
if (*pSrc == TEXT('-')) { bNeg = TRUE; pSrc++; }
while (ISDIGIT(*pSrc)) { Number *= 10; Number += *pSrc - TEXT('0'); pSrc++; }
return ( bNeg ? -Number : Number ); }
////////////////////////////////////////////////////////////////////////////
//
// FreePrinterArray
//
// Purpose: Frees the buffer allocated to store printers.
//
// Parameters: PPRINTINFO pPI
//
// Return: void
//
////////////////////////////////////////////////////////////////////////////
VOID FreePrinterArray( PPRINTINFO pPI) { PPRINTER_INFO_2 pPrinters = pPI->pPrinters; DWORD dwCount; //
// If NULL, we can return now.
//
if (!pPrinters) { return; }
//
// If we made calls to ExtDeviceMode, then we need to
// free the buffers allocated for each devmode.
//
if (pPI->bUseExtDeviceMode) { if (pPI->pAllocInfo) { //
// Loop through each of the printers.
//
for (dwCount = 0; dwCount < pPI->cPrinters; dwCount++) { //
// If pDevMode exists, free it.
//
if ((pPrinters[dwCount].pDevMode) && (pPI->pAllocInfo[dwCount])) { GlobalFree(pPrinters[dwCount].pDevMode); pPrinters[dwCount].pDevMode = NULL; } } GlobalFree(pPI->pAllocInfo); pPI->pAllocInfo = NULL; } }
//
// Free the entire block.
//
GlobalFree(pPI->pPrinters); pPI->pPrinters = NULL; pPI->cPrinters = 0; }
////////////////////////////////////////////////////////////////////////////
//
// TermPrint
//
////////////////////////////////////////////////////////////////////////////
VOID TermPrint(void) { Print_UnloadLibraries(); // printnew.cpp
}
/*========================================================================*/ /* Page Setup <-> Print Dialog */ /*========================================================================*/
////////////////////////////////////////////////////////////////////////////
//
// TransferPSD2PD
//
////////////////////////////////////////////////////////////////////////////
VOID TransferPSD2PD( PPRINTINFO pPI) { if (pPI->pPSD && pPI->pPD) { pPI->pPD->hDevMode = pPI->pPSD->hDevMode; pPI->pPD->hDevNames = pPI->pPSD->hDevNames; } }
////////////////////////////////////////////////////////////////////////////
//
// TransferPD2PSD
//
////////////////////////////////////////////////////////////////////////////
VOID TransferPD2PSD( PPRINTINFO pPI) { if (pPI->pPSD && pPI->pPD) { pPI->pPSD->hDevMode = pPI->pPD->hDevMode; pPI->pPSD->hDevNames = pPI->pPD->hDevNames; } }
////////////////////////////////////////////////////////////////////////////
//
// TransferPSD2PDA
//
////////////////////////////////////////////////////////////////////////////
VOID TransferPSD2PDA( PPRINTINFO pPI) { if (pPI->pPSD && pPI->pPDA) { pPI->pPDA->hDevMode = pPI->pPSD->hDevMode; pPI->pPDA->hDevNames = pPI->pPSD->hDevNames; } }
////////////////////////////////////////////////////////////////////////////
//
// TransferPDA2PSD
//
////////////////////////////////////////////////////////////////////////////
VOID TransferPDA2PSD( PPRINTINFO pPI) { if (pPI->pPSD && pPI->pPDA) { pPI->pPSD->hDevMode = pPI->pPDA->hDevMode; pPI->pPSD->hDevNames = pPI->pPDA->hDevNames; } }
/*========================================================================*/ /* Ansi->Unicode Thunk routines */ /*========================================================================*/
////////////////////////////////////////////////////////////////////////////
//
// ThunkPageSetupDlg
//
////////////////////////////////////////////////////////////////////////////
BOOL ThunkPageSetupDlg( PPRINTINFO pPI, LPPAGESETUPDLGA pPSDA) { LPPRINTDLGA pPDA;
if (!pPSDA) { StoreExtendedError(CDERR_INITIALIZATION); return (FALSE); }
if (pPSDA->lStructSize != sizeof(PAGESETUPDLGA)) { StoreExtendedError(CDERR_STRUCTSIZE); return (FALSE); }
if ((pPSDA->Flags & PSD_RETURNDEFAULT) && (pPSDA->hDevNames || pPSDA->hDevMode)) { StoreExtendedError(PDERR_RETDEFFAILURE); return (FALSE); }
//
// Reset the size of the pPSD structure to the UNICODE size and
// save it in the pPI structure.
//
// NOTE: This must be reset back to the ANSI size before
// returning to the caller.
//
pPSDA->lStructSize = sizeof(PAGESETUPDLGW); pPI->pPSD = (LPPAGESETUPDLG)pPSDA; pPI->ApiType = COMDLG_ANSI;
//
// Create the ANSI version of the print dialog structure.
//
if (pPDA = GlobalAlloc(GPTR, sizeof(PRINTDLGA))) { pPI->pPDA = pPDA;
pPDA->lStructSize = sizeof(PRINTDLGA); pPDA->hwndOwner = pPSDA->hwndOwner; pPDA->Flags = PD_PAGESETUP | (pPSDA->Flags & (PSD_NOWARNING | PSD_SHOWHELP | PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGESETUPTEMPLATE | PSD_ENABLEPAGESETUPTEMPLATEHANDLE | CD_WX86APP | PSD_NONETWORKBUTTON)); pPDA->hInstance = pPSDA->hInstance; pPDA->lCustData = pPSDA->lCustData; pPDA->lpfnSetupHook = pPSDA->lpfnPageSetupHook; pPDA->lpSetupTemplateName = pPSDA->lpPageSetupTemplateName; pPDA->hSetupTemplate = pPSDA->hPageSetupTemplate;
pPDA->hDevMode = pPSDA->hDevMode; pPDA->hDevNames = pPSDA->hDevNames; } else { StoreExtendedError(CDERR_MEMALLOCFAILURE); return (FALSE); }
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// FreeThunkPageSetupDlg
//
////////////////////////////////////////////////////////////////////////////
VOID FreeThunkPageSetupDlg( PPRINTINFO pPI) { //
// Reset the size of the pPSD structure to the correct value.
//
if (pPI->pPSD) { pPI->pPSD->lStructSize = sizeof(PAGESETUPDLGA); }
//
// Free the ANSI print dialog structure.
//
if (pPI->pPDA) { GlobalFree(pPI->pPDA); pPI->pPDA = NULL; } }
////////////////////////////////////////////////////////////////////////////
//
// ThunkPrintDlg
//
////////////////////////////////////////////////////////////////////////////
BOOL ThunkPrintDlg( PPRINTINFO pPI, LPPRINTDLGA pPDA) { LPPRINTDLGW pPDW; LPDEVMODEA pDMA; DWORD cbLen;
if (!pPDA) { StoreExtendedError(CDERR_INITIALIZATION); return (FALSE); }
if (pPDA->lStructSize != sizeof(PRINTDLGA)) { StoreExtendedError(CDERR_STRUCTSIZE); return (FALSE); }
if (!(pPDW = GlobalAlloc(GPTR, sizeof(PRINTDLGW)))) { StoreExtendedError(CDERR_MEMALLOCFAILURE); return (FALSE); }
//
// IN-only constant stuff.
//
pPDW->lStructSize = sizeof(PRINTDLGW); pPDW->hwndOwner = pPDA->hwndOwner; pPDW->hInstance = pPDA->hInstance; pPDW->lpfnPrintHook = pPDA->lpfnPrintHook; pPDW->lpfnSetupHook = pPDA->lpfnSetupHook; pPDW->hPrintTemplate = pPDA->hPrintTemplate; pPDW->hSetupTemplate = pPDA->hSetupTemplate;
//
// IN-OUT Variable Structs.
//
if ((pPDA->hDevMode) && (pDMA = GlobalLock(pPDA->hDevMode))) { //
// Make sure the device name in the devmode is not too long such that
// it has overwritten the other devmode fields.
//
if ((pDMA->dmSize < MIN_DEVMODE_SIZEA) || (lstrlenA(pDMA->dmDeviceName) > CCHDEVICENAME)) { pPDW->hDevMode = NULL; } else { pPDW->hDevMode = GlobalAlloc( GHND, sizeof(DEVMODEW) + pDMA->dmDriverExtra ); } GlobalUnlock(pPDA->hDevMode); } else { pPDW->hDevMode = NULL; }
//
// Thunk Device Names A => W
//
pPDW->hDevNames = NULL; if (pPDA->hDevNames) { // ignore the error case since we can't handle it either way.
HRESULT hr = ThunkDevNamesA2W(pPDA->hDevNames, &pPDW->hDevNames); ASSERT(SUCCEEDED(hr)); }
//
// IN-only constant strings.
//
// Init Print TemplateName constant.
//
if ((pPDA->Flags & PD_ENABLEPRINTTEMPLATE) && (pPDA->lpPrintTemplateName)) { //
// See if it's a string or an integer.
//
if (!IS_INTRESOURCE(pPDA->lpPrintTemplateName)) { //
// String.
//
cbLen = lstrlenA(pPDA->lpPrintTemplateName) + 1; if (!(pPDW->lpPrintTemplateName = GlobalAlloc( GPTR, (cbLen * sizeof(WCHAR)) ))) { StoreExtendedError(CDERR_MEMALLOCFAILURE); return (FALSE); } else { pPI->fPrintTemplateAlloc = TRUE; SHAnsiToUnicode(pPDA->lpPrintTemplateName,(LPWSTR)pPDW->lpPrintTemplateName, cbLen); } } else { //
// Integer.
//
(DWORD_PTR)pPDW->lpPrintTemplateName = (DWORD_PTR)pPDA->lpPrintTemplateName; } } else { pPDW->lpPrintTemplateName = NULL; }
//
// Init Print Setup TemplateName constant.
//
if ((pPDA->Flags & PD_ENABLESETUPTEMPLATE) && (pPDA->lpSetupTemplateName)) { //
// See if it's a string or an integer.
//
if (!IS_INTRESOURCE(pPDA->lpSetupTemplateName)) { //
// String.
//
cbLen = lstrlenA(pPDA->lpSetupTemplateName) + 1; if (!(pPDW->lpSetupTemplateName = GlobalAlloc( GPTR, (cbLen * sizeof(WCHAR)) ))) { StoreExtendedError(CDERR_MEMALLOCFAILURE); return (FALSE); } else { pPI->fSetupTemplateAlloc = TRUE; SHAnsiToUnicode(pPDA->lpSetupTemplateName,(LPWSTR)pPDW->lpSetupTemplateName,cbLen); } } else { //
// Integer.
//
(DWORD_PTR)pPDW->lpSetupTemplateName = (DWORD_PTR)pPDA->lpSetupTemplateName; } } else { pPDW->lpSetupTemplateName = NULL; }
pPI->pPD = pPDW; pPI->pPDA = pPDA; pPI->ApiType = COMDLG_ANSI;
return (TRUE); }
////////////////////////////////////////////////////////////////////////////
//
// FreeThunkPrintDlg
//
////////////////////////////////////////////////////////////////////////////
VOID FreeThunkPrintDlg( PPRINTINFO pPI) { LPPRINTDLGW pPDW = pPI->pPD;
if (!pPDW) { return; }
if (pPDW->hDevNames) { GlobalFree(pPDW->hDevNames); }
if (pPDW->hDevMode) { GlobalFree(pPDW->hDevMode); }
if (pPI->fPrintTemplateAlloc) { GlobalFree((LPWSTR)(pPDW->lpPrintTemplateName)); }
if (pPI->fSetupTemplateAlloc) { GlobalFree((LPWSTR)(pPDW->lpSetupTemplateName)); }
GlobalFree(pPDW); pPI->pPD = NULL; }
////////////////////////////////////////////////////////////////////////////
//
// ThunkPrintDlgA2W
//
////////////////////////////////////////////////////////////////////////////
VOID ThunkPrintDlgA2W( PPRINTINFO pPI) { LPPRINTDLGW pPDW = pPI->pPD; LPPRINTDLGA pPDA = pPI->pPDA;
//
// Copy info A => W
//
pPDW->hDC = pPDA->hDC; pPDW->Flags = pPDA->Flags; pPDW->nFromPage = pPDA->nFromPage; pPDW->nToPage = pPDA->nToPage; pPDW->nMinPage = pPDA->nMinPage; pPDW->nMaxPage = pPDA->nMaxPage; pPDW->nCopies = pPDA->nCopies; pPDW->lCustData = pPDA->lCustData; pPDW->lpfnPrintHook = pPDA->lpfnPrintHook; pPDW->lpfnSetupHook = pPDA->lpfnSetupHook;
//
// Thunk Device Names A => W
//
if (pPDA->hDevNames) { // ignore the error case since we can't handle it either way.
HRESULT hr = ThunkDevNamesA2W(pPDA->hDevNames, &pPDW->hDevNames); ASSERT(SUCCEEDED(hr)); }
//
// Thunk Device Mode A => W
//
if (pPDA->hDevMode && pPDW->hDevMode) { LPDEVMODEW pDMW = GlobalLock(pPDW->hDevMode); LPDEVMODEA pDMA = GlobalLock(pPDA->hDevMode);
ThunkDevModeA2W(pDMA, pDMW);
GlobalUnlock(pPDW->hDevMode); GlobalUnlock(pPDA->hDevMode); } }
////////////////////////////////////////////////////////////////////////////
//
// ThunkPrintDlgW2A
//
////////////////////////////////////////////////////////////////////////////
VOID ThunkPrintDlgW2A( PPRINTINFO pPI) { LPPRINTDLGA pPDA = pPI->pPDA; LPPRINTDLGW pPDW = pPI->pPD;
//
// Copy info W => A
//
pPDA->hDC = pPDW->hDC; pPDA->Flags = pPDW->Flags; pPDA->nFromPage = pPDW->nFromPage; pPDA->nToPage = pPDW->nToPage; pPDA->nMinPage = pPDW->nMinPage; pPDA->nMaxPage = pPDW->nMaxPage; pPDA->nCopies = pPDW->nCopies; pPDA->lCustData = pPDW->lCustData; pPDA->lpfnPrintHook = pPDW->lpfnPrintHook; pPDA->lpfnSetupHook = pPDW->lpfnSetupHook;
//
// Thunk Device Names W => A
//
if (pPDW->hDevNames) { // ignore the error case since we can't handle it either way.
HRESULT hr = ThunkDevNamesW2A(pPDW->hDevNames, &pPDA->hDevNames); ASSERT(SUCCEEDED(hr)); }
//
// Thunk Device Mode W => A
//
if (pPDW->hDevMode) { LPDEVMODEW pDMW = GlobalLock(pPDW->hDevMode); LPDEVMODEA pDMA;
if (pPDA->hDevMode) { HANDLE handle; handle = GlobalReAlloc( pPDA->hDevMode, sizeof(DEVMODEA) + pDMW->dmDriverExtra, GHND ); //Make sure realloc succeeded.
if (handle) { pPDA->hDevMode = handle; } else { //Realloc didn't succeed. Free the memory occupied
pPDA->hDevMode = GlobalFree(pPDA->hDevMode); }
} else { pPDA->hDevMode = GlobalAlloc( GHND, sizeof(DEVMODEA) + pDMW->dmDriverExtra ); } if (pPDA->hDevMode) { pDMA = GlobalLock(pPDA->hDevMode); ThunkDevModeW2A(pDMW, pDMA); GlobalUnlock(pPDA->hDevMode); } GlobalUnlock(pPDW->hDevMode); } }
////////////////////////////////////////////////////////////////////////////
//
// ThunkDevModeA2W
//
////////////////////////////////////////////////////////////////////////////
VOID ThunkDevModeA2W( LPDEVMODEA pDMA, LPDEVMODEW pDMW) { LPDEVMODEA pDevModeA;
if (!pDMA || !pDMW) { return; }
//
// Make sure the device name in the devmode is not too long such that
// it has overwritten the other devmode fields.
//
if ((pDMA->dmSize < MIN_DEVMODE_SIZEA) || (lstrlenA(pDMA->dmDeviceName) > CCHDEVICENAME)) { return; }
//
// We need to create a temporary ANSI that is a known size.
// The problem is if we are being called from WOW, the WOW
// app could be either a Windows 3.1 or 3.0 app. The size
// of the devmode structure was different for both of these
// versions compared to the DEVMODE structure in NT.
// By copying the ANSI devmode to one we allocate, then we
// can access all of the fields (26 currently) without causing
// an access violation.
//
pDevModeA = GlobalAlloc(GPTR, sizeof(DEVMODEA) + pDMA->dmDriverExtra); if (!pDevModeA) { return; }
CopyMemory( (LPBYTE)pDevModeA, (LPBYTE)pDMA, min(sizeof(DEVMODEA), pDMA->dmSize) );
CopyMemory( (LPBYTE)pDevModeA + sizeof(DEVMODEA), (LPBYTE)pDMA + pDMA->dmSize, pDMA->dmDriverExtra );
//
// Now we can thunk the contents of the ANSI structure to the
// Unicode structure.
//
SHAnsiToUnicode((LPSTR)pDevModeA->dmDeviceName,(LPWSTR)pDMW->dmDeviceName,CCHDEVICENAME );
pDMW->dmSpecVersion = pDevModeA->dmSpecVersion; pDMW->dmDriverVersion = pDevModeA->dmDriverVersion; pDMW->dmSize = sizeof(DEVMODEW); pDMW->dmDriverExtra = pDevModeA->dmDriverExtra; pDMW->dmFields = pDevModeA->dmFields; pDMW->dmOrientation = pDevModeA->dmOrientation; pDMW->dmPaperSize = pDevModeA->dmPaperSize; pDMW->dmPaperLength = pDevModeA->dmPaperLength; pDMW->dmPaperWidth = pDevModeA->dmPaperWidth; pDMW->dmScale = pDevModeA->dmScale; pDMW->dmCopies = pDevModeA->dmCopies; pDMW->dmDefaultSource = pDevModeA->dmDefaultSource; pDMW->dmPrintQuality = pDevModeA->dmPrintQuality; pDMW->dmColor = pDevModeA->dmColor; pDMW->dmDuplex = pDevModeA->dmDuplex; pDMW->dmYResolution = pDevModeA->dmYResolution; pDMW->dmTTOption = pDevModeA->dmTTOption; pDMW->dmCollate = pDevModeA->dmCollate;
SHAnsiToUnicode((LPSTR)pDevModeA->dmFormName,(LPWSTR)pDMW->dmFormName,CCHFORMNAME );
pDMW->dmLogPixels = pDevModeA->dmLogPixels; pDMW->dmBitsPerPel = pDevModeA->dmBitsPerPel; pDMW->dmPelsWidth = pDevModeA->dmPelsWidth; pDMW->dmPelsHeight = pDevModeA->dmPelsHeight; pDMW->dmDisplayFlags = pDevModeA->dmDisplayFlags; pDMW->dmDisplayFrequency = pDevModeA->dmDisplayFrequency;
pDMW->dmICMMethod = pDevModeA->dmICMMethod; pDMW->dmICMIntent = pDevModeA->dmICMIntent; pDMW->dmMediaType = pDevModeA->dmMediaType; pDMW->dmDitherType = pDevModeA->dmDitherType;
pDMW->dmReserved1 = pDevModeA->dmReserved1; pDMW->dmReserved2 = pDevModeA->dmReserved2;
pDMW->dmPanningWidth = pDevModeA->dmPanningWidth; pDMW->dmPanningHeight = pDevModeA->dmPanningHeight;
CopyMemory( (pDMW + 1), (pDevModeA + 1), pDevModeA->dmDriverExtra );
//
// Free the memory we allocated.
//
GlobalFree(pDevModeA); }
////////////////////////////////////////////////////////////////////////////
//
// ThunkDevModeW2A
//
////////////////////////////////////////////////////////////////////////////
VOID ThunkDevModeW2A( LPDEVMODEW pDMW, LPDEVMODEA pDMA) { if (!pDMW || !pDMA) { return; }
SHUnicodeToAnsi((LPWSTR)pDMW->dmDeviceName,(LPSTR)pDMA->dmDeviceName,CCHDEVICENAME);
pDMA->dmSpecVersion = pDMW->dmSpecVersion; pDMA->dmDriverVersion = pDMW->dmDriverVersion; pDMA->dmSize = sizeof(DEVMODEA); pDMA->dmDriverExtra = pDMW->dmDriverExtra; pDMA->dmFields = pDMW->dmFields; pDMA->dmOrientation = pDMW->dmOrientation; pDMA->dmPaperSize = pDMW->dmPaperSize; pDMA->dmPaperLength = pDMW->dmPaperLength; pDMA->dmPaperWidth = pDMW->dmPaperWidth; pDMA->dmScale = pDMW->dmScale; pDMA->dmCopies = pDMW->dmCopies; pDMA->dmDefaultSource = pDMW->dmDefaultSource; pDMA->dmPrintQuality = pDMW->dmPrintQuality; pDMA->dmColor = pDMW->dmColor; pDMA->dmDuplex = pDMW->dmDuplex; pDMA->dmYResolution = pDMW->dmYResolution; pDMA->dmTTOption = pDMW->dmTTOption; pDMA->dmCollate = pDMW->dmCollate;
SHUnicodeToAnsi((LPWSTR)pDMW->dmFormName,(LPSTR)pDMA->dmFormName,CCHFORMNAME);
pDMA->dmLogPixels = pDMW->dmLogPixels; pDMA->dmBitsPerPel = pDMW->dmBitsPerPel; pDMA->dmPelsWidth = pDMW->dmPelsWidth; pDMA->dmPelsHeight = pDMW->dmPelsHeight; pDMA->dmDisplayFlags = pDMW->dmDisplayFlags; pDMA->dmDisplayFrequency = pDMW->dmDisplayFrequency;
pDMA->dmICMMethod = pDMW->dmICMMethod; pDMA->dmICMIntent = pDMW->dmICMIntent; pDMA->dmMediaType = pDMW->dmMediaType; pDMA->dmDitherType = pDMW->dmDitherType;
pDMA->dmReserved1 = pDMW->dmReserved1; pDMA->dmReserved2 = pDMW->dmReserved2;
pDMA->dmPanningWidth = pDMW->dmPanningWidth; pDMA->dmPanningHeight = pDMW->dmPanningHeight;
CopyMemory( (pDMA + 1), (pDMW + 1), pDMA->dmDriverExtra ); }
////////////////////////////////////////////////////////////////////////////
//
// AllocateUnicodeDevMode
//
// Purpose: Allocates a Unicode devmode structure, and calls
// the thunk function to fill it in.
//
// Parameters: LPDEVMODEA pANSIDevMode
//
// Return: LPDEVMODEW - pointer to new devmode if successful
// NULL if not.
//
////////////////////////////////////////////////////////////////////////////
LPDEVMODEW AllocateUnicodeDevMode( LPDEVMODEA pANSIDevMode) { int iSize; LPDEVMODEW pUnicodeDevMode;
//
// Check for NULL pointer.
//
if (!pANSIDevMode) { return (NULL); }
//
// Determine output structure size. This has two components: the
// DEVMODEW structure size, plus any private data area. The latter
// is only meaningful when a structure is passed in.
//
iSize = sizeof(DEVMODEW);
iSize += pANSIDevMode->dmDriverExtra;
pUnicodeDevMode = GlobalAlloc(GPTR, iSize);
if (!pUnicodeDevMode) { return (NULL); }
//
// Now call the thunk routine to copy the ANSI devmode to the
// Unicode devmode.
//
ThunkDevModeA2W(pANSIDevMode, pUnicodeDevMode);
//
// Return the pointer.
//
return (pUnicodeDevMode); }
////////////////////////////////////////////////////////////////////////////
//
// AllocateAnsiDevMode
//
// Purpose: Allocates a Ansi devmode structure, and calls
// the thunk function to fill it in.
//
// Parameters: LPDEVMODEW pUnicodeDevMode
//
// Return: LPDEVMODEA - pointer to new devmode if successful
// NULL if not.
//
////////////////////////////////////////////////////////////////////////////
LPDEVMODEA AllocateAnsiDevMode( LPDEVMODEW pUnicodeDevMode) { int iSize; LPDEVMODEA pANSIDevMode;
//
// Check for NULL pointer.
//
if (!pUnicodeDevMode) { return (NULL); }
//
// Determine output structure size. This has two components: the
// DEVMODEW structure size, plus any private data area. The latter
// is only meaningful when a structure is passed in.
//
iSize = sizeof(DEVMODEA);
iSize += pUnicodeDevMode->dmDriverExtra;
pANSIDevMode = GlobalAlloc(GPTR, iSize);
if (!pANSIDevMode) { return (NULL); }
//
// Now call the thunk routine to copy the Unicode devmode to the
// ANSI devmode.
//
ThunkDevModeW2A(pUnicodeDevMode, pANSIDevMode);
//
// Return the pointer.
//
return (pANSIDevMode); }
////////////////////////////////////////////////////////////////////////////
//
// Ssync_ANSI_UNICODE_PD_For_WOW
//
// Function to allow NT WOW to keep the ANSI & UNICODE versions of
// the CHOOSEFONT structure in ssync as required by many 16-bit apps.
// See notes for Ssync_ANSI_UNICODE_Struct_For_WOW() in dlgs.c.
//
////////////////////////////////////////////////////////////////////////////
VOID Ssync_ANSI_UNICODE_PD_For_WOW( HWND hDlg, BOOL f_ANSI_to_UNICODE) { PPRINTINFO pPI;
if (pPI = (PPRINTINFO)GetProp(hDlg, PRNPROP)) { if (pPI->pPD && pPI->pPDA) { if (f_ANSI_to_UNICODE) { ThunkPrintDlgA2W(pPI); } else { ThunkPrintDlgW2A(pPI); } } } }
////////////////////////////////////////////////////////////////////////////
//
// SetCopiesEditWidth
//
// Adjust the width of the copies edit control using the current
// font and the scroll bar width. This is necessary to handle the
// the up down control from encroching on the space in the edit
// control when we are in High Contrast (extra large) mode.
//
////////////////////////////////////////////////////////////////////////////
VOID SetCopiesEditWidth( HWND hDlg, HWND hControl) { HDC hDC = NULL; LONG MaxDigitExtant = 0; LONG EditControlWidth = 0; LONG CurrentWidth = 0; UINT i = 0; INT aDigitWidth[10]; WINDOWPLACEMENT WndPl;
//
// Acquire the edit controls device context.
//
hDC = GetDC( hControl );
if (hDC) { //
// Determine max width of the digit group.
//
if (GetCharWidth32( hDC, TEXT('0'), TEXT('9'), aDigitWidth)) { for (i = 0; i < ARRAYSIZE(aDigitWidth); i++) { if (aDigitWidth[i] > MaxDigitExtant) { MaxDigitExtant = aDigitWidth[i]; } }
//
// Get the edit control placement.
//
WndPl.length = sizeof( WndPl );
if (GetWindowPlacement( hControl, &WndPl )) { //
// Calculate the edit control current width.
//
EditControlWidth = MaxDigitExtant * COPIES_EDIT_SIZE;
//
// Calculate the current width of the edit control.
//
CurrentWidth = WndPl.rcNormalPosition.right - WndPl.rcNormalPosition.left;
//
// Set the new position of the edit control.
//
WndPl.rcNormalPosition.left = WndPl.rcNormalPosition.left - (EditControlWidth - CurrentWidth);
//
// Place the control.
//
SetWindowPlacement( hControl, &WndPl ); } }
//
// Release the device context.
//
ReleaseDC( hControl, hDC ); } }
////////////////////////////////////////////////////////////////////////////
//
// CountDigits
//
// Count how many digits is needed for a specific number
//
////////////////////////////////////////////////////////////////////////////
WORD CountDigits( DWORD dwNumber) { WORD cDigits = 0;
if(dwNumber == 0) { return 1; }
while(dwNumber > 0) { cDigits++; dwNumber /= 10; }
return cDigits++; }
////////////////////////////////////////////////////////////////////////////
//
// ComboBoxGetLBText
//
// A wrapper function for getting combobox label text.
//
////////////////////////////////////////////////////////////////////////////
HRESULT ComboBoxGetLBText( IN HWND hComboBox, IN DWORD dwIndex, IN LPTSTR pszText, IN DWORD cchText) { HRESULT hr = S_OK; LRESULT lResult = CB_ERR;
if(!pszText || cchText == 0) { hr = E_INVALIDARG; }
if(SUCCEEDED(hr)) { //
// Get the length of the text first
//
lResult = SendMessage( hComboBox, CB_GETLBTEXTLEN, (WPARAM)dwIndex, 0L );
if(lResult == CB_ERR) { hr = E_FAIL; } }
if(SUCCEEDED(hr)) { if((DWORD)lResult < cchText) { //
// Buffer is large enough, now get the label text
//
lResult = SendMessage( hComboBox, CB_GETLBTEXT, (WPARAM)dwIndex, (LPARAM)pszText ); hr = (lResult != CB_ERR) ? S_OK : E_FAIL; } else { //
// In case of the buffer size less than needed, we try to truncate
// the label text into the buffer.
//
LPTSTR pszBuffer = NULL;
pszBuffer = (LPTSTR)LocalAlloc(LPTR, (lResult + 1) * sizeof(TCHAR)); if(pszBuffer) { //
// Get the label text
//
lResult = SendMessage( hComboBox, CB_GETLBTEXT, (WPARAM)dwIndex, (LPARAM)pszBuffer );
if(lResult != CB_ERR) { hr = StringCchCopy(pszText, cchText, pszBuffer); } else { hr = E_FAIL; } } else { hr = E_OUTOFMEMORY; }
//
// Cleanup
//
LocalFree(pszBuffer); } }
return hr; }
|