/*++ 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); #ifdef UNICODE //////////////////////////////////////////////////////////////////////////// // // 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); } #else //////////////////////////////////////////////////////////////////////////// // // PrintDlgW // // Stub UNICODE function for PrintDlg when this code is built ANSI. // //////////////////////////////////////////////////////////////////////////// BOOL WINAPI PrintDlgW( LPPRINTDLGW pPDW) { SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return (FALSE); } #endif //////////////////////////////////////////////////////////////////////////// // // 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, SCRATCHBUF_SIZE); } 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, sizeof(szWarning), NULL); } else { CDLoadString(g_hinst, iszWarning, szWarning, SCRATCHBUF_SIZE); } 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; #ifndef WINNT LPCTSTR pDN_Device = NULL; TCHAR szDev[2]; #endif 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); } #ifdef WINNT // // 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); } #endif // // 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); #ifdef UNICODE // // 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; } #endif #ifndef WINNT // // This should NOT be in NT. The device name cannot be longer than // 32 characters, so it may be truncated. If we look for it in the // registry and it's supposed to be larger than 32 characters, then // we won't find it and we'll fail. // // LATER: It probably shouldn't be in WIN95 either, but I'll leave // it for now. // if (pPD->hDevMode) { if (!(pDM = GlobalLock(pPD->hDevMode))) { StoreExtendedError(CDERR_MEMLOCKFAILURE); goto PrintDlgX_DisplayWarning; } } if (pPD->hDevNames) { if (!(pDN = GlobalLock(pPD->hDevNames))) { if (pDM) { GlobalUnlock(pPD->hDevMode); } StoreExtendedError(CDERR_MEMLOCKFAILURE); goto PrintDlgX_DisplayWarning; } else { if (pDN->wDeviceOffset) { pDN_Device = (LPCTSTR)pDN + pDN->wDeviceOffset; } } } if (pDM && pDM->dmDeviceName[0]) { pDM->dmDeviceName[CCHDEVICENAME - 1] = 0; GetProfileString(szTextDevices, pDM->dmDeviceName, szTextNull, szDev, 2); if (!szDev[0]) { GlobalUnlock(pPD->hDevMode); if (pDN) { GlobalUnlock(pPD->hDevNames); } StoreExtendedError(PDERR_PRINTERNOTFOUND); goto PrintDlgX_DisplayWarning; } } if (pDN_Device && pDN_Device[0]) { GetProfileString(szTextDevices, pDN_Device, szTextNull, szDev, 2); if (!szDev[0]) { if (pDM) { GlobalUnlock(pPD->hDevMode); } GlobalUnlock(pPD->hDevNames); StoreExtendedError(PDERR_PRINTERNOTFOUND); goto PrintDlgX_DisplayWarning; } } if (pDM) { GlobalUnlock(pPD->hDevMode); } if (pDN) { GlobalUnlock(pPD->hDevNames); } #endif 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) < MAX_PRINTERNAME)) { lstrcpy(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); } #ifdef UNICODE 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. // } } #endif cbNeeded = DocumentProperties( pPD->hwndOwner, pPI->hCurPrinter, (pPI->pCurPrinter) ? pPI->pCurPrinter->pPrinterName : NULL, NULL, NULL, 0 ); #ifdef UNICODE GotWOWDMSize: #endif if ((cbNeeded > 0) && (pPD->hDevMode = GlobalAlloc(GHND, cbNeeded))) { BOOL fSuccess = FALSE; if (pDM = GlobalLock(pPD->hDevMode)) { #ifdef UNICODE if (pPI->bUseExtDeviceMode && !hDevMode) { CopyMemory(pDM, pDevMode, cbNeeded); fSuccess = TRUE; goto GotNewWOWDM; } #endif fSuccess = DocumentProperties( pPD->hwndOwner, pPI->hCurPrinter, (pPI->pCurPrinter) ? pPI->pCurPrinter->pPrinterName : NULL, pDM, // out pDevMode, // in DM_MODIFY | DM_COPY ) == IDOK; #ifdef UNICODE GotNewWOWDM: #endif 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, SCRATCHBUF_SIZE); // // 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) { // // Display an error message and ignore the return code // since we don't care. // ShowErrorMessage(pPD, pPI, NULL); } return (nResult > 0); } #ifdef UNICODE //////////////////////////////////////////////////////////////////////////// // // 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); } #else //////////////////////////////////////////////////////////////////////////// // // PageSetupDlgW // // Stub UNICODE function for PageSetupDlg when this code is built ANSI. // //////////////////////////////////////////////////////////////////////////// BOOL WINAPI PageSetupDlgW( LPPAGESETUPDLGW pPSDW) { SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return (FALSE); } #endif //////////////////////////////////////////////////////////////////////////// // // 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; #ifdef UNICODE UINT uiWOWFlag = 0; #endif // // 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); #ifdef UNICODE if (IS16BITWOWAPP(pPD)) { uiWOWFlag = SCDLG_16BIT; } fGotInput = (BOOL)DialogBoxIndirectParamAorW( hInstance, (LPDLGTEMPLATE)hDlgTemplate, pPD->hwndOwner, PrintDlgProc, (LPARAM)pPI, uiWOWFlag ); #else fGotInput = (BOOL)DialogBoxIndirectParam( hInstance, (LPDLGTEMPLATE)hDlgTemplate, pPD->hwndOwner, PrintDlgProc, (LPARAM)pPI ); #endif 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; #ifdef UNICODE UINT uiWOWFlag = 0; #endif // // 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); #ifdef UNICODE if (IS16BITWOWAPP(pPD)) { uiWOWFlag = SCDLG_16BIT; } fGotInput = (BOOL)DialogBoxIndirectParamAorW( hInstance, (LPDLGTEMPLATE)hDlgTemplate, pPD->hwndOwner, PrintSetupDlgProc, (LPARAM)pPI, uiWOWFlag ); #else fGotInput = (BOOL)DialogBoxIndirectParam( hInstance, (LPDLGTEMPLATE)hDlgTemplate, pPD->hwndOwner, PrintSetupDlgProc, (LPARAM)pPI ); #endif 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); #ifdef UNICODE if (pPI->ApiType == COMDLG_ANSI) { ThunkPrintDlgW2A(pPI); } #endif if ((bResult = (*lpfnPrintHook)(hDlg, wMsg, wParam, lParam))) { #ifdef UNICODE if (pPI->ApiType == COMDLG_ANSI) { ThunkPrintDlgA2W(pPI); } #endif 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); #ifndef WINNT msgHELPA = RegisterWindowMessage(szCommdlgHelp); #endif 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; #ifdef WINNT 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 ); } } #endif // // 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 ); #ifdef WINNT // // 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); } } #endif } 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 { #ifdef WINNT 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); } #else WNetConnectionDialog(hDlg, RESOURCETYPE_PRINT); #endif break; } case ( ID_BOTH_P_HELP ) : // Help button { #ifdef UNICODE if (pPI->ApiType == COMDLG_ANSI) { if (msgHELPA && pPD->hwndOwner) { SendMessage( pPD->hwndOwner, msgHELPA, (WPARAM)hDlg, (DWORD_PTR)pPI->pPDA ); } } else #endif { 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); } #ifdef UNICODE if (pPD->Flags & CD_WOWAPP) { UpdateSpoolerInfo(pPI); } #endif // 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); #ifdef UNICODE 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 #endif { 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); #ifndef WINNT msgHELPA = RegisterWindowMessage(szCommdlgHelp); #endif 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 { #ifdef WINNT 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); } #else WNetConnectionDialog(hDlg, RESOURCETYPE_PRINT); #endif break; } case ( ID_BOTH_P_HELP ) : // Help button { #ifdef UNICODE if (pPI->ApiType == COMDLG_ANSI) { if (msgHELPA && pPD->hwndOwner) { SendMessage( pPD->hwndOwner, msgHELPA, (WPARAM)hDlg, (LPARAM)pPI->pPDA ); } } else #endif { 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); #ifdef UNICODE if (pPD->Flags & CD_WOWAPP) { UpdateSpoolerInfo(pPI); } #endif } 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; 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 ); 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))) { #ifdef WINNT // // 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); #else pPD->hDevMode = PrintGetDevMode( 0, NULL, (LPTSTR)pDN + pDN->wDeviceOffset, NULL ); #endif 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 ); #ifndef WINNT if (!lpEditMarginProc) { WNDCLASSEX wc; wc.cbSize = sizeof(wc); GetClassInfoEx(NULL, TEXT("edit"), &wc); lpEditMarginProc = wc.lpfnWndProc; GetClassInfoEx(NULL, TEXT("static"), &wc); lpStaticProc = wc.lpfnWndProc; } #endif // // 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); #ifdef WINNT // // 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); #endif } } 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); } #ifdef WINNT 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); } } #endif 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); } #ifndef WINNT // // This is NOT desirable. Most apps use a very high number for // their max page, so it looks very strange. // else { TCHAR szAll[32]; TCHAR szBuf[64]; if (pPD->nMinPage != pPD->nMaxPage) { if (pPD->nMaxPage != 0xFFFF) { if (CDLoadString(g_hinst, iszPrintRangeAll, szAll, 32)) { wsprintf( szBuf, szAll, (DWORD)pPD->nMaxPage - (DWORD)pPD->nMinPage + 1 ); SetDlgItemText(hDlg, ID_PRINT_R_ALL, szBuf); } else { StoreExtendedError(CDERR_LOADSTRFAILURE); return (0xFFFFFFFF); } } } } #endif } 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); #ifdef UNICODE 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 #endif { 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)) { #ifdef WINNT AddNetButton( hDlg, ((pPD->Flags & PD_ENABLESETUPTEMPLATE) ? pPD->hInstance : g_hinst), FILE_BOTTOM_MARGIN, (pPD->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLESETUPTEMPLATEHANDLE)) ? FALSE : TRUE, FALSE, TRUE ); #endif // // The button can be added in two ways - // statically (they have it predefined in their template) and // dynamically (successful call to AddNetButton). // #ifdef WINNT if (!IsNetworkInstalled()) #else if (!GetSystemMetrics(SM_NETWORK)) #endif { hCtl = GetDlgItem(hDlg, ID_BOTH_P_NETWORK); EnableWindow(hCtl, FALSE); ShowWindow(hCtl, SW_HIDE); } } #ifdef WINNT 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); } } #endif // // 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); #ifdef UNICODE 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 #endif { 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)) ) { #ifdef UNICODE // // 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); } #endif 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, 32); CDLoadString(g_hinst, iszMillimeters, cIntlMeasure, 5); break; } case ( PSD_INTHOUSANDTHSOFINCHES ) : { CDLoadString(g_hinst, iszMarginsInches, szMars, 32); CDLoadString(g_hinst, iszInches, cIntlMeasure, 5); 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; wsprintf( szText, lFract ? TEXT("%lu%c%02lu") : TEXT("%lu"), lValue / 100, cIntlDecimal, lFract ); break; } case ( PSD_INTHOUSANDTHSOFINCHES ) : { lFract = lValue % 1000; wsprintf( 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) { TCHAR szText[16]; TCHAR *pText; TCHAR *pFrac; GetWindowText(hEdt, szText, ARRAYSIZE(szText)); szText[ARRAYSIZE(szText)-1] = 0; *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; } } StrCatBuff(szText, TEXT("000"), ARRAYSIZE(szText)); 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, MAX_DEV_SECT)) { goto LoadStrFailure; } StrCatBuff(psBanner, (LPTSTR)szSysPrn, cchBanner); StrCatBuff(psBanner, (LPTSTR)pDN + pDN->wDeviceOffset, cchBanner); StrCatBuff(psBanner, (LPTSTR)TEXT(")"), cchBanner); } else { TCHAR szPrnOnPort[64]; if (!CDLoadString(g_hinst, iszPrnOnPort, szPrnOnPort, 64)) { goto LoadStrFailure; } StrCatBuff(psBanner, (LPTSTR)pDN + pDN->wDeviceOffset, cchBanner); StrCatBuff(psBanner, (LPTSTR)szPrnOnPort, cchBanner); StrCatBuff(psBanner, (LPTSTR)pDN + pDN->wOutputOffset, cchBanner); } 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]) ) { wsprintf(szBuf, TEXT("%ld dpi x %ld dpi"), xRes, yRes); } else { wsprintf(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, 64)) { 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; SendMessage( hCtl, CB_GETLBTEXT, (WPARAM)SendMessage(hCtl, CB_GETCURSEL, 0, 0), (LPARAM)(LPTSTR)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, 32); } Length = lstrlen(szText); dwStatus = pPI->pCurPrinter->Status; for (ctr = 0; ctr++ < 32; dwStatus = dwStatus >> 1) { if (dwStatus & 1) { CDLoadString( g_hinst, iszStatusReady + ctr, szText + lstrlen(szText), 32); } } if (szText[Length]) { if (CDLoadString(g_hinst, iszStatusDocumentsWaiting, szJobs, 64)) { wsprintf( szText + lstrlen(szText), szJobs, pPI->pCurPrinter->cJobs ); } } else { CDLoadString(g_hinst, iszStatusReady, szText + Length, 32); } SetDlgItemText(hDlg, ID_BOTH_S_STATUS, szText); UpdateWindow(GetDlgItem(hDlg, ID_BOTH_S_STATUS)); // // ---------------------- Update Type ---------------------- // if (pPI->pCurPrinter->pDriverName) { lstrcpy(szText, pPI->pCurPrinter->pDriverName); } else { szText[0] = CHAR_NULL; } if (pPI->pPD->hDevMode && (pDM = GlobalLock(pPI->pPD->hDevMode))) { if (pDM->dmSpecVersion < 0x0400) { lstrcat(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; lstrcpy(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) { lstrcpy(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; lstrcpy(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 ); #ifndef WINNT if (pDM->dmSpecVersion >= 0x0400) #endif { // pDM->dmFields |= DM_FORMNAME; SendMessage( hCmb, CB_GETLBTEXT, nInd, (LPARAM)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 // //////////////////////////////////////////////////////////////////////////// #ifdef UNICODE 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); } } } #endif //////////////////////////////////////////////////////////////////////////// // // 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. // #ifdef UNICODE if (pPI->bUseExtDeviceMode) { PrintGetExtDeviceMode(hDlg, pPI); } #endif // // 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, MAX_PATH ) ) { // 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)) { lstrcpy(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. // #ifdef WINNT if ( (pPI->ProcessVersion >= 0x40000) || (!GetProfileString( szTextDevices, pPrinterName, szTextNull, szBuffer, MAX_PATH )) || (!(pPortName = StrChr(szBuffer, CHAR_COMMA))) || (!((++pPortName)[0])) ) #endif { // // Get the port name from the PrinterInfo2 structure // for the current printer. // pPortName = pPI->pCurPrinter->pPortName; } } // // 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); lstrcpy((LPTSTR)pDN + pDN->wDriverOffset, szDriver); pDN->wDeviceOffset = pDN->wDriverOffset + lstrlen(szDriver) + 1; lstrcpy((LPTSTR)pDN + pDN->wDeviceOffset, pPrinterName); pDN->wOutputOffset = pDN->wDeviceOffset + lstrlen(pPrinterName) + 1; lstrcpy((LPTSTR)pDN + pDN->wOutputOffset, 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) { lstrcpy((LPTSTR)pDN + pDN->wOutputOffset, szFilePort); } #ifdef UNICODE // // 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; } #endif 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; } #ifndef WINNT if (pDM->dmSpecVersion >= 0x0400) #endif { SendMessage( hWndSize, CB_GETLBTEXT, nInd, (LPARAM)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++) { #ifndef WINNT LPTSTR lpsT3; LPWORD lpwT4; // // Various checks for HP LaserJet and PostScript // driver bugs. // // // Look for duplicate names. // for (lpsT3 = lpsOut1; lpsT3 <= lpsT1; lpsT3 += cchSize1) { if (!lstrcmp(lpsT3, lpsT1)) { break; } } if (lpsT3 != lpsT1) { // // Duplicate found, so ignore. // continue; } // // Look for duplicate values. // for (lpwT4 = lpwOut2; lpwT4 <= lpwT2; lpwT4++) { if (*lpwT4 == *lpwT2) { break; } } if (lpwT4 != lpwT2) { // // Duplicate found, so ignore. // continue; } #endif // // 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; #ifdef UNICODE if (pPI->bUseExtDeviceMode) { PrintGetExtDeviceMode(NULL, pPI); } #endif } 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 // //////////////////////////////////////////////////////////////////////////// #ifdef UNICODE 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); } #endif //////////////////////////////////////////////////////////////////////////// // // 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; #ifdef UNICODE DWORD dwCount; #endif // // If NULL, we can return now. // if (!pPrinters) { return; } #ifdef UNICODE // // 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; } } #endif // // Free the entire block. // GlobalFree(pPI->pPrinters); pPI->pPrinters = NULL; pPI->cPrinters = 0; } //////////////////////////////////////////////////////////////////////////// // // TermPrint // //////////////////////////////////////////////////////////////////////////// VOID TermPrint(void) { #ifdef WINNT Print_UnloadLibraries(); // printnew.cpp #endif } /*========================================================================*/ /* 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; } } #ifdef UNICODE //////////////////////////////////////////////////////////////////////////// // // 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; } } #endif /*========================================================================*/ /* Ansi->Unicode Thunk routines */ /*========================================================================*/ #ifdef UNICODE //////////////////////////////////////////////////////////////////////////// // // 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); } #ifdef WINNT //////////////////////////////////////////////////////////////////////////// // // 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); } } } } #endif #endif //////////////////////////////////////////////////////////////////////////// // // 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++; }