Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

9240 lines
272 KiB

  1. /*++
  2. Copyright (c) 1990-1998, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. prnsetup.c
  5. Abstract:
  6. This module implements the Win32 print dialogs.
  7. Revision History:
  8. --*/
  9. // precompiled headers
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #include "prnsetup.h"
  13. #include "util.h"
  14. //
  15. // The PrintDlgEx routines.
  16. //
  17. extern VOID Print_UnloadLibraries();
  18. extern BOOL Print_NewPrintDlg(PPRINTINFO pPI);
  19. #ifdef UNICODE
  20. ////////////////////////////////////////////////////////////////////////////
  21. //
  22. // PrintDlgA
  23. //
  24. // ANSI entry point for PrintDlg when this code is built UNICODE.
  25. //
  26. ////////////////////////////////////////////////////////////////////////////
  27. BOOL WINAPI PrintDlgA(
  28. LPPRINTDLGA pPDA)
  29. {
  30. PRINTINFO PI;
  31. BOOL bResult = FALSE;
  32. DWORD Flags;
  33. ZeroMemory(&PI, sizeof(PRINTINFO));
  34. if (bResult = ThunkPrintDlg(&PI, pPDA))
  35. {
  36. ThunkPrintDlgA2W(&PI);
  37. Flags = pPDA->Flags;
  38. bResult = PrintDlgX(&PI);
  39. if ((bResult) || (Flags & (PD_ENABLEPRINTHOOK | PD_ENABLESETUPHOOK)))
  40. {
  41. ThunkPrintDlgW2A(&PI);
  42. }
  43. }
  44. FreeThunkPrintDlg(&PI);
  45. return (bResult);
  46. }
  47. #else
  48. ////////////////////////////////////////////////////////////////////////////
  49. //
  50. // PrintDlgW
  51. //
  52. // Stub UNICODE function for PrintDlg when this code is built ANSI.
  53. //
  54. ////////////////////////////////////////////////////////////////////////////
  55. BOOL WINAPI PrintDlgW(
  56. LPPRINTDLGW pPDW)
  57. {
  58. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  59. return (FALSE);
  60. }
  61. #endif
  62. ////////////////////////////////////////////////////////////////////////////
  63. //
  64. // PrintDlg
  65. //
  66. // The PrintDlg function displays a Print dialog box or a Print Setup
  67. // dialog box. The Print dialog box enables the user to specify the
  68. // properties of a particular print job. The Print Setup dialog box
  69. // allows the user to select additional job properties and to configure
  70. // the printer.
  71. //
  72. ////////////////////////////////////////////////////////////////////////////
  73. BOOL WINAPI PrintDlg(
  74. LPPRINTDLG pPD)
  75. {
  76. PRINTINFO PI;
  77. ZeroMemory(&PI, sizeof(PRINTINFO));
  78. PI.pPD = pPD;
  79. PI.ApiType = COMDLG_WIDE;
  80. return ( PrintDlgX(&PI) );
  81. }
  82. ////////////////////////////////////////////////////////////////////////////
  83. //
  84. // ShowErrorMessage
  85. //
  86. // Shows an error message
  87. //
  88. ////////////////////////////////////////////////////////////////////////////
  89. static HRESULT ShowErrorMessage(
  90. IN const PRINTDLG *pPD,
  91. IN const PRINTINFO *pPI,
  92. OUT BOOL *pbTryAgain OPTIONAL
  93. )
  94. {
  95. HRESULT hr = S_OK;
  96. BOOL bTryAgain = FALSE;
  97. BOOL bPrinterAdded = FALSE;
  98. if (!(pPD->Flags & PD_NOWARNING))
  99. {
  100. DWORD dwErr = GetStoredExtendedError();
  101. //
  102. // Only do this for new apps.
  103. //
  104. if ( (pPI->ProcessVersion >= 0x40000) ||
  105. (dwErr == PDERR_NODEFAULTPRN) ||
  106. (dwErr == PDERR_PRINTERNOTFOUND) )
  107. {
  108. TCHAR szWarning[SCRATCHBUF_SIZE];
  109. TCHAR szTitle[SCRATCHBUF_SIZE];
  110. int iszWarning;
  111. szTitle[0] = TEXT('\0');
  112. if (pPD->hwndOwner)
  113. {
  114. GetWindowText(pPD->hwndOwner, szTitle, SCRATCHBUF_SIZE);
  115. }
  116. if (!szTitle[0])
  117. {
  118. CDLoadString(g_hinst, iszWarningTitle, szTitle, SCRATCHBUF_SIZE);
  119. }
  120. switch (dwErr)
  121. {
  122. case ( PDERR_NODEFAULTPRN ) :
  123. {
  124. //
  125. // Notes: if the app is a 16-bit app, we don't ask the user whether to install a
  126. // new printer. This is because some components may break if we do it.
  127. //
  128. if (IS16BITWOWAPP(pPD))
  129. {
  130. iszWarning = iszNoPrnsInstalled;
  131. }
  132. else
  133. {
  134. iszWarning = iszNoPrinters;
  135. }
  136. break;
  137. }
  138. case ( PDERR_PRINTERNOTFOUND ) :
  139. {
  140. iszWarning = iszPrnNotFound;
  141. break;
  142. }
  143. case ( CDERR_MEMLOCKFAILURE ) :
  144. case ( CDERR_MEMALLOCFAILURE ) :
  145. case ( PDERR_LOADDRVFAILURE ) :
  146. {
  147. iszWarning = iszMemoryError;
  148. break;
  149. }
  150. default :
  151. {
  152. iszWarning = iszGeneralWarning;
  153. break;
  154. }
  155. }
  156. if (iszWarning == iszNoPrnsInstalled)
  157. {
  158. FormatMessage(
  159. FORMAT_MESSAGE_FROM_SYSTEM |
  160. FORMAT_MESSAGE_IGNORE_INSERTS,
  161. NULL,
  162. ERROR_PRINTER_NOT_FOUND,
  163. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  164. (LPTSTR)szWarning,
  165. sizeof(szWarning),
  166. NULL);
  167. }
  168. else
  169. {
  170. CDLoadString(g_hinst, iszWarning, szWarning, SCRATCHBUF_SIZE);
  171. }
  172. MessageBeep(MB_ICONEXCLAMATION);
  173. if (iszWarning == iszNoPrinters)
  174. {
  175. //
  176. // If the problem is that there are no printers installed then ask the
  177. // user if he wants to add one, and then launch the add printer wizard.
  178. //
  179. if (IDYES == MessageBox( pPD->hwndOwner,
  180. szWarning,
  181. szTitle,
  182. MB_ICONQUESTION | MB_YESNO))
  183. {
  184. hr = InvokeAddPrinterWizardModal(pPD->hwndOwner, &bPrinterAdded);
  185. if (SUCCEEDED(hr) && bPrinterAdded)
  186. {
  187. //
  188. // A printer was added successfully. Tell the caller to try again.
  189. //
  190. bTryAgain = TRUE;
  191. }
  192. }
  193. }
  194. else
  195. {
  196. //
  197. // This is a fatal error. Just show an error message and bail.
  198. //
  199. MessageBox( pPD->hwndOwner,
  200. szWarning,
  201. szTitle,
  202. MB_ICONEXCLAMATION | MB_OK );
  203. }
  204. }
  205. }
  206. if (pbTryAgain)
  207. {
  208. *pbTryAgain = bTryAgain;
  209. }
  210. return hr;
  211. }
  212. ////////////////////////////////////////////////////////////////////////////
  213. //
  214. // PrintDlgX
  215. //
  216. // Worker routine for the PrintDlg api.
  217. //
  218. ////////////////////////////////////////////////////////////////////////////
  219. BOOL PrintDlgX(
  220. PPRINTINFO pPI)
  221. {
  222. LPPRINTDLG pPD = pPI->pPD;
  223. BOOL nResult = -1; // <0==error, 0==CANCEL, >0==OK
  224. LPDEVMODE pDM = NULL;
  225. LPDEVMODE pDevMode = NULL;
  226. LPDEVNAMES pDN = NULL;
  227. DWORD dwFlags; // old copy
  228. WORD nCopies, nFromPage, nToPage; // old copy
  229. HGLOBAL hDevNames, hDevMode; // old copy
  230. TCHAR szPrinterName[MAX_PRINTERNAME]; // old copy
  231. LONG cbNeeded;
  232. #ifndef WINNT
  233. LPCTSTR pDN_Device = NULL;
  234. TCHAR szDev[2];
  235. #endif
  236. DWORD dwResult = 0;
  237. BOOL bTryAgain = TRUE;
  238. if (!pPD)
  239. {
  240. StoreExtendedError(CDERR_INITIALIZATION);
  241. return (FALSE);
  242. }
  243. if (pPD->lStructSize != sizeof(PRINTDLG))
  244. {
  245. StoreExtendedError(CDERR_STRUCTSIZE);
  246. return (FALSE);
  247. }
  248. if (pPD->hwndOwner && !IsWindow(pPD->hwndOwner))
  249. {
  250. StoreExtendedError(CDERR_DIALOGFAILURE);
  251. return (FALSE);
  252. }
  253. #ifdef WINNT
  254. //
  255. // See if the application should get the new look.
  256. //
  257. // Do not allow the new look if they have hooks, templates,
  258. // Invalid hwndOwner,
  259. // they want the setup dialog, or they just want to get the default
  260. // printer.
  261. //
  262. // Also don't allow the new look if we are in the context of
  263. // a 16 bit process.
  264. //
  265. if ( (!(pPI->Status & PI_PRINTDLGX_RECURSE)) &&
  266. (!pPI->pPSD) &&
  267. ((!(pPD->Flags & (PD_PAGESETUP |
  268. PD_PRINTSETUP |
  269. PD_RETURNDEFAULT |
  270. PD_ENABLEPRINTHOOK |
  271. PD_ENABLESETUPHOOK |
  272. PD_ENABLEPRINTTEMPLATE |
  273. PD_ENABLESETUPTEMPLATE |
  274. PD_ENABLEPRINTTEMPLATEHANDLE |
  275. PD_ENABLESETUPTEMPLATEHANDLE)))) &&
  276. (pPD->hwndOwner && IsWindow(pPD->hwndOwner)) &&
  277. (!IS16BITWOWAPP(pPD)) )
  278. {
  279. //
  280. // Show the new dialog.
  281. //
  282. StoreExtendedError(0);
  283. return Print_NewPrintDlg(pPI);
  284. }
  285. #endif
  286. //
  287. // Warning! Warning! Warning!
  288. //
  289. // We have to set g_tlsLangID before any call for CDLoadString
  290. //
  291. TlsSetValue(g_tlsLangID, (LPVOID) GetDialogLanguage(pPD->hwndOwner, NULL));
  292. //
  293. // Get the process version of the app for later use.
  294. //
  295. pPI->ProcessVersion = GetProcessVersion(0);
  296. #ifdef UNICODE
  297. //
  298. // Check if we need to use ExtDeviceMode. We use this
  299. // mode only if a 16 bit app is calling us with a NULL
  300. // devmode.
  301. //
  302. if ((pPD->Flags & CD_WOWAPP) && !pPD->hDevMode)
  303. {
  304. pPI->bUseExtDeviceMode = TRUE;
  305. }
  306. else
  307. {
  308. pPI->bUseExtDeviceMode = FALSE;
  309. }
  310. #endif
  311. #ifndef WINNT
  312. //
  313. // This should NOT be in NT. The device name cannot be longer than
  314. // 32 characters, so it may be truncated. If we look for it in the
  315. // registry and it's supposed to be larger than 32 characters, then
  316. // we won't find it and we'll fail.
  317. //
  318. // LATER: It probably shouldn't be in WIN95 either, but I'll leave
  319. // it for now.
  320. //
  321. if (pPD->hDevMode)
  322. {
  323. if (!(pDM = GlobalLock(pPD->hDevMode)))
  324. {
  325. StoreExtendedError(CDERR_MEMLOCKFAILURE);
  326. goto PrintDlgX_DisplayWarning;
  327. }
  328. }
  329. if (pPD->hDevNames)
  330. {
  331. if (!(pDN = GlobalLock(pPD->hDevNames)))
  332. {
  333. if (pDM)
  334. {
  335. GlobalUnlock(pPD->hDevMode);
  336. }
  337. StoreExtendedError(CDERR_MEMLOCKFAILURE);
  338. goto PrintDlgX_DisplayWarning;
  339. }
  340. else
  341. {
  342. if (pDN->wDeviceOffset)
  343. {
  344. pDN_Device = (LPCTSTR)pDN + pDN->wDeviceOffset;
  345. }
  346. }
  347. }
  348. if (pDM && pDM->dmDeviceName[0])
  349. {
  350. pDM->dmDeviceName[CCHDEVICENAME - 1] = 0;
  351. GetProfileString(szTextDevices, pDM->dmDeviceName, szTextNull, szDev, 2);
  352. if (!szDev[0])
  353. {
  354. GlobalUnlock(pPD->hDevMode);
  355. if (pDN)
  356. {
  357. GlobalUnlock(pPD->hDevNames);
  358. }
  359. StoreExtendedError(PDERR_PRINTERNOTFOUND);
  360. goto PrintDlgX_DisplayWarning;
  361. }
  362. }
  363. if (pDN_Device && pDN_Device[0])
  364. {
  365. GetProfileString(szTextDevices, pDN_Device, szTextNull, szDev, 2);
  366. if (!szDev[0])
  367. {
  368. if (pDM)
  369. {
  370. GlobalUnlock(pPD->hDevMode);
  371. }
  372. GlobalUnlock(pPD->hDevNames);
  373. StoreExtendedError(PDERR_PRINTERNOTFOUND);
  374. goto PrintDlgX_DisplayWarning;
  375. }
  376. }
  377. if (pDM)
  378. {
  379. GlobalUnlock(pPD->hDevMode);
  380. }
  381. if (pDN)
  382. {
  383. GlobalUnlock(pPD->hDevNames);
  384. }
  385. #endif
  386. pPD->hDC = 0;
  387. StoreExtendedError(CDERR_GENERALCODES);
  388. //
  389. // Do minimal work when requesting a default printer.
  390. //
  391. if (pPD->Flags & PD_RETURNDEFAULT)
  392. {
  393. //
  394. // Do not display a warning in this case if it fails.
  395. // MFC 3.1 does not specify PD_NOWARNING, but that's what
  396. // it really wants.
  397. //
  398. nResult = PrintReturnDefault(pPI);
  399. PrintClosePrinters(pPI);
  400. return (nResult);
  401. }
  402. if (!PrintLoadIcons())
  403. {
  404. //
  405. // If the icons cannot be loaded, then fail.
  406. //
  407. StoreExtendedError(PDERR_SETUPFAILURE);
  408. goto PrintDlgX_DisplayWarning;
  409. }
  410. //
  411. // Printer enumeration is delayed until the combobox is dropped down.
  412. // However, if a printer is specified, we must force enumeration in
  413. // order to find the printer so that the correct devmode can be created.
  414. //
  415. if ((pPD->hDevMode) &&
  416. (pPD->hDevNames) &&
  417. (pDM = GlobalLock(pPD->hDevMode)))
  418. {
  419. if (pDN = GlobalLock(pPD->hDevNames))
  420. {
  421. dwResult = lstrcmp((LPTSTR)pDM->dmDeviceName,
  422. (LPTSTR)pDN + pDN->wDeviceOffset);
  423. GlobalUnlock(pPD->hDevNames);
  424. }
  425. GlobalUnlock(pPD->hDevMode);
  426. }
  427. //
  428. // First : Try to open the printer in the DevMode.
  429. //
  430. // Note: The printer name field in the DEVMODE struct is limited to
  431. // 32 chars which may cause this case to fail.
  432. //
  433. if ( (!dwResult) &&
  434. (!pPI->hCurPrinter) &&
  435. (pPD->hDevMode) &&
  436. (pDM = GlobalLock(pPD->hDevMode)) )
  437. {
  438. PrintOpenPrinter(pPI, pDM->dmDeviceName);
  439. GlobalUnlock(pPD->hDevMode);
  440. }
  441. //
  442. // Second : Try to open the printer in the DevNames.
  443. //
  444. if ( (!pPI->hCurPrinter) &&
  445. (pPD->hDevNames) &&
  446. (pDN = GlobalLock(pPD->hDevNames)) )
  447. {
  448. PrintOpenPrinter(pPI, (LPTSTR)pDN + pDN->wDeviceOffset);
  449. GlobalUnlock(pPD->hDevNames);
  450. }
  451. for (;;)
  452. {
  453. //
  454. // Third : Try to open the Default Printer.
  455. //
  456. PrintGetDefaultPrinterName(pPI->szDefaultPrinter, MAX_PRINTERNAME);
  457. if (!pPI->hCurPrinter)
  458. {
  459. if (pPI->szDefaultPrinter[0])
  460. {
  461. PrintOpenPrinter(pPI, pPI->szDefaultPrinter);
  462. }
  463. }
  464. //
  465. // Fourth : Enumerate the Printers and try to open one of those.
  466. //
  467. if (!pPI->hCurPrinter)
  468. {
  469. if (!PrintEnumAndSelect(pPD->hwndOwner, 0, pPI, NULL, TRUE))
  470. {
  471. //
  472. // There are no printers installed in the system.
  473. //
  474. if (SUCCEEDED(ShowErrorMessage(pPD, pPI, &bTryAgain)) && bTryAgain)
  475. {
  476. //
  477. // The user has installed a printer. Let's try again now.
  478. //
  479. continue;
  480. }
  481. }
  482. }
  483. break;
  484. }
  485. if (!bTryAgain && IS16BITWOWAPP(pPD))
  486. {
  487. //
  488. // If it's a 16-bit app, we'll return immediately without showing
  489. // warning message. This is because some 16-bit app will crash in
  490. // the common print dialog.
  491. //
  492. return (FALSE);
  493. }
  494. //
  495. // Save the original information passed in by the app in case the user
  496. // hits cancel.
  497. //
  498. dwFlags = pPD->Flags;
  499. nCopies = pPD->nCopies;
  500. nFromPage = pPD->nFromPage;
  501. nToPage = pPD->nToPage;
  502. hDevNames = pPD->hDevNames;
  503. hDevMode = pPD->hDevMode;
  504. if ((pPI->pCurPrinter) &&
  505. (lstrlen(pPI->pCurPrinter->pPrinterName) < MAX_PRINTERNAME))
  506. {
  507. lstrcpy(szPrinterName, pPI->pCurPrinter->pPrinterName);
  508. }
  509. else
  510. {
  511. szPrinterName[0] = 0;
  512. }
  513. pPD->hDevNames = NULL;
  514. pPD->hDevMode = NULL;
  515. //
  516. // Build a copy of the DevNames.
  517. //
  518. PrintBuildDevNames(pPI);
  519. //
  520. // Get the *correct* DevMode.
  521. //
  522. if (hDevMode)
  523. {
  524. pDevMode = GlobalLock(hDevMode);
  525. }
  526. #ifdef UNICODE
  527. else
  528. {
  529. //
  530. // If it's WOW and the app didn't specify a devmode, get the 16-bit
  531. // devmode out of the registry (ie. win.ini [Windows] device section).
  532. //
  533. if (pPI->bUseExtDeviceMode && pPI->pCurPrinter)
  534. {
  535. pDevMode = (pPI->pCurPrinter)->pDevMode;
  536. if (pDevMode)
  537. {
  538. cbNeeded = sizeof(DEVMODEW) + pDevMode->dmDriverExtra;
  539. goto GotWOWDMSize;
  540. }
  541. //
  542. // If a 16-bit devmode isn't available in the registry,
  543. // drop through and get the system default devmode.
  544. //
  545. }
  546. }
  547. #endif
  548. cbNeeded = DocumentProperties( pPD->hwndOwner,
  549. pPI->hCurPrinter,
  550. (pPI->pCurPrinter)
  551. ? pPI->pCurPrinter->pPrinterName
  552. : NULL,
  553. NULL,
  554. NULL,
  555. 0 );
  556. #ifdef UNICODE
  557. GotWOWDMSize:
  558. #endif
  559. if ((cbNeeded > 0) &&
  560. (pPD->hDevMode = GlobalAlloc(GHND, cbNeeded)))
  561. {
  562. BOOL fSuccess = FALSE;
  563. if (pDM = GlobalLock(pPD->hDevMode))
  564. {
  565. #ifdef UNICODE
  566. if (pPI->bUseExtDeviceMode && !hDevMode)
  567. {
  568. CopyMemory(pDM, pDevMode, cbNeeded);
  569. fSuccess = TRUE;
  570. goto GotNewWOWDM;
  571. }
  572. #endif
  573. fSuccess = DocumentProperties( pPD->hwndOwner,
  574. pPI->hCurPrinter,
  575. (pPI->pCurPrinter)
  576. ? pPI->pCurPrinter->pPrinterName
  577. : NULL,
  578. pDM, // out
  579. pDevMode, // in
  580. DM_MODIFY | DM_COPY ) == IDOK;
  581. #ifdef UNICODE
  582. GotNewWOWDM:
  583. #endif
  584. if (pDM->dmFields & DM_COPIES)
  585. {
  586. if ((hDevMode) || (pPD->Flags & PD_USEDEVMODECOPIES))
  587. {
  588. pPD->nCopies = pDM->dmCopies;
  589. }
  590. else if (pPD->nCopies)
  591. {
  592. pDM->dmCopies = pPD->nCopies;
  593. }
  594. }
  595. if (pDM->dmFields & DM_COLLATE)
  596. {
  597. //
  598. // if PD_COLLATE is not set, we also use the setting in
  599. // the returned DEVMODE structure
  600. //
  601. if ((hDevMode) || (pPD->Flags & PD_USEDEVMODECOPIES) || !(pPD->Flags & PD_COLLATE))
  602. {
  603. if (pDM->dmCollate == DMCOLLATE_FALSE)
  604. {
  605. pPD->Flags &= ~PD_COLLATE;
  606. pPI->Status &= ~PI_COLLATE_REQUESTED;
  607. }
  608. else
  609. {
  610. pPD->Flags |= PD_COLLATE;
  611. pPI->Status |= PI_COLLATE_REQUESTED;
  612. }
  613. }
  614. else // in this case (pPD->Flags & PD_COLLATE) must be TRUE
  615. {
  616. pDM->dmCollate = DMCOLLATE_TRUE;
  617. }
  618. }
  619. GlobalUnlock(pPD->hDevMode);
  620. }
  621. if (!fSuccess)
  622. {
  623. GlobalFree(pPD->hDevMode);
  624. pPD->hDevMode = NULL;
  625. }
  626. }
  627. if (hDevMode)
  628. {
  629. GlobalUnlock(hDevMode);
  630. }
  631. //
  632. // Get the default source string.
  633. //
  634. CDLoadString(g_hinst, iszDefaultSource, szDefaultSrc, SCRATCHBUF_SIZE);
  635. //
  636. // Call the appropriate dialog routine.
  637. //
  638. switch (pPD->Flags & (PD_PRINTSETUP | PD_PAGESETUP))
  639. {
  640. case ( 0 ) :
  641. {
  642. nResult = PrintDisplayPrintDlg(pPI);
  643. break;
  644. }
  645. case ( PD_PRINTSETUP ) :
  646. case ( PD_PAGESETUP ) :
  647. {
  648. nResult = PrintDisplaySetupDlg(pPI);
  649. break;
  650. }
  651. default :
  652. {
  653. StoreExtendedError(CDERR_INITIALIZATION);
  654. break;
  655. }
  656. }
  657. if (nResult > 0)
  658. {
  659. //
  660. // User hit OK, so free the copies of the handles passed in
  661. // by the app.
  662. //
  663. if (hDevMode && (hDevMode != pPD->hDevMode))
  664. {
  665. GlobalFree(hDevMode);
  666. hDevMode = NULL;
  667. }
  668. if (hDevNames && (hDevNames != pPD->hDevNames))
  669. {
  670. GlobalFree(hDevNames);
  671. hDevNames = NULL;
  672. }
  673. if (pPD->hDevMode)
  674. {
  675. //
  676. // Make sure the device name in the devmode is null
  677. // terminated.
  678. //
  679. pDevMode = GlobalLock(pPD->hDevMode);
  680. pDevMode->dmDeviceName[CCHDEVICENAME - 1] = 0;
  681. GlobalUnlock(pPD->hDevMode);
  682. }
  683. }
  684. else
  685. {
  686. //
  687. // User hit CANCEL or there was an error, so restore original
  688. // values passed in by the app.
  689. //
  690. pPD->Flags = dwFlags;
  691. pPD->nCopies = nCopies;
  692. pPD->nFromPage = nFromPage;
  693. pPD->nToPage = nToPage;
  694. if (pPD->hDevMode && (pPD->hDevMode != hDevMode))
  695. {
  696. GlobalFree(pPD->hDevMode);
  697. }
  698. if (pPD->hDevNames && (pPD->hDevNames != hDevNames))
  699. {
  700. GlobalFree(pPD->hDevNames);
  701. }
  702. pPD->hDevNames = hDevNames;
  703. pPD->hDevMode = hDevMode;
  704. //
  705. // If we've been called from Page Setup, then we need to reset
  706. // the current printer.
  707. //
  708. if (pPI->Status & PI_PRINTDLGX_RECURSE)
  709. {
  710. PrintCancelPrinterChanged(pPI, szPrinterName);
  711. }
  712. }
  713. //
  714. // Make sure that we are really supposed to be leaving this function
  715. // before we start closing printers and displaying error messages.
  716. //
  717. if (pPI->Status & PI_PRINTDLGX_RECURSE)
  718. {
  719. return (nResult > 0);
  720. }
  721. //
  722. // Close the printers that were opened.
  723. //
  724. PrintClosePrinters(pPI);
  725. //
  726. // Display any error messages.
  727. //
  728. PrintDlgX_DisplayWarning:
  729. if (nResult < 0)
  730. {
  731. //
  732. // Display an error message and ignore the return code
  733. // since we don't care.
  734. //
  735. ShowErrorMessage(pPD, pPI, NULL);
  736. }
  737. return (nResult > 0);
  738. }
  739. #ifdef UNICODE
  740. ////////////////////////////////////////////////////////////////////////////
  741. //
  742. // PageSetupDlgA
  743. //
  744. // ANSI entry point for PageSetupDlg when this code is built UNICODE.
  745. //
  746. ////////////////////////////////////////////////////////////////////////////
  747. BOOL WINAPI PageSetupDlgA(
  748. LPPAGESETUPDLGA pPSDA)
  749. {
  750. PRINTINFO PI;
  751. BOOL bResult = FALSE;
  752. HANDLE hDevMode;
  753. HANDLE hDevNames;
  754. LPCSTR pTemplateName;
  755. ZeroMemory(&PI, sizeof(PRINTINFO));
  756. //
  757. // Get the pPDA structure from the pPSDA structure.
  758. //
  759. if (bResult = ThunkPageSetupDlg(&PI, pPSDA))
  760. {
  761. //
  762. // Save the original devmode and devnames.
  763. //
  764. hDevMode = pPSDA->hDevMode;
  765. hDevNames = pPSDA->hDevNames;
  766. pTemplateName = pPSDA->lpPageSetupTemplateName;
  767. //
  768. // Convert the pPDA structure to Unicode (pPI->pPD).
  769. //
  770. if (bResult = ThunkPrintDlg(&PI, PI.pPDA))
  771. {
  772. //
  773. // Fill in the pPI->pPD structure.
  774. //
  775. ThunkPrintDlgA2W(&PI);
  776. //
  777. // Copy the Unicode information from the pPD structure to
  778. // the pPSD structure for the call to PageSetupDlgX.
  779. //
  780. (PI.pPSD)->hDevMode = (PI.pPD)->hDevMode;
  781. (PI.pPSD)->hDevNames = (PI.pPD)->hDevNames;
  782. (PI.pPSD)->lpPageSetupTemplateName = (PI.pPD)->lpSetupTemplateName;
  783. //
  784. // Call the PageSetupDlgX function to do the work.
  785. //
  786. if (bResult = PageSetupDlgX(&PI))
  787. {
  788. //
  789. // Success. Convert the Unicode pPD structure to
  790. // its ANSI equivalent.
  791. //
  792. ThunkPrintDlgW2A(&PI);
  793. //
  794. // Save the ANSI devmode and devnames in the
  795. // pPSD structure to be returned to the caller.
  796. //
  797. pPSDA->hDevMode = (PI.pPDA)->hDevMode;
  798. pPSDA->hDevNames = (PI.pPDA)->hDevNames;
  799. }
  800. else
  801. {
  802. //
  803. // Failure. Restore the old devmode and devnames.
  804. //
  805. pPSDA->hDevMode = hDevMode;
  806. pPSDA->hDevNames = hDevNames;
  807. }
  808. //
  809. // Restore the old template name (always).
  810. //
  811. pPSDA->lpPageSetupTemplateName = pTemplateName;
  812. }
  813. FreeThunkPrintDlg(&PI);
  814. }
  815. FreeThunkPageSetupDlg(&PI);
  816. return (bResult);
  817. }
  818. #else
  819. ////////////////////////////////////////////////////////////////////////////
  820. //
  821. // PageSetupDlgW
  822. //
  823. // Stub UNICODE function for PageSetupDlg when this code is built ANSI.
  824. //
  825. ////////////////////////////////////////////////////////////////////////////
  826. BOOL WINAPI PageSetupDlgW(
  827. LPPAGESETUPDLGW pPSDW)
  828. {
  829. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  830. return (FALSE);
  831. }
  832. #endif
  833. ////////////////////////////////////////////////////////////////////////////
  834. //
  835. // PageSetupDlg
  836. //
  837. // The PageSetupDlg function displays a Page Setup dialog box. This
  838. // dialog box enables the user to specify the page orientation, the
  839. // paper size, the paper source, and the margin settings. The
  840. // appearance of the printed page is shown in the dialog's page preview.
  841. //
  842. ////////////////////////////////////////////////////////////////////////////
  843. BOOL WINAPI PageSetupDlg(
  844. LPPAGESETUPDLG pPSD)
  845. {
  846. PRINTINFO PI;
  847. BOOL bResult;
  848. ZeroMemory(&PI, sizeof(PRINTINFO));
  849. PI.pPSD = pPSD;
  850. PI.ApiType = COMDLG_WIDE;
  851. bResult = PageSetupDlgX(&PI);
  852. if (PI.pPD)
  853. {
  854. GlobalFree(PI.pPD);
  855. }
  856. return (bResult);
  857. }
  858. ////////////////////////////////////////////////////////////////////////////
  859. //
  860. // PageSetupDlgX
  861. //
  862. // Worker routine for the PageSetupDlg api.
  863. //
  864. // NOTE: Caller of this routine must free pPI->pPD.
  865. //
  866. ////////////////////////////////////////////////////////////////////////////
  867. BOOL PageSetupDlgX(
  868. PPRINTINFO pPI)
  869. {
  870. LPPAGESETUPDLG pPSD = pPI->pPSD;
  871. BOOL bResult = FALSE;
  872. LPPRINTDLG pPD;
  873. RECT rtMinMargin;
  874. RECT rtMargin;
  875. POINT ptPaperSize;
  876. DWORD Flags;
  877. if (!pPSD)
  878. {
  879. StoreExtendedError(CDERR_INITIALIZATION);
  880. return (FALSE);
  881. }
  882. if (pPSD->lStructSize != sizeof(PAGESETUPDLG))
  883. {
  884. StoreExtendedError(CDERR_STRUCTSIZE);
  885. return (FALSE);
  886. }
  887. if ((pPSD->Flags & PSD_RETURNDEFAULT) &&
  888. (pPSD->hDevNames || pPSD->hDevMode))
  889. {
  890. StoreExtendedError(PDERR_RETDEFFAILURE);
  891. return (FALSE);
  892. }
  893. //
  894. // Make sure only the PSD_* bits are on. Otherwise, bad things
  895. // will happen.
  896. //
  897. if ((pPSD->Flags & ~(PSD_MINMARGINS |
  898. PSD_MARGINS |
  899. PSD_INTHOUSANDTHSOFINCHES |
  900. PSD_INHUNDREDTHSOFMILLIMETERS |
  901. PSD_DISABLEMARGINS |
  902. PSD_DISABLEPRINTER |
  903. PSD_NOWARNING | // must be same as PD_*
  904. PSD_DISABLEORIENTATION |
  905. PSD_DISABLEPAPER |
  906. PSD_RETURNDEFAULT | // must be same as PD_*
  907. PSD_SHOWHELP | // must be same as PD_*
  908. PSD_ENABLEPAGESETUPHOOK | // must be same as PD_*
  909. PSD_ENABLEPAGESETUPTEMPLATE | // must be same as PD_*
  910. PSD_ENABLEPAGESETUPTEMPLATEHANDLE | // must be same as PD_*
  911. PSD_ENABLEPAGEPAINTHOOK |
  912. PSD_DISABLEPAGEPAINTING |
  913. CD_WX86APP |
  914. PSD_NONETWORKBUTTON)) || // must be same as PD_*
  915. ((pPSD->Flags & (PSD_INTHOUSANDTHSOFINCHES |
  916. PSD_INHUNDREDTHSOFMILLIMETERS)) ==
  917. (PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS)))
  918. {
  919. StoreExtendedError(PDERR_INITFAILURE);
  920. return (FALSE);
  921. }
  922. if ((pPSD->Flags & PSD_MINMARGINS) && (pPSD->Flags & PSD_MARGINS))
  923. {
  924. if ( (pPSD->rtMargin.left < pPSD->rtMinMargin.left) ||
  925. (pPSD->rtMargin.top < pPSD->rtMinMargin.top) ||
  926. (pPSD->rtMargin.right < pPSD->rtMinMargin.right) ||
  927. (pPSD->rtMargin.bottom < pPSD->rtMinMargin.bottom) )
  928. {
  929. StoreExtendedError(PDERR_INITFAILURE);
  930. return (FALSE);
  931. }
  932. }
  933. if (pPSD->Flags & PSD_ENABLEPAGESETUPHOOK)
  934. {
  935. if (!pPSD->lpfnPageSetupHook)
  936. {
  937. StoreExtendedError(CDERR_NOHOOK);
  938. return (FALSE);
  939. }
  940. }
  941. else
  942. {
  943. pPSD->lpfnPageSetupHook = NULL;
  944. }
  945. if (pPSD->Flags & PSD_ENABLEPAGEPAINTHOOK)
  946. {
  947. if (!pPSD->lpfnPagePaintHook)
  948. {
  949. StoreExtendedError(CDERR_NOHOOK);
  950. return (FALSE);
  951. }
  952. }
  953. else
  954. {
  955. pPSD->lpfnPagePaintHook = NULL;
  956. }
  957. if ((pPI->pPD) || (pPI->pPD = GlobalAlloc(GPTR, sizeof(PRINTDLG))))
  958. {
  959. pPD = pPI->pPD;
  960. pPD->lStructSize = sizeof(PRINTDLG);
  961. pPD->hwndOwner = pPSD->hwndOwner;
  962. pPD->Flags = PD_PAGESETUP |
  963. (pPSD->Flags &
  964. (PSD_NOWARNING |
  965. PSD_SHOWHELP |
  966. PSD_ENABLEPAGESETUPHOOK |
  967. PSD_ENABLEPAGESETUPTEMPLATE |
  968. PSD_ENABLEPAGESETUPTEMPLATEHANDLE |
  969. CD_WX86APP |
  970. PSD_NONETWORKBUTTON));
  971. pPD->hInstance = pPSD->hInstance;
  972. pPD->lCustData = pPSD->lCustData;
  973. pPD->lpfnSetupHook = pPSD->lpfnPageSetupHook;
  974. pPD->lpSetupTemplateName = pPSD->lpPageSetupTemplateName;
  975. pPD->hSetupTemplate = pPSD->hPageSetupTemplate;
  976. //
  977. // Save original settings in case the user hits cancel.
  978. //
  979. rtMinMargin = pPSD->rtMinMargin;
  980. rtMargin = pPSD->rtMargin;
  981. ptPaperSize = pPSD->ptPaperSize;
  982. Flags = pPSD->Flags;
  983. //
  984. // Make sure the measure choice is set.
  985. //
  986. if ((pPSD->Flags & (PSD_INTHOUSANDTHSOFINCHES |
  987. PSD_INHUNDREDTHSOFMILLIMETERS)) == 0)
  988. {
  989. TCHAR szIMeasure[2];
  990. GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IMEASURE, szIMeasure, 2);
  991. if (szIMeasure[0] == TEXT('1'))
  992. {
  993. pPSD->Flags |= PSD_INTHOUSANDTHSOFINCHES;
  994. }
  995. else
  996. {
  997. pPSD->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
  998. }
  999. }
  1000. //
  1001. // Set minimum margins to 0 if not passed in.
  1002. //
  1003. if (!(pPSD->Flags & PSD_MINMARGINS))
  1004. {
  1005. pPSD->rtMinMargin.left = 0;
  1006. pPSD->rtMinMargin.top = 0;
  1007. pPSD->rtMinMargin.right = 0;
  1008. pPSD->rtMinMargin.bottom = 0;
  1009. }
  1010. //
  1011. // Set margins to defaults if not passed in.
  1012. //
  1013. if (!(pPSD->Flags & PSD_MARGINS))
  1014. {
  1015. LONG MarginDefault = (pPSD->Flags & PSD_INTHOUSANDTHSOFINCHES)
  1016. ? INCHES_DEFAULT
  1017. : MMS_DEFAULT;
  1018. pPSD->rtMargin.left = MarginDefault;
  1019. pPSD->rtMargin.top = MarginDefault;
  1020. pPSD->rtMargin.right = MarginDefault;
  1021. pPSD->rtMargin.bottom = MarginDefault;
  1022. }
  1023. TransferPSD2PD(pPI);
  1024. bResult = PrintDlgX(pPI);
  1025. TransferPD2PSD(pPI);
  1026. if (!bResult)
  1027. {
  1028. //
  1029. // Restore original settings when the user hits cancel.
  1030. //
  1031. pPSD->rtMinMargin = rtMinMargin;
  1032. pPSD->rtMargin = rtMargin;
  1033. pPSD->ptPaperSize = ptPaperSize;
  1034. pPSD->Flags = Flags;
  1035. }
  1036. }
  1037. else
  1038. {
  1039. StoreExtendedError(CDERR_MEMALLOCFAILURE);
  1040. }
  1041. return (bResult);
  1042. }
  1043. ////////////////////////////////////////////////////////////////////////////
  1044. //
  1045. // PrintLoadIcons
  1046. //
  1047. ////////////////////////////////////////////////////////////////////////////
  1048. BOOL PrintLoadIcons()
  1049. {
  1050. //
  1051. // See if we need to load the icons.
  1052. //
  1053. if (bAllIconsLoaded == FALSE)
  1054. {
  1055. //
  1056. // Load the orientation icons.
  1057. //
  1058. hIconPortrait = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_PORTRAIT));
  1059. hIconLandscape = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_LANDSCAPE));
  1060. //
  1061. // Load the duplex icons.
  1062. //
  1063. hIconPDuplexNone = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_P_NONE));
  1064. hIconLDuplexNone = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_L_NONE));
  1065. hIconPDuplexTumble = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_P_HORIZ));
  1066. hIconLDuplexTumble = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_L_VERT));
  1067. hIconPDuplexNoTumble = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_P_VERT));
  1068. hIconLDuplexNoTumble = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_L_HORIZ));
  1069. //
  1070. // Load the page setup icons.
  1071. //
  1072. hIconPSStampP = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_P_PSSTAMP));
  1073. hIconPSStampL = LoadIcon(g_hinst, MAKEINTRESOURCE(ICO_L_PSSTAMP));
  1074. //
  1075. // Load the collation images.
  1076. //
  1077. hIconCollate = LoadImage( g_hinst,
  1078. MAKEINTRESOURCE(ICO_COLLATE),
  1079. IMAGE_ICON,
  1080. 0,
  1081. 0,
  1082. LR_SHARED );
  1083. hIconNoCollate = LoadImage( g_hinst,
  1084. MAKEINTRESOURCE(ICO_NO_COLLATE),
  1085. IMAGE_ICON,
  1086. 0,
  1087. 0,
  1088. LR_SHARED );
  1089. bAllIconsLoaded = ( hIconPortrait &&
  1090. hIconLandscape &&
  1091. hIconPDuplexNone &&
  1092. hIconLDuplexNone &&
  1093. hIconPDuplexTumble &&
  1094. hIconLDuplexTumble &&
  1095. hIconPDuplexNoTumble &&
  1096. hIconLDuplexNoTumble &&
  1097. hIconPSStampP &&
  1098. hIconPSStampL &&
  1099. hIconCollate &&
  1100. hIconNoCollate );
  1101. }
  1102. //
  1103. // Return TRUE only if all icons/images were loaded properly.
  1104. //
  1105. return (bAllIconsLoaded);
  1106. }
  1107. ////////////////////////////////////////////////////////////////////////////
  1108. //
  1109. // PrintDisplayPrintDlg
  1110. //
  1111. ////////////////////////////////////////////////////////////////////////////
  1112. int PrintDisplayPrintDlg(
  1113. PPRINTINFO pPI)
  1114. {
  1115. LPPRINTDLG pPD = pPI->pPD;
  1116. int fGotInput = -1;
  1117. HANDLE hDlgTemplate = NULL;
  1118. HANDLE hInstance;
  1119. #ifdef UNICODE
  1120. UINT uiWOWFlag = 0;
  1121. #endif
  1122. //
  1123. // NOTE: The print hook check must be done here rather than in
  1124. // PrintDlgX. Old apps that set this flag without the
  1125. // PrintHook when calling Print Setup will fail - they
  1126. // used to succeed.
  1127. //
  1128. if (pPD->Flags & PD_ENABLEPRINTHOOK)
  1129. {
  1130. if (!pPD->lpfnPrintHook)
  1131. {
  1132. StoreExtendedError(CDERR_NOHOOK);
  1133. return (FALSE);
  1134. }
  1135. }
  1136. else
  1137. {
  1138. pPD->lpfnPrintHook = NULL;
  1139. }
  1140. if (pPD->Flags & PD_ENABLEPRINTTEMPLATEHANDLE)
  1141. {
  1142. if (pPD->hPrintTemplate)
  1143. {
  1144. hDlgTemplate = pPD->hPrintTemplate;
  1145. hInstance = g_hinst;
  1146. }
  1147. else
  1148. {
  1149. StoreExtendedError(CDERR_NOTEMPLATE);
  1150. }
  1151. }
  1152. else
  1153. {
  1154. LPTSTR pTemplateName = NULL;
  1155. if (pPD->Flags & PD_ENABLEPRINTTEMPLATE)
  1156. {
  1157. if (pPD->lpPrintTemplateName)
  1158. {
  1159. if (pPD->hInstance)
  1160. {
  1161. pTemplateName = (LPTSTR)pPD->lpPrintTemplateName;
  1162. hInstance = pPD->hInstance;
  1163. }
  1164. else
  1165. {
  1166. StoreExtendedError(CDERR_NOHINSTANCE);
  1167. }
  1168. }
  1169. else
  1170. {
  1171. StoreExtendedError(CDERR_NOTEMPLATE);
  1172. }
  1173. }
  1174. else
  1175. {
  1176. hInstance = g_hinst;
  1177. pTemplateName = MAKEINTRESOURCE(PRINTDLGORD);
  1178. }
  1179. if (pTemplateName)
  1180. {
  1181. hDlgTemplate = PrintLoadResource( hInstance,
  1182. pTemplateName,
  1183. RT_DIALOG);
  1184. }
  1185. }
  1186. if (!hDlgTemplate)
  1187. {
  1188. return (FALSE);
  1189. }
  1190. if (LockResource(hDlgTemplate))
  1191. {
  1192. glpfnPrintHook = GETPRINTHOOKFN(pPD);
  1193. #ifdef UNICODE
  1194. if (IS16BITWOWAPP(pPD))
  1195. {
  1196. uiWOWFlag = SCDLG_16BIT;
  1197. }
  1198. fGotInput = (BOOL)DialogBoxIndirectParamAorW( hInstance,
  1199. (LPDLGTEMPLATE)hDlgTemplate,
  1200. pPD->hwndOwner,
  1201. PrintDlgProc,
  1202. (LPARAM)pPI,
  1203. uiWOWFlag );
  1204. #else
  1205. fGotInput = (BOOL)DialogBoxIndirectParam( hInstance,
  1206. (LPDLGTEMPLATE)hDlgTemplate,
  1207. pPD->hwndOwner,
  1208. PrintDlgProc,
  1209. (LPARAM)pPI );
  1210. #endif
  1211. glpfnPrintHook = NULL;
  1212. if (fGotInput == -1)
  1213. {
  1214. StoreExtendedError(CDERR_DIALOGFAILURE);
  1215. }
  1216. }
  1217. else
  1218. {
  1219. StoreExtendedError(CDERR_LOCKRESFAILURE);
  1220. }
  1221. return (fGotInput);
  1222. }
  1223. ////////////////////////////////////////////////////////////////////////////
  1224. //
  1225. // PrintDisplaySetupDlg
  1226. //
  1227. ////////////////////////////////////////////////////////////////////////////
  1228. int PrintDisplaySetupDlg(
  1229. PPRINTINFO pPI)
  1230. {
  1231. LPPRINTDLG pPD = pPI->pPD;
  1232. int fGotInput = -1;
  1233. HANDLE hDlgTemplate = NULL;
  1234. HANDLE hInstance;
  1235. #ifdef UNICODE
  1236. UINT uiWOWFlag = 0;
  1237. #endif
  1238. //
  1239. // NOTE: The setup hook check must be done here rather than in
  1240. // PrintDlgX. Old apps that set this flag without the
  1241. // SetupHook when calling Print will fail - they
  1242. // used to succeed.
  1243. //
  1244. if (pPD->Flags & PD_ENABLESETUPHOOK)
  1245. {
  1246. if (!pPD->lpfnSetupHook)
  1247. {
  1248. StoreExtendedError(CDERR_NOHOOK);
  1249. return (FALSE);
  1250. }
  1251. }
  1252. else
  1253. {
  1254. pPD->lpfnSetupHook = NULL;
  1255. }
  1256. if (pPD->Flags & PD_ENABLESETUPTEMPLATEHANDLE)
  1257. {
  1258. if (pPD->hSetupTemplate)
  1259. {
  1260. hDlgTemplate = pPD->hSetupTemplate;
  1261. hInstance = g_hinst;
  1262. }
  1263. else
  1264. {
  1265. StoreExtendedError(CDERR_NOTEMPLATE);
  1266. }
  1267. }
  1268. else
  1269. {
  1270. LPTSTR pTemplateName = NULL;
  1271. if (pPD->Flags & PD_ENABLESETUPTEMPLATE)
  1272. {
  1273. if (pPD->lpSetupTemplateName)
  1274. {
  1275. if (pPD->hInstance)
  1276. {
  1277. pTemplateName = (LPTSTR)pPD->lpSetupTemplateName;
  1278. hInstance = pPD->hInstance;
  1279. }
  1280. else
  1281. {
  1282. StoreExtendedError(CDERR_NOHINSTANCE);
  1283. }
  1284. }
  1285. else
  1286. {
  1287. StoreExtendedError(CDERR_NOTEMPLATE);
  1288. }
  1289. }
  1290. else
  1291. {
  1292. hInstance = g_hinst;
  1293. pTemplateName = ( (pPD->Flags & PD_PRINTSETUP)
  1294. ? MAKEINTRESOURCE(PRNSETUPDLGORD)
  1295. : MAKEINTRESOURCE(PAGESETUPDLGORD) );
  1296. }
  1297. if (pTemplateName)
  1298. {
  1299. hDlgTemplate = PrintLoadResource( hInstance,
  1300. pTemplateName,
  1301. RT_DIALOG);
  1302. }
  1303. }
  1304. if (!hDlgTemplate)
  1305. {
  1306. return (FALSE);
  1307. }
  1308. if (LockResource(hDlgTemplate))
  1309. {
  1310. glpfnSetupHook = GETSETUPHOOKFN(pPD);
  1311. #ifdef UNICODE
  1312. if (IS16BITWOWAPP(pPD))
  1313. {
  1314. uiWOWFlag = SCDLG_16BIT;
  1315. }
  1316. fGotInput = (BOOL)DialogBoxIndirectParamAorW( hInstance,
  1317. (LPDLGTEMPLATE)hDlgTemplate,
  1318. pPD->hwndOwner,
  1319. PrintSetupDlgProc,
  1320. (LPARAM)pPI,
  1321. uiWOWFlag );
  1322. #else
  1323. fGotInput = (BOOL)DialogBoxIndirectParam( hInstance,
  1324. (LPDLGTEMPLATE)hDlgTemplate,
  1325. pPD->hwndOwner,
  1326. PrintSetupDlgProc,
  1327. (LPARAM)pPI );
  1328. #endif
  1329. glpfnSetupHook = NULL;
  1330. if (fGotInput == -1)
  1331. {
  1332. StoreExtendedError(CDERR_DIALOGFAILURE);
  1333. }
  1334. }
  1335. else
  1336. {
  1337. StoreExtendedError(CDERR_LOCKRESFAILURE);
  1338. }
  1339. return (fGotInput);
  1340. }
  1341. ////////////////////////////////////////////////////////////////////////////
  1342. //
  1343. // PrintDlgProc
  1344. //
  1345. // Print Dialog procedure.
  1346. //
  1347. ////////////////////////////////////////////////////////////////////////////
  1348. BOOL_PTR CALLBACK PrintDlgProc(
  1349. HWND hDlg,
  1350. UINT wMsg,
  1351. WPARAM wParam,
  1352. LPARAM lParam)
  1353. {
  1354. PPRINTINFO pPI;
  1355. LPPRINTDLG pPD;
  1356. HWND hCtl;
  1357. BOOL bTest;
  1358. BOOL_PTR bResult;
  1359. LPDEVMODE pDM;
  1360. LPDEVNAMES pDN;
  1361. if (pPI = (PPRINTINFO)GetProp(hDlg, PRNPROP))
  1362. {
  1363. if ((pPD = pPI->pPD) && (pPD->lpfnPrintHook))
  1364. {
  1365. LPPRINTHOOKPROC lpfnPrintHook = GETPRINTHOOKFN(pPD);
  1366. #ifdef UNICODE
  1367. if (pPI->ApiType == COMDLG_ANSI)
  1368. {
  1369. ThunkPrintDlgW2A(pPI);
  1370. }
  1371. #endif
  1372. if ((bResult = (*lpfnPrintHook)(hDlg, wMsg, wParam, lParam)))
  1373. {
  1374. #ifdef UNICODE
  1375. if (pPI->ApiType == COMDLG_ANSI)
  1376. {
  1377. ThunkPrintDlgA2W(pPI);
  1378. }
  1379. #endif
  1380. return (bResult);
  1381. }
  1382. }
  1383. }
  1384. else if (glpfnPrintHook &&
  1385. (wMsg != WM_INITDIALOG) &&
  1386. (bResult = (*glpfnPrintHook)(hDlg, wMsg, wParam, lParam)))
  1387. {
  1388. return (bResult);
  1389. }
  1390. switch (wMsg)
  1391. {
  1392. case ( WM_INITDIALOG ) :
  1393. {
  1394. DWORD dwResult = 0;
  1395. HourGlass(TRUE);
  1396. #ifndef WINNT
  1397. msgHELPA = RegisterWindowMessage(szCommdlgHelp);
  1398. #endif
  1399. SetProp(hDlg, PRNPROP, (HANDLE)lParam);
  1400. glpfnPrintHook = NULL;
  1401. pPI = (PPRINTINFO)lParam;
  1402. pPD = pPI->pPD;
  1403. if (pPI->pPSD)
  1404. {
  1405. TCHAR szTitle[32];
  1406. RECT aRtDlg;
  1407. RECT aRtGrp;
  1408. RECT aRtYep;
  1409. RECT aRtCan;
  1410. HWND hBtnYep = GetDlgItem(hDlg, IDOK);
  1411. HWND hBtnCan = GetDlgItem(hDlg, IDCANCEL);
  1412. RECT aRtWhere;
  1413. RECT aRtCmmnt;
  1414. LONG GapHeight, DlgTop;
  1415. //
  1416. // Save the client coordinate for the top of the dialog.
  1417. // Also, save the height of the gap between the bottom of
  1418. // the original OK button and the bottom of the original
  1419. // dialog.
  1420. //
  1421. GetWindowRect(hDlg, &aRtDlg);
  1422. GetWindowRect(hBtnYep, &aRtYep);
  1423. ScreenToClient(hDlg, (LPPOINT)&aRtDlg.left);
  1424. ScreenToClient(hDlg, (LPPOINT)&aRtDlg.right);
  1425. ScreenToClient(hDlg, (LPPOINT)&aRtYep.right);
  1426. DlgTop = aRtDlg.top;
  1427. GapHeight = (aRtDlg.bottom - aRtYep.bottom > 0)
  1428. ? aRtDlg.bottom - aRtYep.bottom
  1429. : 15;
  1430. //
  1431. // Display the title of the dialog box.
  1432. //
  1433. GetWindowText(GetParent(hDlg), szTitle, 32);
  1434. SetWindowText(hDlg, szTitle);
  1435. //
  1436. // Get the screen and client coordinates for the dialog,
  1437. // the Printer group box, the OK button, and the Cancel
  1438. // button. These will be used to reposition the OK,
  1439. // Cancel, and Help buttons.
  1440. //
  1441. GetWindowRect(hDlg, &aRtDlg);
  1442. GetWindowRect(GetDlgItem(hDlg, ID_PRINT_G_PRINTER), &aRtGrp);
  1443. GetWindowRect(hBtnYep, &aRtYep);
  1444. GetWindowRect(hBtnCan, &aRtCan);
  1445. //
  1446. //If we are in a mirrored Dlg the use the left side.
  1447. //
  1448. if (IS_WINDOW_RTL_MIRRORED(hDlg)) {
  1449. aRtDlg.right = aRtDlg.left;
  1450. }
  1451. ScreenToClient(hDlg , (LPPOINT)&aRtDlg.right);
  1452. ScreenToClient(hDlg , (LPPOINT)&aRtGrp.right);
  1453. MapWindowPoints(NULL, hDlg, (LPPOINT)&aRtYep, 2);
  1454. aRtYep.right -= aRtYep.left;
  1455. aRtYep.bottom -= aRtYep.top;
  1456. MapWindowPoints(NULL, hDlg, (LPPOINT)&aRtCan, 2);
  1457. aRtCan.right -= aRtCan.left;
  1458. aRtCan.bottom -= aRtCan.top;
  1459. #ifdef WINNT
  1460. if (pPD->Flags & PD_SHOWHELP)
  1461. {
  1462. HWND hBtnHlp = GetDlgItem(hDlg, ID_BOTH_P_HELP);
  1463. RECT aRtHlp;
  1464. //
  1465. // Move the Help button up underneath the
  1466. // Printer group box.
  1467. //
  1468. if (hBtnHlp)
  1469. {
  1470. GetWindowRect(hBtnHlp, &aRtHlp);
  1471. MapWindowPoints(NULL, hDlg, (LPPOINT)&aRtHlp, 2);
  1472. aRtHlp.right -= aRtHlp.left;
  1473. aRtHlp.bottom -= aRtHlp.top;
  1474. MoveWindow( hBtnHlp,
  1475. aRtHlp.left,
  1476. aRtGrp.bottom + 2 * aRtHlp.bottom / 3,
  1477. aRtHlp.right,
  1478. aRtHlp.bottom,
  1479. FALSE );
  1480. }
  1481. }
  1482. #endif
  1483. //
  1484. // Move the OK and Cancel buttons up underneath the
  1485. // Printer group box.
  1486. //
  1487. MoveWindow( hBtnYep,
  1488. aRtYep.left,
  1489. aRtGrp.bottom + 2 * aRtYep.bottom / 3,
  1490. aRtYep.right,
  1491. aRtYep.bottom,
  1492. FALSE );
  1493. MoveWindow( hBtnCan,
  1494. aRtCan.left,
  1495. aRtGrp.bottom + 2 * aRtCan.bottom / 3,
  1496. aRtCan.right,
  1497. aRtCan.bottom,
  1498. FALSE );
  1499. //
  1500. // Resize the dialog.
  1501. //
  1502. GetWindowRect(hBtnYep, &aRtYep);
  1503. MapWindowPoints(NULL, hDlg, (LPPOINT)&aRtYep, 2);
  1504. MoveWindow( hDlg,
  1505. aRtDlg.left,
  1506. aRtDlg.top,
  1507. aRtDlg.right,
  1508. (aRtYep.bottom - DlgTop) + GapHeight,
  1509. FALSE );
  1510. //
  1511. // Hide all other print dlg items.
  1512. //
  1513. // NOTE: Need to do a SetWindowPos to actually remove
  1514. // the window so that the AddNetButton call does
  1515. // not think it's there.
  1516. //
  1517. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_X_TOFILE),
  1518. NULL,
  1519. 0, 0, 0, 0,
  1520. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1521. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_X_COLLATE),
  1522. NULL,
  1523. 0, 0, 0, 0,
  1524. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1525. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_E_FROM),
  1526. NULL,
  1527. 0, 0, 0, 0,
  1528. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1529. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_E_TO),
  1530. NULL,
  1531. 0, 0, 0, 0,
  1532. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1533. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_E_COPIES),
  1534. NULL,
  1535. 0, 0, 0, 0,
  1536. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1537. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_G_RANGE),
  1538. NULL,
  1539. 0, 0, 0, 0,
  1540. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1541. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_G_COPIES),
  1542. NULL,
  1543. 0, 0, 0, 0,
  1544. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1545. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_I_COLLATE),
  1546. NULL,
  1547. 0, 0, 0, 0,
  1548. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1549. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_R_ALL),
  1550. NULL,
  1551. 0, 0, 0, 0,
  1552. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1553. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_R_SELECTION),
  1554. NULL,
  1555. 0, 0, 0, 0,
  1556. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1557. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_R_PAGES),
  1558. NULL,
  1559. 0, 0, 0, 0,
  1560. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1561. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_S_FROM),
  1562. NULL,
  1563. 0, 0, 0, 0,
  1564. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1565. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_S_TO),
  1566. NULL,
  1567. 0, 0, 0, 0,
  1568. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1569. SetWindowPos( GetDlgItem(hDlg, ID_PRINT_S_COPIES),
  1570. NULL,
  1571. 0, 0, 0, 0,
  1572. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
  1573. //
  1574. // Enlarge the comment edit control, since the
  1575. // "print to file" check box is hidden.
  1576. //
  1577. GetWindowRect(GetDlgItem(hDlg, ID_BOTH_S_WHERE), &aRtWhere);
  1578. GetWindowRect( hCtl = GetDlgItem(hDlg, ID_BOTH_S_COMMENT),
  1579. &aRtCmmnt );
  1580. MapWindowPoints(NULL, hDlg, (LPPOINT)&aRtCmmnt, 2);
  1581. MoveWindow( hCtl,
  1582. aRtCmmnt.left,
  1583. aRtCmmnt.top,
  1584. aRtWhere.right - aRtWhere.left,
  1585. aRtWhere.bottom - aRtWhere.top,
  1586. FALSE );
  1587. #ifdef WINNT
  1588. //
  1589. // Add or hide net button, if necessary.
  1590. //
  1591. if ((pPD->Flags & PD_NONETWORKBUTTON))
  1592. {
  1593. if (hCtl = GetDlgItem(hDlg, ID_BOTH_P_NETWORK))
  1594. {
  1595. EnableWindow(hCtl, FALSE);
  1596. ShowWindow(hCtl, SW_HIDE);
  1597. }
  1598. }
  1599. else
  1600. {
  1601. AddNetButton( hDlg,
  1602. g_hinst,
  1603. FILE_BOTTOM_MARGIN,
  1604. TRUE,
  1605. FALSE,
  1606. TRUE);
  1607. //
  1608. // The button can be added in two ways -
  1609. // statically (they have it predefined in their template) and
  1610. // dynamically (successful call to AddNetButton).
  1611. //
  1612. if (!IsNetworkInstalled())
  1613. {
  1614. hCtl = GetDlgItem(hDlg, ID_BOTH_P_NETWORK);
  1615. EnableWindow(hCtl, FALSE);
  1616. ShowWindow(hCtl, SW_HIDE);
  1617. }
  1618. }
  1619. #endif
  1620. }
  1621. else
  1622. {
  1623. if (pPD->Flags & PD_COLLATE)
  1624. {
  1625. pPI->Status |= PI_COLLATE_REQUESTED;
  1626. }
  1627. }
  1628. if (!PrintInitGeneral(hDlg, ID_PRINT_C_NAME, pPI) ||
  1629. ((dwResult = PrintInitPrintDlg( hDlg,
  1630. wParam,
  1631. pPI )) == 0xFFFFFFFF))
  1632. {
  1633. RemoveProp(hDlg, PRNPROP);
  1634. EndDialog(hDlg, -2);
  1635. }
  1636. HourGlass(FALSE);
  1637. bResult = (dwResult == 1);
  1638. return (bResult);
  1639. }
  1640. case ( WM_COMMAND ) :
  1641. {
  1642. if (!pPI)
  1643. {
  1644. return (FALSE);
  1645. }
  1646. bResult = FALSE;
  1647. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1648. {
  1649. case ( ID_PRINT_C_NAME ) : // Printer Name combobox
  1650. {
  1651. if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE)
  1652. {
  1653. PrintPrinterChanged(hDlg, ID_PRINT_C_NAME, pPI);
  1654. }
  1655. else if ( (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_DROPDOWN) &&
  1656. !(pPI->Status & PI_PRINTERS_ENUMERATED) )
  1657. {
  1658. //
  1659. // Enumerate printers if this hasn't been done yet.
  1660. //
  1661. PrintEnumAndSelect( hDlg,
  1662. ID_PRINT_C_NAME,
  1663. pPI,
  1664. (pPI->pCurPrinter)
  1665. ? pPI->pCurPrinter->pPrinterName
  1666. : NULL,
  1667. TRUE );
  1668. }
  1669. break;
  1670. }
  1671. case ( ID_BOTH_P_PROPERTIES ) : // Properties... button
  1672. {
  1673. PrintChangeProperties(hDlg, ID_PRINT_C_NAME, pPI);
  1674. break;
  1675. }
  1676. case ( ID_PRINT_P_SETUP ) : // Setup... button
  1677. {
  1678. DWORD dwFlags = pPD->Flags;
  1679. HWND hwndOwner = pPD->hwndOwner;
  1680. pPD->Flags |= PD_PRINTSETUP;
  1681. pPD->Flags &= ~(PD_RETURNDC | PD_RETURNIC);
  1682. pPI->Status |= PI_PRINTDLGX_RECURSE;
  1683. pPD->hwndOwner = hDlg;
  1684. if (PrintDlgX(pPI))
  1685. {
  1686. if (!PrintInitBannerAndQuality(hDlg, pPI, pPD))
  1687. {
  1688. StoreExtendedError(CDERR_GENERALCODES);
  1689. }
  1690. }
  1691. pPI->Status &= ~PI_PRINTDLGX_RECURSE;
  1692. pPD->Flags = dwFlags;
  1693. pPD->hwndOwner = hwndOwner;
  1694. break;
  1695. }
  1696. case ( ID_PRINT_R_ALL ) : // Print Range - All
  1697. case ( ID_PRINT_R_SELECTION ) : // Print Range - Selection
  1698. case ( ID_PRINT_R_PAGES ) : // Print Range - Pages (From, To)
  1699. {
  1700. CheckRadioButton( hDlg,
  1701. ID_PRINT_R_ALL,
  1702. ID_PRINT_R_PAGES,
  1703. GET_WM_COMMAND_ID(wParam, lParam) );
  1704. //
  1705. // Only move the the focus to the "From" control when
  1706. // the up/down arrow is NOT used.
  1707. //
  1708. if ( !IS_KEY_PRESSED(VK_UP) &&
  1709. !IS_KEY_PRESSED(VK_DOWN) &&
  1710. ((BOOL)(GET_WM_COMMAND_ID(wParam, lParam) == ID_PRINT_R_PAGES)) )
  1711. {
  1712. SendMessage( hDlg,
  1713. WM_NEXTDLGCTL,
  1714. (WPARAM)GetDlgItem(hDlg, ID_PRINT_E_FROM),
  1715. 1L );
  1716. }
  1717. break;
  1718. }
  1719. case ( ID_PRINT_E_FROM ) : // From (Print Range - Pages)
  1720. {
  1721. //
  1722. // Only enable the "To" control if the "From" control
  1723. // contains a value.
  1724. //
  1725. GetDlgItemInt(hDlg, ID_PRINT_E_FROM, &bTest, FALSE);
  1726. EnableWindow(GetDlgItem(hDlg, ID_PRINT_S_TO), bTest);
  1727. EnableWindow(GetDlgItem(hDlg, ID_PRINT_E_TO), bTest);
  1728. // FALL THRU...
  1729. }
  1730. case ( ID_PRINT_E_TO ) : // To (Print Range - Pages)
  1731. {
  1732. if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE)
  1733. {
  1734. CheckRadioButton( hDlg,
  1735. ID_PRINT_R_ALL,
  1736. ID_PRINT_R_PAGES,
  1737. ID_PRINT_R_PAGES );
  1738. }
  1739. break;
  1740. }
  1741. case (ID_PRINT_E_COPIES ) :
  1742. {
  1743. if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE)
  1744. {
  1745. BOOL bTest;
  1746. //
  1747. // Save the number of copies.
  1748. //
  1749. DWORD nCopies = GetDlgItemInt(hDlg, ID_PRINT_E_COPIES, &bTest, FALSE);
  1750. //
  1751. // If the copy count is > 1, enable collate. Otherwise,
  1752. // disable it.
  1753. //
  1754. if (hCtl = GetDlgItem(hDlg, ID_PRINT_X_COLLATE))
  1755. {
  1756. EnableWindow(hCtl, (nCopies > 1));
  1757. }
  1758. }
  1759. break;
  1760. }
  1761. case ( ID_PRINT_X_COLLATE ) : // Collate check box
  1762. {
  1763. if (hCtl = GetDlgItem(hDlg, ID_PRINT_I_COLLATE))
  1764. {
  1765. ShowWindow(hCtl, SW_HIDE);
  1766. SendMessage( hCtl,
  1767. STM_SETICON,
  1768. IsDlgButtonChecked(hDlg, ID_PRINT_X_COLLATE)
  1769. ? (LONG_PTR)hIconCollate
  1770. : (LONG_PTR)hIconNoCollate,
  1771. 0L );
  1772. ShowWindow(hCtl, SW_SHOW);
  1773. if (IsDlgButtonChecked(hDlg, ID_PRINT_X_COLLATE))
  1774. {
  1775. pPI->Status |= PI_COLLATE_REQUESTED;
  1776. }
  1777. else
  1778. {
  1779. pPI->Status &= ~PI_COLLATE_REQUESTED;
  1780. }
  1781. }
  1782. break;
  1783. }
  1784. case ( ID_BOTH_P_NETWORK ) : // Network... button
  1785. {
  1786. #ifdef WINNT
  1787. HANDLE hPrinter;
  1788. DWORD cbPrinter = 0;
  1789. PPRINTER_INFO_2 pPrinter = NULL;
  1790. hPrinter = (HANDLE)ConnectToPrinterDlg(hDlg, 0);
  1791. if (hPrinter)
  1792. {
  1793. if (!GetPrinter( hPrinter,
  1794. 2,
  1795. (LPBYTE)pPrinter,
  1796. cbPrinter,
  1797. &cbPrinter ))
  1798. {
  1799. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  1800. {
  1801. if (pPrinter = LocalAlloc(LPTR, cbPrinter))
  1802. {
  1803. if (!GetPrinter( hPrinter,
  1804. 2,
  1805. (LPBYTE)pPrinter,
  1806. cbPrinter,
  1807. &cbPrinter ))
  1808. {
  1809. StoreExtendedError(PDERR_PRINTERNOTFOUND);
  1810. }
  1811. else
  1812. {
  1813. SendDlgItemMessage( hDlg,
  1814. ID_PRINT_C_NAME,
  1815. CB_RESETCONTENT,
  1816. 0,
  1817. 0 );
  1818. PrintEnumAndSelect( hDlg,
  1819. ID_PRINT_C_NAME,
  1820. pPI,
  1821. pPrinter->pPrinterName,
  1822. TRUE );
  1823. }
  1824. }
  1825. else
  1826. {
  1827. StoreExtendedError(CDERR_MEMALLOCFAILURE);
  1828. }
  1829. }
  1830. else
  1831. {
  1832. StoreExtendedError(PDERR_SETUPFAILURE);
  1833. }
  1834. }
  1835. if (!GetStoredExtendedError())
  1836. {
  1837. SendDlgItemMessage( hDlg,
  1838. ID_PRINT_C_NAME,
  1839. CB_SETCURSEL,
  1840. (WPARAM)SendDlgItemMessage(
  1841. hDlg,
  1842. ID_PRINT_C_NAME,
  1843. CB_FINDSTRING,
  1844. 0,
  1845. (LPARAM)pPrinter->pPrinterName ),
  1846. (LPARAM)0 );
  1847. PrintPrinterChanged(hDlg, ID_PRINT_C_NAME, pPI);
  1848. }
  1849. LocalFree(pPrinter);
  1850. ClosePrinter(hPrinter);
  1851. }
  1852. #else
  1853. WNetConnectionDialog(hDlg, RESOURCETYPE_PRINT);
  1854. #endif
  1855. break;
  1856. }
  1857. case ( ID_BOTH_P_HELP ) : // Help button
  1858. {
  1859. #ifdef UNICODE
  1860. if (pPI->ApiType == COMDLG_ANSI)
  1861. {
  1862. if (msgHELPA && pPD->hwndOwner)
  1863. {
  1864. SendMessage( pPD->hwndOwner,
  1865. msgHELPA,
  1866. (WPARAM)hDlg,
  1867. (DWORD_PTR)pPI->pPDA );
  1868. }
  1869. }
  1870. else
  1871. #endif
  1872. {
  1873. if (msgHELPW && pPD->hwndOwner)
  1874. {
  1875. SendMessage( pPD->hwndOwner,
  1876. msgHELPW,
  1877. (WPARAM)hDlg,
  1878. (DWORD_PTR)pPD );
  1879. }
  1880. }
  1881. break;
  1882. }
  1883. case ( IDOK ) : // OK button
  1884. {
  1885. bResult = TRUE;
  1886. if (!(pPI->pPSD))
  1887. {
  1888. pPD->Flags &= ~((DWORD)( PD_PRINTTOFILE |
  1889. PD_PAGENUMS |
  1890. PD_SELECTION |
  1891. PD_COLLATE ));
  1892. pPD->nCopies = (WORD)GetDlgItemInt( hDlg,
  1893. ID_PRINT_E_COPIES,
  1894. &bTest,
  1895. FALSE );
  1896. if ((!bTest) || (!pPD->nCopies))
  1897. {
  1898. PrintEditError( hDlg,
  1899. ID_PRINT_E_COPIES,
  1900. iszCopiesZero );
  1901. return (TRUE);
  1902. }
  1903. if (IsDlgButtonChecked(hDlg, ID_PRINT_R_SELECTION))
  1904. {
  1905. pPD->Flags |= PD_SELECTION;
  1906. }
  1907. else if (IsDlgButtonChecked(hDlg, ID_PRINT_R_PAGES))
  1908. {
  1909. //
  1910. // Check the "From" and "To" values.
  1911. //
  1912. pPD->Flags |= PD_PAGENUMS;
  1913. pPD->nFromPage = (WORD)GetDlgItemInt( hDlg,
  1914. ID_PRINT_E_FROM,
  1915. &bTest,
  1916. FALSE );
  1917. if (!bTest)
  1918. {
  1919. PrintEditError( hDlg,
  1920. ID_PRINT_E_FROM,
  1921. iszPageFromError );
  1922. return (TRUE);
  1923. }
  1924. pPD->nToPage = (WORD)GetDlgItemInt( hDlg,
  1925. ID_PRINT_E_TO,
  1926. &bTest,
  1927. FALSE );
  1928. if (!bTest)
  1929. {
  1930. TCHAR szBuf[PAGE_EDIT_SIZE + 1];
  1931. if (GetDlgItemText( hDlg,
  1932. ID_PRINT_E_TO,
  1933. szBuf,
  1934. PAGE_EDIT_SIZE + 1 ))
  1935. {
  1936. PrintEditError( hDlg,
  1937. ID_PRINT_E_TO,
  1938. iszPageToError );
  1939. return (TRUE);
  1940. }
  1941. else
  1942. {
  1943. pPD->nToPage = pPD->nFromPage;
  1944. }
  1945. }
  1946. if ( (pPD->nFromPage < pPD->nMinPage) ||
  1947. (pPD->nFromPage > pPD->nMaxPage) )
  1948. {
  1949. PrintEditError( hDlg,
  1950. ID_PRINT_E_FROM,
  1951. iszPageRangeError,
  1952. pPD->nMinPage,
  1953. pPD->nMaxPage );
  1954. return (TRUE);
  1955. }
  1956. if ( (pPD->nToPage < pPD->nMinPage) ||
  1957. (pPD->nToPage > pPD->nMaxPage) )
  1958. {
  1959. PrintEditError( hDlg,
  1960. ID_PRINT_E_TO,
  1961. iszPageRangeError,
  1962. pPD->nMinPage,
  1963. pPD->nMaxPage );
  1964. return (TRUE);
  1965. }
  1966. if (pPD->nFromPage > pPD->nToPage)
  1967. {
  1968. PrintEditError( hDlg,
  1969. ID_PRINT_E_FROM,
  1970. iszFromToError );
  1971. return (TRUE);
  1972. }
  1973. }
  1974. }
  1975. HourGlass(TRUE);
  1976. if (IsDlgButtonChecked(hDlg, ID_PRINT_X_TOFILE))
  1977. {
  1978. pPD->Flags |= PD_PRINTTOFILE;
  1979. }
  1980. if ( (hCtl = GetDlgItem(hDlg, ID_PRINT_X_COLLATE)) &&
  1981. IsWindowEnabled(hCtl) &&
  1982. IsDlgButtonChecked(hDlg, ID_PRINT_X_COLLATE) )
  1983. {
  1984. pPD->Flags |= PD_COLLATE;
  1985. }
  1986. if (!PrintSetCopies(hDlg, pPI, ID_PRINT_C_NAME))
  1987. {
  1988. HourGlass(FALSE);
  1989. return (TRUE);
  1990. }
  1991. pDM = NULL;
  1992. pDN = NULL;
  1993. if (pPD->hDevMode)
  1994. {
  1995. pDM = GlobalLock(pPD->hDevMode);
  1996. }
  1997. if (pPD->hDevNames)
  1998. {
  1999. pDN = GlobalLock(pPD->hDevNames);
  2000. }
  2001. if (pDM && pDN)
  2002. {
  2003. DWORD nNum;
  2004. if ( GetDlgItem(hDlg, ID_PRINT_C_QUALITY) &&
  2005. (nNum = (DWORD) SendDlgItemMessage( hDlg,
  2006. ID_PRINT_C_QUALITY,
  2007. CB_GETCURSEL,
  2008. 0,
  2009. 0L )) != CB_ERR )
  2010. {
  2011. pDM->dmPrintQuality =
  2012. (WORD)SendDlgItemMessage( hDlg,
  2013. ID_PRINT_C_QUALITY,
  2014. CB_GETITEMDATA,
  2015. (WPARAM)nNum,
  2016. 0L );
  2017. }
  2018. PrintReturnICDC(pPD, pDN, pDM);
  2019. }
  2020. if (pDM)
  2021. {
  2022. GlobalUnlock(pPD->hDevMode);
  2023. }
  2024. if (pDN)
  2025. {
  2026. GlobalUnlock(pPD->hDevNames);
  2027. }
  2028. #ifdef UNICODE
  2029. if (pPD->Flags & CD_WOWAPP)
  2030. {
  2031. UpdateSpoolerInfo(pPI);
  2032. }
  2033. #endif
  2034. // FALL THRU...
  2035. }
  2036. case ( IDCANCEL ) : // Cancel button
  2037. case ( IDABORT ) :
  2038. {
  2039. HourGlass(TRUE);
  2040. glpfnPrintHook = GETPRINTHOOKFN(pPD);
  2041. RemoveProp(hDlg, PRNPROP);
  2042. EndDialog(hDlg, bResult);
  2043. HourGlass(FALSE);
  2044. break;
  2045. }
  2046. default :
  2047. {
  2048. return (FALSE);
  2049. break;
  2050. }
  2051. }
  2052. break;
  2053. }
  2054. case ( WM_MEASUREITEM ) :
  2055. {
  2056. PrintMeasureItem(hDlg, (LPMEASUREITEMSTRUCT)lParam);
  2057. break;
  2058. }
  2059. case ( WM_HELP ) :
  2060. {
  2061. if (IsWindowEnabled(hDlg))
  2062. {
  2063. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  2064. NULL,
  2065. HELP_WM_HELP,
  2066. (ULONG_PTR)(LPTSTR)aPrintHelpIDs );
  2067. }
  2068. break;
  2069. }
  2070. case ( WM_CONTEXTMENU ) :
  2071. {
  2072. if (IsWindowEnabled(hDlg))
  2073. {
  2074. WinHelp( (HWND)wParam,
  2075. NULL,
  2076. HELP_CONTEXTMENU,
  2077. (ULONG_PTR)(LPVOID)aPrintHelpIDs );
  2078. }
  2079. break;
  2080. }
  2081. case ( WM_CTLCOLOREDIT ) :
  2082. {
  2083. if (GetWindowLong((HWND)lParam, GWL_STYLE) & ES_READONLY)
  2084. {
  2085. return ( (BOOL_PTR) SendMessage(hDlg, WM_CTLCOLORDLG, wParam, lParam) );
  2086. }
  2087. // FALL THRU...
  2088. }
  2089. default :
  2090. {
  2091. return (FALSE);
  2092. break;
  2093. }
  2094. }
  2095. return (TRUE);
  2096. }
  2097. ////////////////////////////////////////////////////////////////////////////
  2098. //
  2099. // PrintSetupDlgProc
  2100. //
  2101. // Print Setup Dialog proc.
  2102. //
  2103. ////////////////////////////////////////////////////////////////////////////
  2104. BOOL_PTR CALLBACK PrintSetupDlgProc(
  2105. HWND hDlg,
  2106. UINT wMsg,
  2107. WPARAM wParam,
  2108. LPARAM lParam)
  2109. {
  2110. PPRINTINFO pPI;
  2111. LPPRINTDLG pPD = NULL;
  2112. BOOL_PTR bResult;
  2113. UINT uCmdId;
  2114. LPDEVMODE pDM;
  2115. if (pPI = (PPRINTINFO)GetProp(hDlg, PRNPROP))
  2116. {
  2117. if ((pPD = pPI->pPD) && (pPD->lpfnSetupHook))
  2118. {
  2119. LPSETUPHOOKPROC lpfnSetupHook = GETSETUPHOOKFN(pPD);
  2120. #ifdef UNICODE
  2121. if (pPI->ApiType == COMDLG_ANSI)
  2122. {
  2123. ThunkPrintDlgW2A(pPI);
  2124. TransferPDA2PSD(pPI);
  2125. pPI->NestCtr++;
  2126. bResult = (*lpfnSetupHook)(hDlg, wMsg, wParam, lParam);
  2127. pPI->NestCtr--;
  2128. if (bResult)
  2129. {
  2130. TransferPSD2PDA(pPI);
  2131. ThunkPrintDlgA2W(pPI);
  2132. if (pPI->NestCtr == 0)
  2133. {
  2134. TransferPD2PSD(pPI);
  2135. }
  2136. return (bResult);
  2137. }
  2138. }
  2139. else
  2140. #endif
  2141. {
  2142. TransferPD2PSD(pPI);
  2143. bResult = (*lpfnSetupHook)(hDlg, wMsg, wParam, lParam);
  2144. if (bResult)
  2145. {
  2146. TransferPSD2PD(pPI);
  2147. return (bResult);
  2148. }
  2149. }
  2150. }
  2151. }
  2152. else if (glpfnSetupHook &&
  2153. (wMsg != WM_INITDIALOG) &&
  2154. (bResult = (*glpfnSetupHook)(hDlg, wMsg, wParam, lParam)))
  2155. {
  2156. return (bResult);
  2157. }
  2158. switch (wMsg)
  2159. {
  2160. case ( WM_INITDIALOG ) :
  2161. {
  2162. DWORD dwResult = 0;
  2163. //
  2164. // Disable RTL mirroring on the WHITE-SAMPLE
  2165. //
  2166. SetWindowLong(GetDlgItem(hDlg, ID_SETUP_W_SAMPLE),
  2167. GWL_EXSTYLE,
  2168. GetWindowLong(GetDlgItem(hDlg, ID_SETUP_W_SAMPLE), GWL_EXSTYLE) & ~RTL_MIRRORED_WINDOW);
  2169. HourGlass(TRUE);
  2170. #ifndef WINNT
  2171. msgHELPA = RegisterWindowMessage(szCommdlgHelp);
  2172. #endif
  2173. SetProp(hDlg, PRNPROP, (HANDLE)lParam);
  2174. pPI = (PPRINTINFO)lParam;
  2175. pPI->bKillFocus = FALSE;
  2176. glpfnSetupHook = NULL;
  2177. if (!PrintInitGeneral(hDlg, ID_SETUP_C_NAME, pPI) ||
  2178. ((dwResult = PrintInitSetupDlg( hDlg,
  2179. wParam,
  2180. pPI )) == 0xFFFFFFFF))
  2181. {
  2182. RemoveProp(hDlg, PRNPROP);
  2183. EndDialog(hDlg, FALSE);
  2184. }
  2185. else if (pPI->pPSD && (pPI->pPSD->Flags & PSD_RETURNDEFAULT))
  2186. {
  2187. //
  2188. // PSD_RETURNDEFAULT goes through the entire initialization
  2189. // in order to set rtMinMargin, rtMargin, and ptPaperSize.
  2190. // Win95 Notepad relies on this behavior.
  2191. //
  2192. SendMessage(hDlg, WM_COMMAND, IDOK, 0);
  2193. }
  2194. HourGlass(FALSE);
  2195. bResult = (dwResult == 1);
  2196. return (bResult);
  2197. }
  2198. case ( WM_COMMAND ) :
  2199. {
  2200. if (!pPI)
  2201. {
  2202. return (FALSE);
  2203. }
  2204. bResult = FALSE;
  2205. switch (uCmdId = GET_WM_COMMAND_ID(wParam, lParam))
  2206. {
  2207. case ( ID_SETUP_C_NAME ) : // Printer Name combobox
  2208. {
  2209. if ( (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_DROPDOWN) &&
  2210. !(pPI->Status & PI_PRINTERS_ENUMERATED) )
  2211. {
  2212. //
  2213. // Enumerate printers if this hasn't been done yet.
  2214. //
  2215. PrintEnumAndSelect( hDlg,
  2216. ID_SETUP_C_NAME,
  2217. pPI,
  2218. (pPI->pCurPrinter)
  2219. ? pPI->pCurPrinter->pPrinterName
  2220. : NULL,
  2221. TRUE );
  2222. }
  2223. if (GET_WM_COMMAND_CMD(wParam, lParam) != CBN_SELCHANGE)
  2224. {
  2225. break;
  2226. }
  2227. if ( !GetDlgItem(hDlg, ID_SETUP_R_SPECIFIC) ||
  2228. IsDlgButtonChecked(hDlg, ID_SETUP_R_SPECIFIC) )
  2229. {
  2230. PrintPrinterChanged(hDlg, ID_SETUP_C_NAME, pPI);
  2231. break;
  2232. }
  2233. uCmdId = ID_SETUP_R_SPECIFIC;
  2234. // FALL THRU...
  2235. }
  2236. case ( ID_SETUP_R_DEFAULT ) : // Default printer
  2237. case ( ID_SETUP_R_SPECIFIC ) : // Specific printer
  2238. {
  2239. //
  2240. // Sanity check for Publisher bug where user tries to
  2241. // set focus to ID_SETUP_R_DEFAULT on exit if the
  2242. // dialog has no default printer.
  2243. //
  2244. if (pPI->hCurPrinter)
  2245. {
  2246. HWND hCmb;
  2247. DWORD dwStyle;
  2248. hCmb = GetDlgItem(hDlg, ID_SETUP_C_NAME);
  2249. if (hCmb && (uCmdId == ID_SETUP_R_DEFAULT))
  2250. {
  2251. if (!(pPI->Status & PI_PRINTERS_ENUMERATED))
  2252. {
  2253. //
  2254. // Enumerate printers if this hasn't been
  2255. // done yet. Otherwise, the default printer
  2256. // may not be found in the list box when
  2257. // switching from Specific to Default.
  2258. //
  2259. PrintEnumAndSelect( hDlg,
  2260. ID_SETUP_C_NAME,
  2261. pPI,
  2262. NULL,
  2263. TRUE );
  2264. }
  2265. SendMessage( hCmb,
  2266. CB_SETCURSEL,
  2267. (WPARAM)SendMessage(
  2268. hCmb,
  2269. CB_FINDSTRINGEXACT,
  2270. (WPARAM)-1,
  2271. (LPARAM)(pPI->szDefaultPrinter) ),
  2272. (LPARAM)0 );
  2273. }
  2274. PrintPrinterChanged(hDlg, ID_SETUP_C_NAME, pPI);
  2275. CheckRadioButton( hDlg,
  2276. ID_SETUP_R_DEFAULT,
  2277. ID_SETUP_R_SPECIFIC,
  2278. uCmdId);
  2279. dwStyle = GetWindowLong(hCmb, GWL_STYLE);
  2280. if (uCmdId == ID_SETUP_R_DEFAULT)
  2281. {
  2282. dwStyle &= ~WS_TABSTOP;
  2283. }
  2284. else
  2285. {
  2286. dwStyle |= WS_TABSTOP;
  2287. SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)hCmb, 1L);
  2288. }
  2289. SetWindowLong(hCmb, GWL_STYLE, dwStyle);
  2290. }
  2291. break;
  2292. }
  2293. case ( ID_BOTH_P_PROPERTIES ) : // Properties... button
  2294. {
  2295. PrintChangeProperties(hDlg, ID_SETUP_C_NAME, pPI);
  2296. break;
  2297. }
  2298. case ( ID_SETUP_P_MORE ) : // More... button
  2299. {
  2300. pDM = GlobalLock(pPD->hDevMode);
  2301. AdvancedDocumentProperties( hDlg,
  2302. pPI->hCurPrinter,
  2303. (pPI->pCurPrinter)
  2304. ? pPI->pCurPrinter->pPrinterName
  2305. : NULL,
  2306. pDM,
  2307. pDM );
  2308. GlobalUnlock(pPD->hDevMode);
  2309. SendMessage( hDlg,
  2310. WM_NEXTDLGCTL,
  2311. (WPARAM)GetDlgItem(hDlg, IDOK),
  2312. 1L );
  2313. break;
  2314. }
  2315. case ( ID_SETUP_R_PORTRAIT ) : // Portrait
  2316. case ( ID_SETUP_R_LANDSCAPE ) : // Landscape
  2317. {
  2318. if ((pPD->hDevMode) && (pDM = GlobalLock(pPD->hDevMode)))
  2319. {
  2320. PrintSetOrientation( hDlg,
  2321. pPI,
  2322. pDM,
  2323. pPI->uiOrientationID,
  2324. uCmdId );
  2325. GlobalUnlock(pPD->hDevMode);
  2326. }
  2327. // FALL THRU ...
  2328. }
  2329. case ( ID_SETUP_R_NONE ) : // None (2-Sided)
  2330. case ( ID_SETUP_R_LONG ) : // Long Side (2-Sided)
  2331. case ( ID_SETUP_R_SHORT ) : // Short Side (2-Sided)
  2332. {
  2333. if ((pPD->hDevMode) && (pDM = GlobalLock(pPD->hDevMode)))
  2334. {
  2335. PrintSetDuplex(hDlg, pDM, uCmdId);
  2336. GlobalUnlock(pPD->hDevMode);
  2337. }
  2338. break;
  2339. }
  2340. case ( ID_SETUP_C_SIZE ) : // Size combobox
  2341. {
  2342. UINT Orientation;
  2343. if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE)
  2344. {
  2345. if ((pPD->hDevMode) && (pDM = GlobalLock(pPD->hDevMode)))
  2346. {
  2347. // pDM->dmFields |= DM_PAPERSIZE;
  2348. pDM->dmPaperSize =
  2349. (SHORT)SendMessage( (HWND)lParam,
  2350. CB_GETITEMDATA,
  2351. SendMessage( (HWND)lParam,
  2352. CB_GETCURSEL,
  2353. 0,
  2354. 0L ),
  2355. 0L );
  2356. Orientation =
  2357. IsDlgButtonChecked(hDlg, ID_SETUP_R_PORTRAIT)
  2358. ? ID_SETUP_R_PORTRAIT
  2359. : ID_SETUP_R_LANDSCAPE;
  2360. PrintSetOrientation( hDlg,
  2361. pPI,
  2362. pDM,
  2363. Orientation,
  2364. Orientation );
  2365. GlobalUnlock(pPD->hDevMode);
  2366. }
  2367. }
  2368. break;
  2369. }
  2370. case ( ID_SETUP_C_SOURCE ) : // Source combobox
  2371. {
  2372. if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE)
  2373. {
  2374. if ((pPD->hDevMode) && (pDM = GlobalLock(pPD->hDevMode)))
  2375. {
  2376. // pDM->dmFields |= DM_DEFAULTSOURCE;
  2377. pDM->dmDefaultSource =
  2378. (SHORT)SendMessage( (HWND)lParam,
  2379. CB_GETITEMDATA,
  2380. SendMessage( (HWND)lParam,
  2381. CB_GETCURSEL,
  2382. 0,
  2383. 0L ),
  2384. 0L );
  2385. GlobalUnlock(pPD->hDevMode);
  2386. }
  2387. }
  2388. break;
  2389. }
  2390. case ( ID_SETUP_E_LEFT ) : // Left (Margins)
  2391. case ( ID_SETUP_E_TOP ) : // Top (Margins)
  2392. case ( ID_SETUP_E_RIGHT ) : // Right (Margins)
  2393. case ( ID_SETUP_E_BOTTOM ) : // Bottom (Margins)
  2394. {
  2395. if (pPI->bKillFocus)
  2396. {
  2397. break;
  2398. }
  2399. switch (GET_WM_COMMAND_CMD(wParam, lParam))
  2400. {
  2401. case ( EN_KILLFOCUS ) :
  2402. {
  2403. pPI->bKillFocus = TRUE;
  2404. PrintSetMargin( hDlg,
  2405. pPI,
  2406. uCmdId,
  2407. *((LONG*)&pPI->pPSD->rtMargin +
  2408. uCmdId - ID_SETUP_E_LEFT) );
  2409. pPI->bKillFocus = FALSE;
  2410. break;
  2411. }
  2412. case ( EN_CHANGE ) :
  2413. {
  2414. HWND hSample;
  2415. PrintGetMargin( GET_WM_COMMAND_HWND(wParam, lParam),
  2416. pPI,
  2417. *((LONG*)&pPI->pPSD->rtMinMargin +
  2418. uCmdId - ID_SETUP_E_LEFT),
  2419. (LONG*)&pPI->pPSD->rtMargin +
  2420. uCmdId - ID_SETUP_E_LEFT,
  2421. (LONG*)&pPI->RtMarginMMs +
  2422. uCmdId - ID_SETUP_E_LEFT );
  2423. if (hSample = GetDlgItem(hDlg, ID_SETUP_W_SAMPLE))
  2424. {
  2425. RECT rect;
  2426. GetClientRect(hSample, &rect);
  2427. InflateRect(&rect, -1, -1);
  2428. InvalidateRect(hSample, &rect, TRUE);
  2429. }
  2430. break;
  2431. }
  2432. }
  2433. break;
  2434. }
  2435. case ( ID_SETUP_P_PRINTER ) : // Printer... button
  2436. {
  2437. //
  2438. // Save a copy of the original values.
  2439. //
  2440. HWND hwndOwner = pPD->hwndOwner;
  2441. DWORD dwFlags = pPD->Flags;
  2442. HINSTANCE hInstance = pPD->hInstance;
  2443. LPCTSTR lpPrintTemplateName = pPD->lpPrintTemplateName;
  2444. //
  2445. // Set up pPI so that PrintDlgX can do all the work.
  2446. //
  2447. pPD->hwndOwner = hDlg;
  2448. pPD->Flags &= ~( PD_ENABLEPRINTTEMPLATEHANDLE |
  2449. PD_RETURNIC |
  2450. PD_RETURNDC |
  2451. PD_PAGESETUP );
  2452. pPD->Flags |= PD_ENABLEPRINTTEMPLATE;
  2453. pPD->hInstance = g_hinst;
  2454. pPD->lpPrintTemplateName = MAKEINTRESOURCE(PRINTDLGORD);
  2455. pPI->Status |= PI_PRINTDLGX_RECURSE;
  2456. if (PrintDlgX(pPI))
  2457. {
  2458. PrintUpdateSetupDlg( hDlg,
  2459. pPI,
  2460. GlobalLock(pPD->hDevMode),
  2461. TRUE );
  2462. GlobalUnlock(pPD->hDevMode);
  2463. }
  2464. //
  2465. // Restore the original values.
  2466. //
  2467. pPD->hwndOwner = hwndOwner;
  2468. pPD->Flags = dwFlags;
  2469. pPD->hInstance = hInstance;
  2470. pPD->lpPrintTemplateName = lpPrintTemplateName;
  2471. pPI->Status &= ~PI_PRINTDLGX_RECURSE;
  2472. //
  2473. // Set the keyboard focus to the OK button.
  2474. //
  2475. SendMessage( hDlg,
  2476. WM_NEXTDLGCTL,
  2477. (WPARAM)GetDlgItem(hDlg, IDOK),
  2478. 1L );
  2479. HourGlass(FALSE);
  2480. break;
  2481. }
  2482. case ( ID_BOTH_P_NETWORK ) : // Network... button
  2483. {
  2484. #ifdef WINNT
  2485. HANDLE hPrinter;
  2486. DWORD cbPrinter = 0;
  2487. PPRINTER_INFO_2 pPrinter = NULL;
  2488. hPrinter = (HANDLE)ConnectToPrinterDlg(hDlg, 0);
  2489. if (hPrinter)
  2490. {
  2491. if (!GetPrinter( hPrinter,
  2492. 2,
  2493. (LPBYTE)pPrinter,
  2494. cbPrinter,
  2495. &cbPrinter ))
  2496. {
  2497. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  2498. {
  2499. if (pPrinter = LocalAlloc(LPTR, cbPrinter))
  2500. {
  2501. if (!GetPrinter( hPrinter,
  2502. 2,
  2503. (LPBYTE)pPrinter,
  2504. cbPrinter,
  2505. &cbPrinter ))
  2506. {
  2507. StoreExtendedError(PDERR_PRINTERNOTFOUND);
  2508. }
  2509. else
  2510. {
  2511. SendDlgItemMessage( hDlg,
  2512. ID_SETUP_C_NAME,
  2513. CB_RESETCONTENT,
  2514. 0,
  2515. 0 );
  2516. PrintEnumAndSelect( hDlg,
  2517. ID_SETUP_C_NAME,
  2518. pPI,
  2519. pPrinter->pPrinterName,
  2520. TRUE );
  2521. }
  2522. }
  2523. else
  2524. {
  2525. StoreExtendedError(CDERR_MEMALLOCFAILURE);
  2526. }
  2527. }
  2528. else
  2529. {
  2530. StoreExtendedError(PDERR_SETUPFAILURE);
  2531. }
  2532. }
  2533. if (!GetStoredExtendedError())
  2534. {
  2535. SendDlgItemMessage( hDlg,
  2536. ID_SETUP_C_NAME,
  2537. CB_SETCURSEL,
  2538. (WPARAM)SendDlgItemMessage(
  2539. hDlg,
  2540. ID_SETUP_C_NAME,
  2541. CB_FINDSTRING,
  2542. 0,
  2543. (LPARAM)pPrinter->pPrinterName ),
  2544. (LPARAM)0 );
  2545. PrintPrinterChanged(hDlg, ID_SETUP_C_NAME, pPI);
  2546. }
  2547. LocalFree(pPrinter);
  2548. ClosePrinter(hPrinter);
  2549. }
  2550. #else
  2551. WNetConnectionDialog(hDlg, RESOURCETYPE_PRINT);
  2552. #endif
  2553. break;
  2554. }
  2555. case ( ID_BOTH_P_HELP ) : // Help button
  2556. {
  2557. #ifdef UNICODE
  2558. if (pPI->ApiType == COMDLG_ANSI)
  2559. {
  2560. if (msgHELPA && pPD->hwndOwner)
  2561. {
  2562. SendMessage( pPD->hwndOwner,
  2563. msgHELPA,
  2564. (WPARAM)hDlg,
  2565. (LPARAM)pPI->pPDA );
  2566. }
  2567. }
  2568. else
  2569. #endif
  2570. {
  2571. if (msgHELPW && pPD->hwndOwner)
  2572. {
  2573. SendMessage( pPD->hwndOwner,
  2574. msgHELPW,
  2575. (WPARAM)hDlg,
  2576. (LPARAM)pPD );
  2577. }
  2578. }
  2579. break;
  2580. }
  2581. case ( IDOK ) : // OK button
  2582. {
  2583. LPPAGESETUPDLG pPSD = pPI->pPSD;
  2584. int i;
  2585. if (pPSD)
  2586. {
  2587. if ((pPSD->rtMinMargin.left + pPSD->rtMinMargin.right >
  2588. pPSD->ptPaperSize.x) ||
  2589. (pPSD->rtMinMargin.top + pPSD->rtMinMargin.bottom >
  2590. pPSD->ptPaperSize.y))
  2591. {
  2592. //
  2593. // This is an unprintable case that can happen.
  2594. // Let's assume that the driver is at fault
  2595. // and accept whatever the user entered.
  2596. //
  2597. }
  2598. else if (pPSD->rtMargin.left + pPSD->rtMargin.right >
  2599. pPSD->ptPaperSize.x)
  2600. {
  2601. i = (pPSD->rtMargin.left >= pPSD->rtMargin.right)
  2602. ? ID_SETUP_E_LEFT
  2603. : ID_SETUP_E_RIGHT;
  2604. PrintEditError(hDlg, i, iszBadMarginError);
  2605. return (TRUE);
  2606. }
  2607. else if (pPSD->rtMargin.top + pPSD->rtMargin.bottom >
  2608. pPSD->ptPaperSize.y)
  2609. {
  2610. i = (pPSD->rtMargin.top >= pPSD->rtMargin.bottom)
  2611. ? ID_SETUP_E_TOP
  2612. : ID_SETUP_E_BOTTOM;
  2613. PrintEditError(hDlg, i, iszBadMarginError);
  2614. return (TRUE);
  2615. }
  2616. }
  2617. else
  2618. {
  2619. HourGlass(TRUE);
  2620. if (!PrintSetCopies(hDlg, pPI, ID_SETUP_C_NAME))
  2621. {
  2622. HourGlass(FALSE);
  2623. return (TRUE);
  2624. }
  2625. }
  2626. bResult = TRUE;
  2627. SetFocus( GetDlgItem(hDlg, IDOK) );
  2628. // FALL THRU...
  2629. }
  2630. case ( IDCANCEL ) : // Cancel button
  2631. case ( IDABORT ) :
  2632. {
  2633. HourGlass(TRUE);
  2634. if (bResult)
  2635. {
  2636. PrintGetSetupInfo(hDlg, pPD);
  2637. #ifdef UNICODE
  2638. if (pPD->Flags & CD_WOWAPP)
  2639. {
  2640. UpdateSpoolerInfo(pPI);
  2641. }
  2642. #endif
  2643. }
  2644. else
  2645. {
  2646. SetFocus( GetDlgItem(hDlg, IDCANCEL) );
  2647. }
  2648. pPI->bKillFocus = TRUE;
  2649. glpfnSetupHook = GETSETUPHOOKFN(pPD);
  2650. RemoveProp(hDlg, PRNPROP);
  2651. EndDialog(hDlg, bResult);
  2652. HourGlass(FALSE);
  2653. break;
  2654. }
  2655. default :
  2656. {
  2657. return (FALSE);
  2658. break;
  2659. }
  2660. }
  2661. break;
  2662. }
  2663. case ( WM_MEASUREITEM ) :
  2664. {
  2665. PrintMeasureItem(hDlg, (LPMEASUREITEMSTRUCT)lParam);
  2666. break;
  2667. }
  2668. case ( WM_HELP ) :
  2669. {
  2670. if (IsWindowEnabled(hDlg))
  2671. {
  2672. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  2673. NULL,
  2674. HELP_WM_HELP,
  2675. (ULONG_PTR)(LPTSTR)( pPD && (pPD->Flags & PD_PRINTSETUP)
  2676. ? aPrintSetupHelpIDs
  2677. : aPageSetupHelpIDs) );
  2678. }
  2679. break;
  2680. }
  2681. case ( WM_CONTEXTMENU ) :
  2682. {
  2683. if (IsWindowEnabled(hDlg))
  2684. {
  2685. WinHelp( (HWND)wParam,
  2686. NULL,
  2687. HELP_CONTEXTMENU,
  2688. (ULONG_PTR)(LPVOID)( pPD && (pPD->Flags & PD_PRINTSETUP)
  2689. ? aPrintSetupHelpIDs
  2690. : aPageSetupHelpIDs) );
  2691. }
  2692. break;
  2693. }
  2694. case ( WM_CTLCOLOREDIT ) :
  2695. {
  2696. if (GetWindowLong((HWND)lParam, GWL_STYLE) & ES_READONLY)
  2697. {
  2698. return ( (BOOL_PTR) SendMessage(hDlg, WM_CTLCOLORDLG, wParam, lParam) );
  2699. }
  2700. // FALL THRU...
  2701. }
  2702. default :
  2703. {
  2704. return (FALSE);
  2705. break;
  2706. }
  2707. }
  2708. return (TRUE);
  2709. }
  2710. ////////////////////////////////////////////////////////////////////////////
  2711. //
  2712. // PrintEditMarginProc
  2713. //
  2714. ////////////////////////////////////////////////////////////////////////////
  2715. LRESULT PrintEditMarginProc(
  2716. HWND hWnd,
  2717. UINT msg,
  2718. WPARAM wP,
  2719. LPARAM lP)
  2720. {
  2721. if ( (msg == WM_CHAR) &&
  2722. (wP != BACKSPACE) &&
  2723. (wP != CTRL_X_CUT) &&
  2724. (wP != CTRL_C_COPY) &&
  2725. (wP != CTRL_V_PASTE) &&
  2726. (wP != (WPARAM)cIntlDecimal) &&
  2727. ((wP < TEXT('0')) || (wP > TEXT('9'))) )
  2728. {
  2729. MessageBeep(0);
  2730. return (FALSE);
  2731. }
  2732. return ( CallWindowProc(lpEditMarginProc, hWnd, msg, wP, lP) );
  2733. }
  2734. ////////////////////////////////////////////////////////////////////////////
  2735. //
  2736. // PrintPageSetupPaintProc
  2737. //
  2738. ////////////////////////////////////////////////////////////////////////////
  2739. LRESULT PrintPageSetupPaintProc(
  2740. HWND hWnd,
  2741. UINT msg,
  2742. WPARAM wP,
  2743. LPARAM lP)
  2744. {
  2745. LRESULT lResult;
  2746. PPRINTINFO pPI;
  2747. LPPAGESETUPDLG pPSD;
  2748. HDC hDC;
  2749. RECT aRt, aRtPage, aRtUser;
  2750. PAINTSTRUCT aPs;
  2751. HGDIOBJ hPen, hBr, hFont, hFontGreek;
  2752. HRGN hRgn;
  2753. 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");
  2754. LPTSTR psGreekText;
  2755. int i;
  2756. if (msg != WM_PAINT)
  2757. {
  2758. return ( CallWindowProc(lpStaticProc, hWnd, msg, wP, lP) );
  2759. }
  2760. hDC = BeginPaint(hWnd, &aPs);
  2761. GetClientRect(hWnd, &aRt);
  2762. FillRect(hDC, &aRt, (HBRUSH)GetStockObject(WHITE_BRUSH));
  2763. EndPaint(hWnd, &aPs);
  2764. lResult = 0;
  2765. if ( (!(hDC = GetDC(hWnd))) ||
  2766. (!(pPI = (PPRINTINFO)GetProp(GetParent(hWnd), PRNPROP))) )
  2767. {
  2768. return (0);
  2769. }
  2770. pPSD = pPI->pPSD;
  2771. TransferPD2PSD(pPI);
  2772. aRtPage = aRt;
  2773. hPen = (HGDIOBJ)CreatePen(PS_SOLID, 1, RGB(128, 128, 128));
  2774. hPen = SelectObject(hDC, hPen);
  2775. // Rectangle() does not work here
  2776. MoveToEx( hDC, 0 , 0 , NULL );
  2777. LineTo( hDC, aRt.right - 1, 0 );
  2778. MoveToEx( hDC, 0 , 1 , NULL );
  2779. LineTo( hDC, 0 , aRt.bottom - 1 );
  2780. DeleteObject(SelectObject(hDC, hPen));
  2781. // Rectangle() does not work here
  2782. MoveToEx( hDC, aRt.right - 1, 0 , NULL );
  2783. LineTo( hDC, aRt.right - 1, aRt.bottom - 1 );
  2784. MoveToEx( hDC, 0 , aRt.bottom - 1, NULL );
  2785. LineTo( hDC, aRt.right , aRt.bottom - 1 );
  2786. SetBkMode(hDC, TRANSPARENT);
  2787. hPen = (HGDIOBJ)CreatePen(PS_DOT, 1, RGB(128, 128, 128));
  2788. hPen = SelectObject(hDC, hPen);
  2789. hBr = (HGDIOBJ)GetStockObject(NULL_BRUSH);
  2790. hBr = SelectObject(hDC, hBr);
  2791. hFont = hFontGreek = CreateFont( pPI->PtMargins.y,
  2792. pPI->PtMargins.x,
  2793. 0,
  2794. 0,
  2795. FW_DONTCARE,
  2796. 0,
  2797. 0,
  2798. 0,
  2799. ANSI_CHARSET,
  2800. OUT_DEFAULT_PRECIS,
  2801. CLIP_DEFAULT_PRECIS,
  2802. DEFAULT_QUALITY,
  2803. VARIABLE_PITCH | FF_SWISS,
  2804. NULL );
  2805. hFont = SelectObject(hDC, hFont);
  2806. InflateRect(&aRt, -1, -1);
  2807. aRtUser = aRt;
  2808. hRgn = CreateRectRgnIndirect(&aRtUser);
  2809. SelectClipRgn(hDC, hRgn);
  2810. DeleteObject(hRgn);
  2811. if (pPSD->lpfnPagePaintHook)
  2812. {
  2813. WORD wFlags;
  2814. LPPAGEPAINTHOOK lpfnPagePaintHook = GETPAGEPAINTHOOKFN(pPSD);
  2815. switch (pPI->dwRotation)
  2816. {
  2817. default :
  2818. {
  2819. //
  2820. // Portrait mode only.
  2821. //
  2822. wFlags = 0x0000;
  2823. break;
  2824. }
  2825. case ( ROTATE_LEFT ) :
  2826. {
  2827. //
  2828. // Dot-Matrix (270)
  2829. //
  2830. wFlags = 0x0001;
  2831. break;
  2832. }
  2833. case ( ROTATE_RIGHT ) :
  2834. {
  2835. //
  2836. // HP PCL (90)
  2837. //
  2838. wFlags = 0x0003;
  2839. break;
  2840. }
  2841. }
  2842. if ( !wFlags ||
  2843. IsDlgButtonChecked(GetParent(hWnd), ID_SETUP_R_PORTRAIT) )
  2844. {
  2845. //
  2846. // Paper in portrait.
  2847. //
  2848. wFlags |= 0x0004;
  2849. }
  2850. if (pPI->pPD->Flags & PI_WPAPER_ENVELOPE)
  2851. {
  2852. wFlags |= 0x0008;
  2853. if (aRt.right < aRt.bottom)
  2854. {
  2855. //
  2856. // Envelope in portrait.
  2857. //
  2858. wFlags |= 0x0010;
  2859. }
  2860. }
  2861. if ((*lpfnPagePaintHook)( hWnd,
  2862. WM_PSD_PAGESETUPDLG,
  2863. MAKELONG(pPI->wPaper, wFlags),
  2864. (LPARAM)pPSD ) ||
  2865. (*lpfnPagePaintHook)( hWnd,
  2866. WM_PSD_FULLPAGERECT,
  2867. (WPARAM)hDC,
  2868. (LPARAM)(LPRECT)&aRtUser ))
  2869. {
  2870. goto NoMorePainting;
  2871. }
  2872. aRtUser = aRt;
  2873. aRtUser.left += aRtUser.right * pPI->RtMinMarginMMs.left / pPI->PtPaperSizeMMs.x;
  2874. aRtUser.top += aRtUser.bottom * pPI->RtMinMarginMMs.top / pPI->PtPaperSizeMMs.y;
  2875. aRtUser.right -= aRtUser.right * pPI->RtMinMarginMMs.right / pPI->PtPaperSizeMMs.x;
  2876. aRtUser.bottom -= aRtUser.bottom * pPI->RtMinMarginMMs.bottom / pPI->PtPaperSizeMMs.y;
  2877. if ((aRtUser.left < aRtUser.right) &&
  2878. (aRtUser.top < aRtUser.bottom) &&
  2879. (aRtUser.left > aRtPage.left) &&
  2880. (aRtUser.top > aRtPage.top) &&
  2881. (aRtUser.right < aRtPage.right) &&
  2882. (aRtUser.bottom < aRtPage.bottom))
  2883. {
  2884. hRgn = CreateRectRgnIndirect(&aRtUser);
  2885. SelectClipRgn(hDC, hRgn);
  2886. DeleteObject(hRgn);
  2887. if ((*lpfnPagePaintHook)( hWnd,
  2888. WM_PSD_MINMARGINRECT,
  2889. (WPARAM)hDC,
  2890. (LPARAM)(LPRECT)&aRtUser ))
  2891. {
  2892. goto NoMorePainting;
  2893. }
  2894. }
  2895. }
  2896. aRt.left += aRt.right * pPI->RtMarginMMs.left / pPI->PtPaperSizeMMs.x;
  2897. aRt.top += aRt.bottom * pPI->RtMarginMMs.top / pPI->PtPaperSizeMMs.y;
  2898. aRt.right -= aRt.right * pPI->RtMarginMMs.right / pPI->PtPaperSizeMMs.x;
  2899. aRt.bottom -= aRt.bottom * pPI->RtMarginMMs.bottom / pPI->PtPaperSizeMMs.y;
  2900. if ( (aRt.left > aRtPage.left) && (aRt.left < aRtPage.right) &&
  2901. (aRt.right < aRtPage.right) && (aRt.right > aRtPage.left) &&
  2902. (aRt.top > aRtPage.top) && (aRt.top < aRtPage.bottom) &&
  2903. (aRt.bottom < aRtPage.bottom) && (aRt.bottom > aRtPage.top) &&
  2904. (aRt.left < aRt.right) &&
  2905. (aRt.top < aRt.bottom) )
  2906. {
  2907. if (pPSD->lpfnPagePaintHook)
  2908. {
  2909. LPPAGEPAINTHOOK lpfnPagePaintHook = GETPAGEPAINTHOOKFN(pPSD);
  2910. aRtUser = aRt;
  2911. hRgn = CreateRectRgnIndirect(&aRtUser);
  2912. SelectClipRgn(hDC, hRgn);
  2913. DeleteObject(hRgn);
  2914. if ((*lpfnPagePaintHook)( hWnd,
  2915. WM_PSD_MARGINRECT,
  2916. (WPARAM)hDC,
  2917. (LPARAM)(LPRECT)&aRtUser ))
  2918. {
  2919. goto SkipMarginRectangle;
  2920. }
  2921. }
  2922. if (!(pPSD->Flags & PSD_DISABLEPAGEPAINTING))
  2923. {
  2924. Rectangle(hDC, aRt.left, aRt.top, aRt.right, aRt.bottom);
  2925. }
  2926. SkipMarginRectangle:
  2927. InflateRect(&aRt, -1, -1);
  2928. if (pPSD->lpfnPagePaintHook)
  2929. {
  2930. LPPAGEPAINTHOOK lpfnPagePaintHook = GETPAGEPAINTHOOKFN(pPSD);
  2931. aRtUser = aRt;
  2932. hRgn = CreateRectRgnIndirect(&aRtUser);
  2933. SelectClipRgn(hDC, hRgn);
  2934. DeleteObject(hRgn);
  2935. if ((*lpfnPagePaintHook)( hWnd,
  2936. WM_PSD_GREEKTEXTRECT,
  2937. (WPARAM)hDC,
  2938. (LPARAM)(LPRECT)&aRtUser ))
  2939. {
  2940. goto SkipGreekText;
  2941. }
  2942. }
  2943. if (!(pPSD->Flags & PSD_DISABLEPAGEPAINTING))
  2944. {
  2945. psGreekText = LocalAlloc( LPTR,
  2946. 10 * (sizeof(szGreekText) + sizeof(TCHAR)) );
  2947. for (i = 0; i < 10; i++)
  2948. {
  2949. CopyMemory( &(psGreekText[i * (sizeof(szGreekText) / sizeof(TCHAR))]),
  2950. szGreekText,
  2951. sizeof(szGreekText) );
  2952. }
  2953. aRt.left++;
  2954. aRt.right--;
  2955. aRt.bottom -= (aRt.bottom - aRt.top) % pPI->PtMargins.y;
  2956. hFontGreek = SelectObject(hDC, hFontGreek);
  2957. DrawText( hDC,
  2958. psGreekText,
  2959. 10 * (sizeof(szGreekText) / sizeof(TCHAR)),
  2960. &aRt,
  2961. DT_NOPREFIX | DT_WORDBREAK );
  2962. SelectObject(hDC, hFontGreek);
  2963. LocalFree(psGreekText);
  2964. }
  2965. }
  2966. SkipGreekText:
  2967. InflateRect(&aRtPage, -1, -1);
  2968. if (pPI->pPD->Flags & PI_WPAPER_ENVELOPE)
  2969. {
  2970. int iOrientation;
  2971. aRt = aRtPage;
  2972. if (aRt.right < aRt.bottom) // portrait
  2973. // switch (pPI->dwRotation)
  2974. {
  2975. // default : // no landscape
  2976. // case ( ROTATE_LEFT ) : // dot-matrix
  2977. // {
  2978. // aRt.left = aRt.right - 16;
  2979. // aRt.top = aRt.bottom - 32;
  2980. // iOrientation = 2;
  2981. // break;
  2982. // }
  2983. // case ( ROTATE_RIGHT ) : // HP PCL
  2984. // {
  2985. aRt.right = aRt.left + 16;
  2986. aRt.bottom = aRt.top + 32;
  2987. iOrientation = 1;
  2988. // break;
  2989. // }
  2990. }
  2991. else // landscape
  2992. {
  2993. aRt.left = aRt.right - 32;
  2994. aRt.bottom = aRt.top + 16;
  2995. iOrientation = 3;
  2996. }
  2997. hRgn = CreateRectRgnIndirect(&aRt);
  2998. SelectClipRgn(hDC, hRgn);
  2999. DeleteObject(hRgn);
  3000. if (pPSD->lpfnPagePaintHook)
  3001. {
  3002. LPPAGEPAINTHOOK lpfnPagePaintHook = GETPAGEPAINTHOOKFN(pPSD);
  3003. aRtUser = aRt;
  3004. if ((*lpfnPagePaintHook)( hWnd,
  3005. WM_PSD_ENVSTAMPRECT,
  3006. (WPARAM)hDC,
  3007. (LPARAM)(LPRECT)&aRtUser ))
  3008. {
  3009. goto SkipEnvelopeStamp;
  3010. }
  3011. }
  3012. if (!(pPSD->Flags & PSD_DISABLEPAGEPAINTING))
  3013. {
  3014. switch (iOrientation)
  3015. {
  3016. default : // HP PCL
  3017. // case ( 1 ) :
  3018. {
  3019. DrawIcon(hDC, aRt.left, aRt.top, hIconPSStampP);
  3020. break;
  3021. }
  3022. // case ( 2 ) : // dot-matrix
  3023. // {
  3024. // DrawIcon(hDC, aRt.left - 16, aRt.top, hIconPSStampP);
  3025. // break;
  3026. // }
  3027. case ( 3 ) : // landscape
  3028. {
  3029. DrawIcon(hDC, aRt.left, aRt.top, hIconPSStampL);
  3030. break;
  3031. }
  3032. }
  3033. }
  3034. }
  3035. SkipEnvelopeStamp:;
  3036. aRtUser = aRtPage;
  3037. hRgn = CreateRectRgnIndirect(&aRtUser);
  3038. SelectClipRgn(hDC, hRgn);
  3039. DeleteObject(hRgn);
  3040. if (pPSD->lpfnPagePaintHook)
  3041. {
  3042. LPPAGEPAINTHOOK lpfnPagePaintHook = GETPAGEPAINTHOOKFN(pPSD);
  3043. if ((*lpfnPagePaintHook)( hWnd,
  3044. WM_PSD_YAFULLPAGERECT,
  3045. (WPARAM)hDC,
  3046. (LPARAM)(LPRECT)&aRtUser ))
  3047. {
  3048. goto NoMorePainting;
  3049. }
  3050. }
  3051. //
  3052. // Draw the envelope lines.
  3053. //
  3054. if ( (!(pPSD->Flags & PSD_DISABLEPAGEPAINTING)) &&
  3055. (pPI->pPD->Flags & PI_WPAPER_ENVELOPE) )
  3056. {
  3057. int iRotation;
  3058. HGDIOBJ hPenBlack;
  3059. aRt = aRtPage;
  3060. if (aRt.right < aRt.bottom) // portrait
  3061. {
  3062. // if (pPI->dwRotation == ROTATE_LEFT ) // dot-matrix
  3063. // iRotation = 3;
  3064. // else // ROTATE_RIGHT // HP PCL
  3065. iRotation = 2;
  3066. }
  3067. else // landscape
  3068. {
  3069. iRotation = 1; // normal
  3070. }
  3071. switch (iRotation)
  3072. {
  3073. default :
  3074. // case ( 1 ) : // normal
  3075. {
  3076. aRt.right = aRt.left + 32;
  3077. aRt.bottom = aRt.top + 13;
  3078. break;
  3079. }
  3080. case ( 2 ) : // left
  3081. {
  3082. aRt.right = aRt.left + 13;
  3083. aRt.top = aRt.bottom - 32;
  3084. break;
  3085. }
  3086. // case ( 3 ) : // right
  3087. // {
  3088. // aRt.left = aRt.right - 13;
  3089. // aRt.bottom = aRt.top + 32;
  3090. // break;
  3091. // }
  3092. }
  3093. InflateRect(&aRt, -3, -3);
  3094. hPenBlack = SelectObject(hDC, GetStockObject(BLACK_PEN));
  3095. switch (iRotation)
  3096. {
  3097. case ( 1 ) : // normal
  3098. {
  3099. MoveToEx(hDC, aRt.left , aRt.top , NULL);
  3100. LineTo( hDC, aRt.right, aRt.top);
  3101. MoveToEx(hDC, aRt.left , aRt.top + 3, NULL);
  3102. LineTo( hDC, aRt.right, aRt.top + 3);
  3103. MoveToEx(hDC, aRt.left , aRt.top + 6, NULL);
  3104. LineTo( hDC, aRt.right, aRt.top + 6);
  3105. break;
  3106. }
  3107. // case ( 2 ) : // left
  3108. // case ( 3 ) : // right
  3109. default :
  3110. {
  3111. MoveToEx( hDC, aRt.left , aRt.top , NULL );
  3112. LineTo( hDC, aRt.left , aRt.bottom );
  3113. MoveToEx( hDC, aRt.left + 3, aRt.top , NULL );
  3114. LineTo( hDC, aRt.left + 3, aRt.bottom );
  3115. MoveToEx( hDC, aRt.left + 6, aRt.top , NULL );
  3116. LineTo( hDC, aRt.left + 6, aRt.bottom );
  3117. break;
  3118. }
  3119. }
  3120. SelectObject(hDC, hPenBlack);
  3121. }
  3122. NoMorePainting:
  3123. DeleteObject(SelectObject(hDC, hPen));
  3124. SelectObject(hDC, hBr);
  3125. DeleteObject(SelectObject(hDC, hFont));
  3126. TransferPSD2PD(pPI);
  3127. ReleaseDC(hWnd, hDC);
  3128. return (lResult);
  3129. }
  3130. ////////////////////////////////////////////////////////////////////////////
  3131. //
  3132. // PrintLoadResource
  3133. //
  3134. // This routine loads the resource with the given name and type.
  3135. //
  3136. ////////////////////////////////////////////////////////////////////////////
  3137. HANDLE PrintLoadResource(
  3138. HANDLE hInst,
  3139. LPTSTR pResName,
  3140. LPTSTR pType)
  3141. {
  3142. HANDLE hResInfo, hRes;
  3143. LANGID LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
  3144. //
  3145. // If we are loading a resource from ComDlg32 then use the correct LangID.
  3146. //
  3147. if (hInst == g_hinst) {
  3148. LangID = (LANGID) TlsGetValue(g_tlsLangID);
  3149. }
  3150. if (!(hResInfo = FindResourceExFallback(hInst, pType, pResName, LangID)))
  3151. {
  3152. StoreExtendedError(CDERR_FINDRESFAILURE);
  3153. return (NULL);
  3154. }
  3155. if (!(hRes = LoadResource(hInst, hResInfo)))
  3156. {
  3157. StoreExtendedError(CDERR_LOADRESFAILURE);
  3158. return (NULL);
  3159. }
  3160. return (hRes);
  3161. }
  3162. ////////////////////////////////////////////////////////////////////////////
  3163. //
  3164. // PrintGetDefaultPrinterName
  3165. //
  3166. // This routine gets the name of the default printer and stores it
  3167. // in the given buffer.
  3168. //
  3169. ////////////////////////////////////////////////////////////////////////////
  3170. VOID PrintGetDefaultPrinterName(
  3171. LPTSTR pDefaultPrinter,
  3172. UINT cchSize)
  3173. {
  3174. DWORD dwSize;
  3175. LPTSTR lpsz;
  3176. if (pDefaultPrinter[0] != CHAR_NULL)
  3177. {
  3178. return;
  3179. }
  3180. //
  3181. // First, try to get the default printername from the win.ini file.
  3182. //
  3183. if (GetProfileString( szTextWindows,
  3184. szTextDevice,
  3185. szTextNull,
  3186. pDefaultPrinter,
  3187. cchSize ))
  3188. {
  3189. lpsz = pDefaultPrinter;
  3190. while (*lpsz != CHAR_COMMA)
  3191. {
  3192. if (!*lpsz++)
  3193. {
  3194. pDefaultPrinter[0] = CHAR_NULL;
  3195. goto GetDefaultFromRegistry;
  3196. }
  3197. }
  3198. *lpsz = CHAR_NULL;
  3199. }
  3200. else
  3201. {
  3202. GetDefaultFromRegistry:
  3203. //
  3204. // Second, try to get it from the registry.
  3205. //
  3206. dwSize = cchSize * sizeof(TCHAR);
  3207. if (RegOpenKeyEx( HKEY_CURRENT_USER,
  3208. szRegistryPrinter,
  3209. 0,
  3210. KEY_READ,
  3211. &hPrinterKey ) == ERROR_SUCCESS)
  3212. {
  3213. RegQueryValueEx( hPrinterKey,
  3214. szRegistryDefaultValueName,
  3215. NULL,
  3216. NULL,
  3217. (LPBYTE)(pDefaultPrinter),
  3218. &dwSize );
  3219. RegCloseKey(hPrinterKey);
  3220. }
  3221. }
  3222. }
  3223. ////////////////////////////////////////////////////////////////////////////
  3224. //
  3225. // PrintReturnDefault
  3226. //
  3227. ////////////////////////////////////////////////////////////////////////////
  3228. BOOL PrintReturnDefault(
  3229. PPRINTINFO pPI)
  3230. {
  3231. LPPRINTDLG pPD = pPI->pPD;
  3232. LPDEVNAMES pDN;
  3233. LPDEVMODE pDM;
  3234. StoreExtendedError(CDERR_GENERALCODES);
  3235. if (pPD->hDevNames || pPD->hDevMode)
  3236. {
  3237. StoreExtendedError(PDERR_RETDEFFAILURE);
  3238. return (FALSE);
  3239. }
  3240. PrintBuildDevNames(pPI);
  3241. if ((pPD->hDevNames) && (pDN = GlobalLock(pPD->hDevNames)))
  3242. {
  3243. #ifdef WINNT
  3244. //
  3245. // This is not needed in Win95. An optimization was
  3246. // added to DocumentProperties that allows the caller to
  3247. // simply pass in the printer name without the printer
  3248. // handle.
  3249. //
  3250. LPTSTR pPrinterName;
  3251. pPrinterName = (LPTSTR)pDN + pDN->wDeviceOffset;
  3252. if (pPrinterName[0])
  3253. {
  3254. PrintOpenPrinter(pPI, pPrinterName);
  3255. }
  3256. pPD->hDevMode = PrintGetDevMode( 0,
  3257. pPI->hCurPrinter,
  3258. pPrinterName,
  3259. NULL);
  3260. #else
  3261. pPD->hDevMode = PrintGetDevMode( 0,
  3262. NULL,
  3263. (LPTSTR)pDN + pDN->wDeviceOffset,
  3264. NULL );
  3265. #endif
  3266. if ((pPD->hDevMode) && (pDM = GlobalLock(pPD->hDevMode)))
  3267. {
  3268. PrintReturnICDC(pPD, pDN, pDM);
  3269. GlobalUnlock(pPD->hDevMode);
  3270. GlobalUnlock(pPD->hDevNames);
  3271. return (TRUE);
  3272. }
  3273. GlobalUnlock(pPD->hDevNames);
  3274. GlobalFree(pPD->hDevNames);
  3275. pPD->hDevNames = NULL;
  3276. }
  3277. StoreExtendedError(PDERR_NODEFAULTPRN);
  3278. return (FALSE);
  3279. }
  3280. ////////////////////////////////////////////////////////////////////////////
  3281. //
  3282. // PrintInitGeneral
  3283. //
  3284. // Initialize (enable/disable) dialog elements general to both PrintDlg
  3285. // and SetupDlg.
  3286. //
  3287. ////////////////////////////////////////////////////////////////////////////
  3288. BOOL PrintInitGeneral(
  3289. HWND hDlg,
  3290. UINT Id,
  3291. PPRINTINFO pPI)
  3292. {
  3293. LPPRINTDLG pPD = pPI->pPD;
  3294. HWND hCtl;
  3295. SetWindowLong( hDlg,
  3296. GWL_STYLE,
  3297. GetWindowLong(hDlg, GWL_STYLE) | DS_CONTEXTHELP );
  3298. #ifndef WINNT
  3299. if (!lpEditMarginProc)
  3300. {
  3301. WNDCLASSEX wc;
  3302. wc.cbSize = sizeof(wc);
  3303. GetClassInfoEx(NULL, TEXT("edit"), &wc);
  3304. lpEditMarginProc = wc.lpfnWndProc;
  3305. GetClassInfoEx(NULL, TEXT("static"), &wc);
  3306. lpStaticProc = wc.lpfnWndProc;
  3307. }
  3308. #endif
  3309. //
  3310. // LATER: If we don't enumerate here, there will only be ONE item
  3311. // in the list box. As a result, we won't catch the
  3312. // keyboard strokes within the list box (eg. arrow keys,
  3313. // pgup, pgdown, etc). Need to subclass the combo boxes
  3314. // to catch these key strokes so that the printers can be
  3315. // enumerated.
  3316. //
  3317. if (!PrintEnumAndSelect( hDlg,
  3318. Id,
  3319. pPI,
  3320. (pPI->pCurPrinter)
  3321. ? pPI->pCurPrinter->pPrinterName
  3322. : NULL,
  3323. (!(pPI->Status & PI_PRINTERS_ENUMERATED)) ))
  3324. {
  3325. goto InitGeneral_ConstructFailure;
  3326. }
  3327. PrintUpdateStatus(hDlg, pPI);
  3328. //
  3329. // See if the Help button should be hidden.
  3330. //
  3331. if (!(pPD->Flags & PD_SHOWHELP))
  3332. {
  3333. if (hCtl = GetDlgItem(hDlg, ID_BOTH_P_HELP))
  3334. {
  3335. EnableWindow(hCtl, FALSE);
  3336. ShowWindow(hCtl, SW_HIDE);
  3337. #ifdef WINNT
  3338. //
  3339. // Move the window out of this spot so that no overlap
  3340. // will be detected when adding the network button.
  3341. //
  3342. MoveWindow(hCtl, -8000, -8000, 20, 20, FALSE);
  3343. #endif
  3344. }
  3345. }
  3346. return (TRUE);
  3347. InitGeneral_ConstructFailure:
  3348. if (!GetStoredExtendedError())
  3349. {
  3350. StoreExtendedError(PDERR_INITFAILURE);
  3351. }
  3352. return (FALSE);
  3353. }
  3354. ////////////////////////////////////////////////////////////////////////////
  3355. //
  3356. // PrintInitPrintDlg
  3357. //
  3358. // Initialize PRINT DLG-specific dialog stuff.
  3359. //
  3360. // Returns 0xFFFFFFFF if the dialog should be ended.
  3361. // Otherwise, returns 1/0 (TRUE/FALSE) depending on focus.
  3362. //
  3363. ////////////////////////////////////////////////////////////////////////////
  3364. DWORD PrintInitPrintDlg(
  3365. HWND hDlg,
  3366. WPARAM wParam,
  3367. PPRINTINFO pPI)
  3368. {
  3369. LPPRINTDLG pPD = pPI->pPD;
  3370. WORD wCheckID;
  3371. HWND hCtl;
  3372. //
  3373. // Set the number of copies.
  3374. //
  3375. pPD->nCopies = max(pPD->nCopies, 1);
  3376. pPD->nCopies = min(pPD->nCopies, MAX_COPIES);
  3377. SetDlgItemInt(hDlg, ID_PRINT_E_COPIES, pPD->nCopies, FALSE);
  3378. if ( !(pPI->pPSD) &&
  3379. (hCtl = GetDlgItem(hDlg, ID_PRINT_E_COPIES)) &&
  3380. (GetWindowLong(hCtl, GWL_STYLE) & WS_VISIBLE) )
  3381. {
  3382. //
  3383. // "9999" is the maximum value.
  3384. //
  3385. Edit_LimitText(hCtl, COPIES_EDIT_SIZE);
  3386. CreateUpDownControl( WS_CHILD | WS_BORDER | WS_VISIBLE |
  3387. UDS_ALIGNRIGHT | UDS_SETBUDDYINT |
  3388. UDS_NOTHOUSANDS | UDS_ARROWKEYS,
  3389. 0,
  3390. 0,
  3391. 0,
  3392. 0,
  3393. hDlg,
  3394. IDC_COPIES_UDARROW,
  3395. g_hinst,
  3396. hCtl,
  3397. MAX_COPIES,
  3398. 1,
  3399. pPD->nCopies );
  3400. //
  3401. // Adjust the width of the copies edit control using the current
  3402. // font and the scroll bar width. This is necessary to handle the
  3403. // the up down control from encroching on the space in the edit
  3404. // control when we are in High Contrast (extra large) mode.
  3405. //
  3406. SetCopiesEditWidth(hDlg, hCtl);
  3407. }
  3408. if (!PrintInitBannerAndQuality(hDlg, pPI, pPD))
  3409. {
  3410. if (!GetStoredExtendedError())
  3411. {
  3412. StoreExtendedError(PDERR_INITFAILURE);
  3413. }
  3414. return (0xFFFFFFFF);
  3415. }
  3416. #ifdef WINNT
  3417. if (!(pPD->Flags & PD_SHOWHELP))
  3418. {
  3419. if (hCtl = GetDlgItem(hDlg, ID_BOTH_P_HELP))
  3420. {
  3421. EnableWindow(hCtl, FALSE);
  3422. ShowWindow(hCtl, SW_HIDE);
  3423. //
  3424. // Move the window out of this spot so that no overlap
  3425. // will be detected when adding the network button.
  3426. //
  3427. MoveWindow(hCtl, -8000, -8000, 20, 20, FALSE);
  3428. }
  3429. }
  3430. #endif
  3431. if (hCtl = GetDlgItem(hDlg, ID_PRINT_X_TOFILE))
  3432. {
  3433. if (pPD->Flags & PD_PRINTTOFILE)
  3434. {
  3435. CheckDlgButton(hDlg, ID_PRINT_X_TOFILE, TRUE);
  3436. }
  3437. if (pPD->Flags & PD_HIDEPRINTTOFILE)
  3438. {
  3439. EnableWindow(hCtl, FALSE);
  3440. ShowWindow(hCtl, SW_HIDE);
  3441. }
  3442. else if (pPD->Flags & PD_DISABLEPRINTTOFILE)
  3443. {
  3444. EnableWindow(hCtl, FALSE);
  3445. }
  3446. }
  3447. if (pPD->Flags & PD_NOPAGENUMS)
  3448. {
  3449. EnableWindow(GetDlgItem(hDlg, ID_PRINT_R_PAGES), FALSE);
  3450. EnableWindow(GetDlgItem(hDlg, ID_PRINT_S_FROM), FALSE);
  3451. EnableWindow(GetDlgItem(hDlg, ID_PRINT_E_FROM), FALSE);
  3452. EnableWindow(GetDlgItem(hDlg, ID_PRINT_S_TO), FALSE);
  3453. EnableWindow(GetDlgItem(hDlg, ID_PRINT_E_TO), FALSE);
  3454. //
  3455. // Don't allow disabled button checked.
  3456. //
  3457. pPD->Flags &= ~((DWORD)PD_PAGENUMS);
  3458. }
  3459. else
  3460. {
  3461. //
  3462. // Some apps (marked 3.1) do not pass in valid ranges.
  3463. // (e.g. Corel Ventura)
  3464. //
  3465. if ((pPI->ProcessVersion < 0x40000) || (!(pPD->Flags & PD_PAGENUMS)))
  3466. {
  3467. if (pPD->nFromPage != 0xFFFF)
  3468. {
  3469. if (pPD->nFromPage < pPD->nMinPage)
  3470. {
  3471. pPD->nFromPage = pPD->nMinPage;
  3472. }
  3473. else if (pPD->nFromPage > pPD->nMaxPage)
  3474. {
  3475. pPD->nFromPage = pPD->nMaxPage;
  3476. }
  3477. }
  3478. if (pPD->nToPage != 0xFFFF)
  3479. {
  3480. if (pPD->nToPage < pPD->nMinPage)
  3481. {
  3482. pPD->nToPage = pPD->nMinPage;
  3483. }
  3484. else if (pPD->nToPage > pPD->nMaxPage)
  3485. {
  3486. pPD->nToPage = pPD->nMaxPage;
  3487. }
  3488. }
  3489. }
  3490. if ( pPD->nMinPage > pPD->nMaxPage ||
  3491. ( pPD->nFromPage != 0xFFFF &&
  3492. ( pPD->nFromPage < pPD->nMinPage ||
  3493. pPD->nFromPage > pPD->nMaxPage ) ) ||
  3494. ( pPD->nToPage != 0xFFFF &&
  3495. ( pPD->nToPage < pPD->nMinPage ||
  3496. pPD->nToPage > pPD->nMaxPage ) ) )
  3497. {
  3498. StoreExtendedError(PDERR_INITFAILURE);
  3499. return (0xFFFFFFFF);
  3500. }
  3501. if (pPD->nFromPage != 0xFFFF)
  3502. {
  3503. SetDlgItemInt(hDlg, ID_PRINT_E_FROM, pPD->nFromPage, FALSE);
  3504. if (pPD->nToPage != 0xFFFF)
  3505. {
  3506. SetDlgItemInt(hDlg, ID_PRINT_E_TO, pPD->nToPage, FALSE);
  3507. }
  3508. }
  3509. else
  3510. {
  3511. EnableWindow(GetDlgItem(hDlg, ID_PRINT_S_TO), FALSE);
  3512. EnableWindow(GetDlgItem(hDlg, ID_PRINT_E_TO), FALSE);
  3513. }
  3514. if (pPD->nMinPage == pPD->nMaxPage)
  3515. {
  3516. EnableWindow(GetDlgItem(hDlg, ID_PRINT_R_PAGES), FALSE);
  3517. EnableWindow(GetDlgItem(hDlg, ID_PRINT_S_FROM), FALSE);
  3518. EnableWindow(GetDlgItem(hDlg, ID_PRINT_E_FROM), FALSE);
  3519. EnableWindow(GetDlgItem(hDlg, ID_PRINT_S_TO), FALSE);
  3520. EnableWindow(GetDlgItem(hDlg, ID_PRINT_E_TO), FALSE);
  3521. //
  3522. // Don't allow disabled button checked.
  3523. //
  3524. pPD->Flags &= ~((DWORD)(PD_PAGENUMS | PD_COLLATE));
  3525. pPI->Status &= ~PI_COLLATE_REQUESTED;
  3526. EnableWindow(GetDlgItem(hDlg, ID_PRINT_X_COLLATE), FALSE);
  3527. ShowWindow(GetDlgItem(hDlg, ID_PRINT_X_COLLATE), SW_HIDE);
  3528. }
  3529. #ifndef WINNT
  3530. //
  3531. // This is NOT desirable. Most apps use a very high number for
  3532. // their max page, so it looks very strange.
  3533. //
  3534. else
  3535. {
  3536. TCHAR szAll[32];
  3537. TCHAR szBuf[64];
  3538. if (pPD->nMinPage != pPD->nMaxPage)
  3539. {
  3540. if (pPD->nMaxPage != 0xFFFF)
  3541. {
  3542. if (CDLoadString(g_hinst, iszPrintRangeAll, szAll, 32))
  3543. {
  3544. wsprintf( szBuf,
  3545. szAll,
  3546. (DWORD)pPD->nMaxPage - (DWORD)pPD->nMinPage + 1 );
  3547. SetDlgItemText(hDlg, ID_PRINT_R_ALL, szBuf);
  3548. }
  3549. else
  3550. {
  3551. StoreExtendedError(CDERR_LOADSTRFAILURE);
  3552. return (0xFFFFFFFF);
  3553. }
  3554. }
  3555. }
  3556. }
  3557. #endif
  3558. }
  3559. if (pPD->Flags & PD_NOSELECTION)
  3560. {
  3561. HWND hRad = GetDlgItem(hDlg, ID_PRINT_R_SELECTION);
  3562. if (hRad)
  3563. {
  3564. EnableWindow(hRad, FALSE);
  3565. }
  3566. //
  3567. // Don't allow disabled button checked.
  3568. //
  3569. pPD->Flags &= ~((DWORD)PD_SELECTION);
  3570. }
  3571. if (pPD->Flags & PD_PAGENUMS)
  3572. {
  3573. wCheckID = ID_PRINT_R_PAGES;
  3574. }
  3575. else if (pPD->Flags & PD_SELECTION)
  3576. {
  3577. wCheckID = ID_PRINT_R_SELECTION;
  3578. }
  3579. else
  3580. {
  3581. // PD_ALL
  3582. wCheckID = ID_PRINT_R_ALL;
  3583. }
  3584. CheckRadioButton(hDlg, ID_PRINT_R_ALL, ID_PRINT_R_PAGES, (int)wCheckID);
  3585. //
  3586. // Subclass the integer only edit controls.
  3587. //
  3588. if (!(pPI->pPSD))
  3589. {
  3590. if (hCtl = GetDlgItem(hDlg, ID_PRINT_E_FROM))
  3591. {
  3592. //
  3593. // "99999" is the maximum value.
  3594. //
  3595. Edit_LimitText(hCtl, PAGE_EDIT_SIZE);
  3596. }
  3597. if (hCtl = GetDlgItem(hDlg, ID_PRINT_E_TO))
  3598. {
  3599. //
  3600. // "99999" is the maximum value.
  3601. //
  3602. Edit_LimitText(hCtl, PAGE_EDIT_SIZE);
  3603. }
  3604. }
  3605. if (pPD->lpfnPrintHook)
  3606. {
  3607. LPPRINTHOOKPROC lpfnPrintHook = GETPRINTHOOKFN(pPD);
  3608. #ifdef UNICODE
  3609. if (pPI->ApiType == COMDLG_ANSI)
  3610. {
  3611. DWORD dwHookRet;
  3612. ThunkPrintDlgW2A(pPI);
  3613. dwHookRet = (*lpfnPrintHook)( hDlg,
  3614. WM_INITDIALOG,
  3615. wParam,
  3616. (LONG_PTR)pPI->pPDA ) != 0;
  3617. if (dwHookRet)
  3618. {
  3619. ThunkPrintDlgA2W(pPI);
  3620. }
  3621. return (dwHookRet);
  3622. }
  3623. else
  3624. #endif
  3625. {
  3626. return ( (*lpfnPrintHook)( hDlg,
  3627. WM_INITDIALOG,
  3628. wParam,
  3629. (LONG_PTR)pPD ) ) != 0;
  3630. }
  3631. }
  3632. return (TRUE);
  3633. }
  3634. ////////////////////////////////////////////////////////////////////////////
  3635. //
  3636. // PrintInitSetupDlg
  3637. //
  3638. // Initialize SETUP-specific dialog stuff.
  3639. //
  3640. // Returns 0xFFFFFFFF if the dialog should be ended.
  3641. // Otherwise, returns 1/0 (TRUE/FALSE) depending on focus.
  3642. //
  3643. ////////////////////////////////////////////////////////////////////////////
  3644. DWORD PrintInitSetupDlg(
  3645. HWND hDlg,
  3646. WPARAM wParam,
  3647. PPRINTINFO pPI)
  3648. {
  3649. LPPRINTDLG pPD = pPI->pPD;
  3650. LPDEVMODE pDM = NULL;
  3651. HWND hCtl;
  3652. LPPAGESETUPDLG pPSD = pPI->pPSD;
  3653. UINT Orientation;
  3654. if (!pPD->hDevMode ||
  3655. !(pDM = GlobalLock(pPD->hDevMode)))
  3656. {
  3657. StoreExtendedError(CDERR_MEMLOCKFAILURE);
  3658. goto InitSetupDlg_ConstructFailure;
  3659. }
  3660. if (hCtl = GetDlgItem(hDlg, ID_SETUP_C_SIZE))
  3661. {
  3662. PrintInitPaperCombo( pPI,
  3663. hCtl,
  3664. GetDlgItem(hDlg, ID_SETUP_S_SIZE),
  3665. pPI->pCurPrinter,
  3666. pDM,
  3667. DC_PAPERNAMES,
  3668. CCHPAPERNAME,
  3669. DC_PAPERS );
  3670. }
  3671. //
  3672. // Provide backward compatibility for old-style-template sources
  3673. // ID_SETUP_C_SOURCE.
  3674. //
  3675. if (hCtl = GetDlgItem(hDlg, ID_SETUP_C_SOURCE))
  3676. {
  3677. PrintInitPaperCombo( pPI,
  3678. hCtl,
  3679. GetDlgItem(hDlg, ID_SETUP_S_SOURCE),
  3680. pPI->pCurPrinter,
  3681. pDM,
  3682. DC_BINNAMES,
  3683. CCHBINNAME,
  3684. DC_BINS );
  3685. }
  3686. //
  3687. // Set the edit field lengths and other setup stuff for margins.
  3688. // This must be called before PrintSetMargin, which is called in
  3689. // PrintSetOrientation.
  3690. //
  3691. PrintSetupMargins(hDlg, pPI);
  3692. PrintInitOrientation(hDlg, pPI, pDM);
  3693. Orientation = pDM->dmOrientation + ID_SETUP_R_PORTRAIT - DMORIENT_PORTRAIT;
  3694. PrintSetOrientation( hDlg,
  3695. pPI,
  3696. pDM,
  3697. Orientation,
  3698. Orientation );
  3699. PrintInitDuplex(hDlg, pDM);
  3700. PrintSetDuplex( hDlg,
  3701. pDM,
  3702. pDM->dmDuplex + ID_SETUP_R_NONE - DMDUP_SIMPLEX );
  3703. GlobalUnlock(pPD->hDevMode);
  3704. if (pPSD)
  3705. {
  3706. if (pPSD->Flags & PSD_DISABLEORIENTATION)
  3707. {
  3708. EnableWindow(GetDlgItem(hDlg, ID_SETUP_R_PORTRAIT), FALSE );
  3709. EnableWindow(GetDlgItem(hDlg, ID_SETUP_R_LANDSCAPE), FALSE );
  3710. }
  3711. if (pPSD->Flags & PSD_DISABLEPAPER)
  3712. {
  3713. EnableWindow(GetDlgItem(hDlg, ID_SETUP_S_SIZE), FALSE );
  3714. EnableWindow(GetDlgItem(hDlg, ID_SETUP_C_SIZE), FALSE );
  3715. EnableWindow(GetDlgItem(hDlg, ID_SETUP_S_SOURCE), FALSE );
  3716. EnableWindow(GetDlgItem(hDlg, ID_SETUP_C_SOURCE), FALSE );
  3717. }
  3718. if (pPSD->Flags & PSD_DISABLEMARGINS)
  3719. {
  3720. EnableWindow(GetDlgItem(hDlg, ID_SETUP_S_LEFT), FALSE );
  3721. EnableWindow(GetDlgItem(hDlg, ID_SETUP_E_LEFT), FALSE );
  3722. EnableWindow(GetDlgItem(hDlg, ID_SETUP_S_RIGHT), FALSE );
  3723. EnableWindow(GetDlgItem(hDlg, ID_SETUP_E_RIGHT), FALSE );
  3724. EnableWindow(GetDlgItem(hDlg, ID_SETUP_S_TOP), FALSE );
  3725. EnableWindow(GetDlgItem(hDlg, ID_SETUP_E_TOP), FALSE );
  3726. EnableWindow(GetDlgItem(hDlg, ID_SETUP_S_BOTTOM), FALSE );
  3727. EnableWindow(GetDlgItem(hDlg, ID_SETUP_E_BOTTOM), FALSE );
  3728. }
  3729. if (pPSD->Flags & PSD_DISABLEPRINTER)
  3730. {
  3731. EnableWindow(GetDlgItem(hDlg, ID_SETUP_P_PRINTER), FALSE );
  3732. }
  3733. }
  3734. if (hCtl = GetDlgItem(hDlg, ID_SETUP_W_SAMPLE))
  3735. {
  3736. lpStaticProc = (WNDPROC)SetWindowLongPtr( hCtl,
  3737. GWLP_WNDPROC,
  3738. (LONG_PTR)PrintPageSetupPaintProc );
  3739. }
  3740. if ((pPD->Flags & PD_NONETWORKBUTTON))
  3741. {
  3742. if (hCtl = GetDlgItem(hDlg, ID_BOTH_P_NETWORK))
  3743. {
  3744. EnableWindow(hCtl, FALSE);
  3745. ShowWindow(hCtl, SW_HIDE);
  3746. }
  3747. }
  3748. else if (!(pPI->pPSD))
  3749. {
  3750. #ifdef WINNT
  3751. AddNetButton( hDlg,
  3752. ((pPD->Flags & PD_ENABLESETUPTEMPLATE)
  3753. ? pPD->hInstance : g_hinst),
  3754. FILE_BOTTOM_MARGIN,
  3755. (pPD->Flags & (PD_ENABLESETUPTEMPLATE |
  3756. PD_ENABLESETUPTEMPLATEHANDLE))
  3757. ? FALSE : TRUE,
  3758. FALSE,
  3759. TRUE );
  3760. #endif
  3761. //
  3762. // The button can be added in two ways -
  3763. // statically (they have it predefined in their template) and
  3764. // dynamically (successful call to AddNetButton).
  3765. //
  3766. #ifdef WINNT
  3767. if (!IsNetworkInstalled())
  3768. #else
  3769. if (!GetSystemMetrics(SM_NETWORK))
  3770. #endif
  3771. {
  3772. hCtl = GetDlgItem(hDlg, ID_BOTH_P_NETWORK);
  3773. EnableWindow(hCtl, FALSE);
  3774. ShowWindow(hCtl, SW_HIDE);
  3775. }
  3776. }
  3777. #ifdef WINNT
  3778. if (!(pPD->Flags & PD_SHOWHELP))
  3779. {
  3780. if (hCtl = GetDlgItem(hDlg, ID_BOTH_P_HELP))
  3781. {
  3782. EnableWindow(hCtl, FALSE);
  3783. ShowWindow(hCtl, SW_HIDE);
  3784. //
  3785. // Move the window out of this spot so that no overlap
  3786. // will be detected when adding the network button.
  3787. //
  3788. MoveWindow(hCtl, -8000, -8000, 20, 20, FALSE);
  3789. }
  3790. }
  3791. #endif
  3792. //
  3793. // Provide backward compatibility for old-style-template radio buttons.
  3794. //
  3795. if (hCtl = GetDlgItem(hDlg, ID_SETUP_R_DEFAULT))
  3796. {
  3797. TCHAR szBuf[MAX_DEV_SECT];
  3798. TCHAR szDefFormat[MAX_DEV_SECT];
  3799. if (pPI->szDefaultPrinter[0])
  3800. {
  3801. if (!CDLoadString( g_hinst,
  3802. iszDefCurOn,
  3803. szDefFormat,
  3804. ARRAYSIZE(szDefFormat) ))
  3805. {
  3806. StoreExtendedError(CDERR_LOADSTRFAILURE);
  3807. goto InitSetupDlg_ConstructFailure;
  3808. }
  3809. wnsprintf(szBuf, ARRAYSIZE(szBuf), szDefFormat, pPI->szDefaultPrinter);
  3810. }
  3811. else
  3812. {
  3813. szBuf[0] = CHAR_NULL;
  3814. EnableWindow(hCtl, FALSE);
  3815. }
  3816. SetDlgItemText(hDlg, ID_SETUP_S_DEFAULT, szBuf);
  3817. if ( pPI->pCurPrinter &&
  3818. pPI->pCurPrinter->pPrinterName &&
  3819. !lstrcmp(pPI->pCurPrinter->pPrinterName, pPI->szDefaultPrinter) )
  3820. {
  3821. CheckRadioButton( hDlg,
  3822. ID_SETUP_R_DEFAULT,
  3823. ID_SETUP_R_SPECIFIC,
  3824. ID_SETUP_R_DEFAULT );
  3825. }
  3826. else
  3827. {
  3828. CheckRadioButton( hDlg,
  3829. ID_SETUP_R_DEFAULT,
  3830. ID_SETUP_R_SPECIFIC,
  3831. ID_SETUP_R_SPECIFIC );
  3832. }
  3833. }
  3834. if (pPD->lpfnSetupHook)
  3835. {
  3836. DWORD dwHookRet;
  3837. LPSETUPHOOKPROC lpfnSetupHook = GETSETUPHOOKFN(pPD);
  3838. #ifdef UNICODE
  3839. if (pPI->ApiType == COMDLG_ANSI)
  3840. {
  3841. ThunkPrintDlgW2A(pPI);
  3842. TransferPDA2PSD(pPI);
  3843. pPI->NestCtr++;
  3844. dwHookRet = (*lpfnSetupHook)( hDlg,
  3845. WM_INITDIALOG,
  3846. wParam,
  3847. (pPI->pPSD)
  3848. ? (LONG_PTR)pPI->pPSD
  3849. : (LONG_PTR)pPI->pPDA ) != 0;
  3850. pPI->NestCtr--;
  3851. if (dwHookRet)
  3852. {
  3853. TransferPSD2PDA(pPI);
  3854. ThunkPrintDlgA2W(pPI);
  3855. if (pPI->NestCtr == 0)
  3856. {
  3857. TransferPD2PSD(pPI);
  3858. }
  3859. }
  3860. }
  3861. else
  3862. #endif
  3863. {
  3864. TransferPD2PSD(pPI);
  3865. dwHookRet = (*lpfnSetupHook)( hDlg,
  3866. WM_INITDIALOG,
  3867. wParam,
  3868. (pPI->pPSD)
  3869. ? (LONG_PTR)pPI->pPSD
  3870. : (LONG_PTR)pPD ) != 0;
  3871. TransferPSD2PD(pPI);
  3872. }
  3873. return (dwHookRet);
  3874. }
  3875. return (TRUE);
  3876. InitSetupDlg_ConstructFailure:
  3877. if (!GetStoredExtendedError())
  3878. {
  3879. StoreExtendedError(PDERR_INITFAILURE);
  3880. }
  3881. return (0xFFFFFFFF);
  3882. }
  3883. ////////////////////////////////////////////////////////////////////////////
  3884. //
  3885. // PrintUpdateSetupDlg
  3886. //
  3887. // Update the print setup and page setup dialogs with the new settings.
  3888. //
  3889. ////////////////////////////////////////////////////////////////////////////
  3890. VOID PrintUpdateSetupDlg(
  3891. HWND hDlg,
  3892. PPRINTINFO pPI,
  3893. LPDEVMODE pDM,
  3894. BOOL fResetContent)
  3895. {
  3896. HWND hCtl;
  3897. UINT Count;
  3898. UINT Orientation = 0;
  3899. //
  3900. // Update the Size combo box.
  3901. //
  3902. if (hCtl = GetDlgItem(hDlg, ID_SETUP_C_SIZE))
  3903. {
  3904. if (fResetContent)
  3905. {
  3906. PrintInitPaperCombo( pPI,
  3907. hCtl,
  3908. GetDlgItem(hDlg, ID_SETUP_S_SIZE),
  3909. pPI->pCurPrinter,
  3910. pDM,
  3911. DC_PAPERNAMES,
  3912. CCHPAPERNAME,
  3913. DC_PAPERS );
  3914. //
  3915. // PrintInitPaperCombo will turn off the hour glass cursor, so
  3916. // turn it back on.
  3917. //
  3918. HourGlass(TRUE);
  3919. }
  3920. else
  3921. {
  3922. Count = (UINT) SendMessage(hCtl, CB_GETCOUNT, 0, 0);
  3923. while (Count != 0)
  3924. {
  3925. Count--;
  3926. if (pDM->dmPaperSize == (SHORT)SendMessage( hCtl,
  3927. CB_GETITEMDATA,
  3928. Count,
  3929. 0 ) )
  3930. {
  3931. break;
  3932. }
  3933. }
  3934. SendMessage( hCtl,
  3935. CB_SETCURSEL,
  3936. Count,
  3937. 0 );
  3938. }
  3939. }
  3940. //
  3941. // Update the Source combo box.
  3942. //
  3943. if (hCtl = GetDlgItem(hDlg, ID_SETUP_C_SOURCE))
  3944. {
  3945. if (fResetContent)
  3946. {
  3947. PrintInitPaperCombo( pPI,
  3948. hCtl,
  3949. GetDlgItem(hDlg, ID_SETUP_S_SOURCE),
  3950. pPI->pCurPrinter,
  3951. pDM,
  3952. DC_BINNAMES,
  3953. CCHBINNAME,
  3954. DC_BINS );
  3955. //
  3956. // PrintInitPaperCombo will turn off the hour glass cursor, so
  3957. // turn it back on.
  3958. //
  3959. HourGlass(TRUE);
  3960. }
  3961. else
  3962. {
  3963. Count = (UINT) SendMessage(hCtl, CB_GETCOUNT, 0, 0);
  3964. while (Count != 0)
  3965. {
  3966. Count--;
  3967. if (pDM->dmDefaultSource == (SHORT)SendMessage( hCtl,
  3968. CB_GETITEMDATA,
  3969. Count,
  3970. 0 ) )
  3971. {
  3972. break;
  3973. }
  3974. }
  3975. SendMessage( hCtl,
  3976. CB_SETCURSEL,
  3977. Count,
  3978. 0 );
  3979. }
  3980. }
  3981. //
  3982. // Update the Orientation radio buttons.
  3983. //
  3984. if (GetDlgItem(hDlg, ID_SETUP_R_PORTRAIT))
  3985. {
  3986. Orientation = pDM->dmOrientation + ID_SETUP_R_PORTRAIT - DMORIENT_PORTRAIT;
  3987. PrintSetOrientation( hDlg,
  3988. pPI,
  3989. pDM,
  3990. IsDlgButtonChecked(hDlg, ID_SETUP_R_PORTRAIT)
  3991. ? ID_SETUP_R_PORTRAIT
  3992. : ID_SETUP_R_LANDSCAPE,
  3993. Orientation );
  3994. }
  3995. //
  3996. // Update the Duplex radio buttons.
  3997. //
  3998. if (GetDlgItem(hDlg, ID_SETUP_R_NONE))
  3999. {
  4000. PrintSetDuplex( hDlg,
  4001. pDM,
  4002. pDM->dmDuplex + ID_SETUP_R_NONE - DMDUP_SIMPLEX );
  4003. }
  4004. //
  4005. // Update the page setup sample picture.
  4006. //
  4007. if ((Orientation == 0) && (hCtl = GetDlgItem(hDlg, ID_SETUP_W_SAMPLE)))
  4008. {
  4009. Orientation = pDM->dmOrientation + ID_SETUP_R_PORTRAIT - DMORIENT_PORTRAIT;
  4010. PrintUpdatePageSetup( hDlg,
  4011. pPI,
  4012. pDM,
  4013. 0,
  4014. Orientation );
  4015. }
  4016. //
  4017. // Update the Default/Specific Printer radio buttons.
  4018. //
  4019. if (hCtl = GetDlgItem(hDlg, ID_SETUP_R_DEFAULT))
  4020. {
  4021. if ( pPI->pCurPrinter &&
  4022. pPI->pCurPrinter->pPrinterName &&
  4023. !lstrcmp(pPI->pCurPrinter->pPrinterName, pPI->szDefaultPrinter) )
  4024. {
  4025. CheckRadioButton( hDlg,
  4026. ID_SETUP_R_DEFAULT,
  4027. ID_SETUP_R_SPECIFIC,
  4028. ID_SETUP_R_DEFAULT );
  4029. }
  4030. else
  4031. {
  4032. CheckRadioButton( hDlg,
  4033. ID_SETUP_R_DEFAULT,
  4034. ID_SETUP_R_SPECIFIC,
  4035. ID_SETUP_R_SPECIFIC );
  4036. }
  4037. }
  4038. }
  4039. ////////////////////////////////////////////////////////////////////////////
  4040. //
  4041. // PrintSetCopies
  4042. //
  4043. // Sets the appropriate number of copies in the PrintDlg structure and
  4044. // in the DevMode structure.
  4045. //
  4046. ////////////////////////////////////////////////////////////////////////////
  4047. BOOL PrintSetCopies(
  4048. HWND hDlg,
  4049. PPRINTINFO pPI,
  4050. UINT Id)
  4051. {
  4052. LPPRINTDLG pPD = pPI->pPD;
  4053. LPDEVMODE pDM;
  4054. DWORD dwMaxCopies;
  4055. DWORD dwCollate;
  4056. BOOL bAllowCollate;
  4057. if ( (pPD->hDevMode) &&
  4058. (pDM = GlobalLock(pPD->hDevMode)) )
  4059. {
  4060. #ifdef UNICODE
  4061. //
  4062. // If we're coming from a WOW app, we need to only set
  4063. // the copies in the devmode if the PD_USEDEVMODECOPIES
  4064. // flag is set.
  4065. //
  4066. if (IS16BITWOWAPP(pPD))
  4067. {
  4068. if (pPD->Flags & PD_USEDEVMODECOPIES)
  4069. {
  4070. pDM->dmCopies = pPD->nCopies;
  4071. pPD->nCopies = 1;
  4072. }
  4073. else
  4074. {
  4075. pDM->dmCopies = 1;
  4076. }
  4077. return (TRUE);
  4078. }
  4079. #endif
  4080. if ( (!(pDM->dmFields & DM_COPIES)) ||
  4081. ((!(pPI->pPSD)) &&
  4082. (pPI->ProcessVersion < 0x40000) &&
  4083. (!(pPD->Flags & PD_USEDEVMODECOPIES))) )
  4084. {
  4085. LeaveInfoInPD:
  4086. //
  4087. // The driver cannot do copies, so leave the
  4088. // copy/collate info in the pPD.
  4089. //
  4090. pDM->dmCopies = 1;
  4091. SetField(pDM, dmCollate, DMCOLLATE_FALSE);
  4092. }
  4093. else if ( (pDM->dmSpecVersion < 0x0400) ||
  4094. (!(pDM->dmFields & DM_COLLATE)) )
  4095. {
  4096. //
  4097. // The driver can do copies, but not collate.
  4098. // Where the info goes depends on the PD_COLLATE flag.
  4099. //
  4100. if (pPD->Flags & PD_COLLATE)
  4101. {
  4102. goto LeaveInfoInPD;
  4103. }
  4104. else
  4105. {
  4106. goto PutInfoInDevMode;
  4107. }
  4108. }
  4109. else
  4110. {
  4111. PutInfoInDevMode:
  4112. //
  4113. // Make sure we have a current printer.
  4114. //
  4115. if (!pPI->pCurPrinter)
  4116. {
  4117. goto LeaveInfoInPD;
  4118. }
  4119. //
  4120. // Make sure the driver can support the number
  4121. // of copies requested and collation.
  4122. //
  4123. dwMaxCopies = DeviceCapabilities(
  4124. pPI->pCurPrinter->pPrinterName,
  4125. pPI->pCurPrinter->pPortName,
  4126. DC_COPIES,
  4127. NULL,
  4128. NULL );
  4129. //
  4130. // If DeviceCapabilities() returns error, set the copy number to 1
  4131. //
  4132. if ((dwMaxCopies < 1) || (dwMaxCopies == (DWORD)(-1)))
  4133. {
  4134. dwMaxCopies = 1;
  4135. }
  4136. if (dwMaxCopies < pPD->nCopies)
  4137. {
  4138. if (pPD->Flags & PD_USEDEVMODECOPIES)
  4139. {
  4140. PrintEditError( hDlg,
  4141. (Id == ID_PRINT_C_NAME)
  4142. ? ID_PRINT_E_COPIES
  4143. : ID_BOTH_P_PROPERTIES,
  4144. iszTooManyCopies,
  4145. dwMaxCopies );
  4146. GlobalUnlock(pPD->hDevMode);
  4147. return (FALSE);
  4148. }
  4149. goto LeaveInfoInPD;
  4150. }
  4151. dwCollate = DeviceCapabilities(
  4152. pPI->pCurPrinter->pPrinterName,
  4153. pPI->pCurPrinter->pPortName,
  4154. DC_COLLATE,
  4155. NULL,
  4156. NULL );
  4157. bAllowCollate = ((dwCollate < 1) || (dwCollate == (DWORD)-1)) ? FALSE : TRUE;
  4158. //
  4159. // The driver can do both copies and collate,
  4160. // so move the info to the devmode.
  4161. //
  4162. pDM->dmCopies = pPD->nCopies;
  4163. SetField( pDM,
  4164. dmCollate,
  4165. (bAllowCollate && (pPD->Flags & PD_COLLATE))
  4166. ? DMCOLLATE_TRUE
  4167. : DMCOLLATE_FALSE );
  4168. pPD->nCopies = 1;
  4169. pPD->Flags &= ~PD_COLLATE;
  4170. }
  4171. GlobalUnlock(pPD->hDevMode);
  4172. }
  4173. return (TRUE);
  4174. }
  4175. ////////////////////////////////////////////////////////////////////////////
  4176. //
  4177. // PrintSetMinMargins
  4178. //
  4179. ////////////////////////////////////////////////////////////////////////////
  4180. VOID PrintSetMinMargins(
  4181. HWND hDlg,
  4182. PPRINTINFO pPI,
  4183. LPDEVMODE pDM)
  4184. {
  4185. LPPAGESETUPDLG pPSD = pPI->pPSD;
  4186. HDC hDC;
  4187. RECT rtMinMargin;
  4188. if (!pPSD)
  4189. {
  4190. return;
  4191. }
  4192. if (pPSD->Flags & PSD_MINMARGINS)
  4193. {
  4194. //
  4195. // Convert passed in margins to 10th of MMs.
  4196. //
  4197. if (pPSD->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
  4198. {
  4199. pPI->RtMinMarginMMs.left = pPSD->rtMinMargin.left / 10;
  4200. pPI->RtMinMarginMMs.top = pPSD->rtMinMargin.top / 10;
  4201. pPI->RtMinMarginMMs.right = pPSD->rtMinMargin.right / 10;
  4202. pPI->RtMinMarginMMs.bottom = pPSD->rtMinMargin.bottom / 10;
  4203. }
  4204. else // PSD_INTHOUSANDTHSOFINCHES
  4205. {
  4206. pPI->RtMinMarginMMs.left = pPSD->rtMinMargin.left * MMS_PER_INCH / 100;
  4207. pPI->RtMinMarginMMs.top = pPSD->rtMinMargin.top * MMS_PER_INCH / 100;
  4208. pPI->RtMinMarginMMs.right = pPSD->rtMinMargin.right * MMS_PER_INCH / 100;
  4209. pPI->RtMinMarginMMs.bottom = pPSD->rtMinMargin.bottom * MMS_PER_INCH / 100;
  4210. }
  4211. }
  4212. else
  4213. {
  4214. //
  4215. // Default to no minimum if we can't get the info.
  4216. //
  4217. pPI->RtMinMarginMMs.left = 0;
  4218. pPI->RtMinMarginMMs.top = 0;
  4219. pPI->RtMinMarginMMs.right = 0;
  4220. pPI->RtMinMarginMMs.bottom = 0;
  4221. pPSD->rtMinMargin.left = 0;
  4222. pPSD->rtMinMargin.top = 0;
  4223. pPSD->rtMinMargin.right = 0;
  4224. pPSD->rtMinMargin.bottom = 0;
  4225. //
  4226. // Calculate new min margins from driver.
  4227. //
  4228. if (hDC = CreateIC(NULL, pDM->dmDeviceName, NULL, pDM))
  4229. {
  4230. //
  4231. // These are in PIXELS.
  4232. //
  4233. int nPageWidth = GetDeviceCaps(hDC, PHYSICALWIDTH);
  4234. int nPageHeight = GetDeviceCaps(hDC, PHYSICALHEIGHT);
  4235. int nPrintWidth = GetDeviceCaps(hDC, HORZRES);
  4236. int nPrintHeight = GetDeviceCaps(hDC, VERTRES);
  4237. int nOffsetWidth = GetDeviceCaps(hDC, PHYSICALOFFSETX);
  4238. int nOffsetHeight = GetDeviceCaps(hDC, PHYSICALOFFSETY);
  4239. int nPerInchWidth = GetDeviceCaps(hDC, LOGPIXELSX);
  4240. int nPerInchHeight = GetDeviceCaps(hDC, LOGPIXELSY);
  4241. //
  4242. // Calculate min margins in PIXELS.
  4243. //
  4244. rtMinMargin.left = nOffsetWidth;
  4245. rtMinMargin.top = nOffsetHeight;
  4246. rtMinMargin.right = nPageWidth - nPrintWidth - nOffsetWidth;
  4247. rtMinMargin.bottom = nPageHeight - nPrintHeight - nOffsetHeight;
  4248. //
  4249. // Convert to 10ths of MMs.
  4250. //
  4251. if (nPerInchWidth && nPerInchHeight)
  4252. {
  4253. pPI->RtMinMarginMMs.left = rtMinMargin.left * MMS_PER_INCH / nPerInchWidth / 10;
  4254. pPI->RtMinMarginMMs.top = rtMinMargin.top * MMS_PER_INCH / nPerInchHeight / 10;
  4255. pPI->RtMinMarginMMs.right = rtMinMargin.right * MMS_PER_INCH / nPerInchHeight / 10;
  4256. pPI->RtMinMarginMMs.bottom = rtMinMargin.bottom * MMS_PER_INCH / nPerInchHeight / 10;
  4257. }
  4258. if (pPSD->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
  4259. {
  4260. //
  4261. // Convert to 100ths of MMs.
  4262. //
  4263. pPSD->rtMinMargin.left = pPI->RtMinMarginMMs.left / 10;
  4264. pPSD->rtMinMargin.top = pPI->RtMinMarginMMs.top / 10;
  4265. pPSD->rtMinMargin.right = pPI->RtMinMarginMMs.right / 10;
  4266. pPSD->rtMinMargin.bottom = pPI->RtMinMarginMMs.bottom / 10;
  4267. }
  4268. else // PSD_INTHOUSANDTHSOFINCHES
  4269. {
  4270. //
  4271. // Convert to 1000ths of inches.
  4272. //
  4273. if (nPerInchWidth && nPerInchHeight)
  4274. {
  4275. pPSD->rtMinMargin.left = rtMinMargin.left * 1000 / nPerInchWidth;
  4276. pPSD->rtMinMargin.top = rtMinMargin.top * 1000 / nPerInchHeight;
  4277. pPSD->rtMinMargin.right = rtMinMargin.right * 1000 / nPerInchHeight;
  4278. pPSD->rtMinMargin.bottom = rtMinMargin.bottom * 1000 / nPerInchHeight;
  4279. }
  4280. }
  4281. DeleteDC(hDC);
  4282. }
  4283. }
  4284. }
  4285. ////////////////////////////////////////////////////////////////////////////
  4286. //
  4287. // PrintSetupMargins
  4288. //
  4289. ////////////////////////////////////////////////////////////////////////////
  4290. VOID PrintSetupMargins(
  4291. HWND hDlg,
  4292. PPRINTINFO pPI)
  4293. {
  4294. TCHAR szMars[32];
  4295. TCHAR szText[16];
  4296. int ids[4] = { ID_SETUP_E_LEFT,
  4297. ID_SETUP_E_TOP,
  4298. ID_SETUP_E_RIGHT,
  4299. ID_SETUP_E_BOTTOM };
  4300. int i;
  4301. HWND hEdt;
  4302. //
  4303. // Margins are only available from the PageSetupDlg.
  4304. //
  4305. if (!(pPI->pPSD))
  4306. {
  4307. return;
  4308. }
  4309. for (i = 0; i < 4; i++)
  4310. {
  4311. if (hEdt = GetDlgItem(hDlg, ids[i]))
  4312. {
  4313. //
  4314. // "999999" is the maximum value.
  4315. //
  4316. SendMessage(hEdt, EM_LIMITTEXT, MARGIN_EDIT_SIZE, 0);
  4317. lpEditMarginProc =
  4318. (WNDPROC)SetWindowLongPtr( hEdt,
  4319. GWLP_WNDPROC,
  4320. (LONG_PTR)PrintEditMarginProc );
  4321. }
  4322. }
  4323. if (!GetLocaleInfo( LOCALE_USER_DEFAULT,
  4324. LOCALE_SDECIMAL,
  4325. szText,
  4326. 16 ))
  4327. {
  4328. cIntlDecimal = CHAR_DOT;
  4329. }
  4330. else
  4331. {
  4332. cIntlDecimal = szText[0];
  4333. }
  4334. switch (pPI->pPSD->Flags & (PSD_INTHOUSANDTHSOFINCHES |
  4335. PSD_INHUNDREDTHSOFMILLIMETERS))
  4336. {
  4337. case ( PSD_INHUNDREDTHSOFMILLIMETERS ) :
  4338. {
  4339. CDLoadString(g_hinst, iszMarginsMillimeters, szMars, 32);
  4340. CDLoadString(g_hinst, iszMillimeters, cIntlMeasure, 5);
  4341. break;
  4342. }
  4343. case ( PSD_INTHOUSANDTHSOFINCHES ) :
  4344. {
  4345. CDLoadString(g_hinst, iszMarginsInches, szMars, 32);
  4346. CDLoadString(g_hinst, iszInches, cIntlMeasure, 5);
  4347. break;
  4348. }
  4349. }
  4350. cchIntlMeasure = lstrlen(cIntlMeasure);
  4351. SetWindowText(GetDlgItem(hDlg, ID_SETUP_G_MARGINS), szMars);
  4352. pPI->PtMargins.x = 2 * (IS_KEY_PRESSED(pPI->PtMargins.x / 4) &&
  4353. IS_KEY_PRESSED(pPI->PtMargins.y / 4)
  4354. ? sizeof(WCHAR)
  4355. : sizeof(CHAR));
  4356. pPI->PtMargins.y = 2 * pPI->PtMargins.x;
  4357. }
  4358. ////////////////////////////////////////////////////////////////////////////
  4359. //
  4360. // PrintSetMargin
  4361. //
  4362. ////////////////////////////////////////////////////////////////////////////
  4363. VOID PrintSetMargin(
  4364. HWND hDlg,
  4365. PPRINTINFO pPI,
  4366. UINT Id,
  4367. LONG lValue)
  4368. {
  4369. HWND hEdt;
  4370. TCHAR szText[32];
  4371. TCHAR szILZero[2];
  4372. LONG lFract;
  4373. if (hEdt = GetDlgItem(hDlg, Id))
  4374. {
  4375. switch (pPI->pPSD->Flags & (PSD_INTHOUSANDTHSOFINCHES |
  4376. PSD_INHUNDREDTHSOFMILLIMETERS))
  4377. {
  4378. case ( PSD_INHUNDREDTHSOFMILLIMETERS ) :
  4379. {
  4380. lFract = lValue % 100;
  4381. wsprintf( szText,
  4382. lFract ? TEXT("%lu%c%02lu") : TEXT("%lu"),
  4383. lValue / 100,
  4384. cIntlDecimal,
  4385. lFract );
  4386. break;
  4387. }
  4388. case ( PSD_INTHOUSANDTHSOFINCHES ) :
  4389. {
  4390. lFract = lValue % 1000;
  4391. wsprintf( szText,
  4392. lFract ? TEXT("%lu%c%03lu") : TEXT("%lu"),
  4393. lValue / 1000,
  4394. cIntlDecimal,
  4395. lFract );
  4396. break;
  4397. }
  4398. }
  4399. //
  4400. // Remove trailing zeros off of fraction.
  4401. //
  4402. if (lFract)
  4403. {
  4404. LPTSTR pStr = szText + lstrlen(szText) - 1;
  4405. while (*pStr == TEXT('0'))
  4406. {
  4407. *pStr-- = TEXT('\0');
  4408. }
  4409. }
  4410. //
  4411. // Determine if a leading zero is to be used and write the
  4412. // text to the edit window.
  4413. //
  4414. if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILZERO, szILZero, 2))
  4415. {
  4416. szILZero[0] = TEXT('0');
  4417. }
  4418. SetWindowText( hEdt,
  4419. szText + (szText[0] == TEXT('0') &&
  4420. szText[1] == cIntlDecimal &&
  4421. szILZero[0] == TEXT('0')) );
  4422. }
  4423. }
  4424. ////////////////////////////////////////////////////////////////////////////
  4425. //
  4426. // PrintGetMargin
  4427. //
  4428. ////////////////////////////////////////////////////////////////////////////
  4429. VOID PrintGetMargin(
  4430. HWND hEdt,
  4431. PPRINTINFO pPI,
  4432. LONG lMin,
  4433. LONG *plMargin,
  4434. LONG *plSample)
  4435. {
  4436. TCHAR szText[16];
  4437. TCHAR *pText;
  4438. TCHAR *pFrac;
  4439. GetWindowText(hEdt, szText, ARRAYSIZE(szText));
  4440. szText[ARRAYSIZE(szText)-1] = 0;
  4441. *plMargin = ConvertStringToInteger(szText);
  4442. for (pText = szText; *pText;)
  4443. {
  4444. if (*pText++ == cIntlDecimal)
  4445. {
  4446. break;
  4447. }
  4448. }
  4449. for (pFrac = pText; *pFrac; pFrac++)
  4450. {
  4451. if (*pFrac == cIntlMeasure[0])
  4452. {
  4453. *pFrac = CHAR_NULL;
  4454. break;
  4455. }
  4456. if (*pFrac == cIntlDecimal)
  4457. {
  4458. *pFrac = CHAR_NULL;
  4459. break;
  4460. }
  4461. }
  4462. StrCatBuff(szText, TEXT("000"), ARRAYSIZE(szText));
  4463. switch (pPI->pPSD->Flags & (PSD_INTHOUSANDTHSOFINCHES |
  4464. PSD_INHUNDREDTHSOFMILLIMETERS))
  4465. {
  4466. case ( PSD_INTHOUSANDTHSOFINCHES ) :
  4467. {
  4468. //
  4469. // In 1000ths of inches.
  4470. //
  4471. *plMargin *= 1000;
  4472. pText[3] = CHAR_NULL;
  4473. *plMargin += ConvertStringToInteger(pText);
  4474. *plMargin = max(lMin, *plMargin);
  4475. //
  4476. // In 10ths of MMs.
  4477. //
  4478. *plSample = *plMargin * MMS_PER_INCH / 1000;
  4479. break;
  4480. }
  4481. case ( PSD_INHUNDREDTHSOFMILLIMETERS ) :
  4482. {
  4483. //
  4484. // In 100ths of MMs.
  4485. //
  4486. *plMargin *= 100 ;
  4487. pText[2] = CHAR_NULL;
  4488. *plMargin += ConvertStringToInteger(pText);
  4489. *plMargin = max(lMin, *plMargin);
  4490. //
  4491. // In 10ths of MMs.
  4492. //
  4493. *plSample = *plMargin / 10;
  4494. break;
  4495. }
  4496. }
  4497. }
  4498. ////////////////////////////////////////////////////////////////////////////
  4499. //
  4500. // PrintInitBannerAndQuality
  4501. //
  4502. // Reset PRINT DLG items dependent upon which printer was selected.
  4503. // Assumes that pPD->hDevNames is non-NULL. pPD->hDevMode non-NULL.
  4504. //
  4505. ////////////////////////////////////////////////////////////////////////////
  4506. BOOL PrintInitBannerAndQuality(
  4507. HWND hDlg,
  4508. PPRINTINFO pPI,
  4509. LPPRINTDLG pPD)
  4510. {
  4511. HWND hCtl;
  4512. BOOL bResult = TRUE;
  4513. LPDEVMODE pDM = NULL;
  4514. LPDEVNAMES pDN = NULL;
  4515. TCHAR szText[MAX_DEV_SECT];
  4516. //
  4517. // ID_PRINT_S_DEFAULT is from one of the old templates.
  4518. //
  4519. if (GetDlgItem(hDlg, ID_PRINT_S_DEFAULT))
  4520. {
  4521. if (!pPD->hDevNames ||
  4522. !(pDN = GlobalLock(pPD->hDevNames)))
  4523. {
  4524. StoreExtendedError(CDERR_MEMLOCKFAILURE);
  4525. return (FALSE);
  4526. }
  4527. if (PrintCreateBanner(hDlg, pDN, szText, MAX_DEV_SECT))
  4528. {
  4529. SetDlgItemText(hDlg, ID_PRINT_S_DEFAULT, szText);
  4530. }
  4531. else
  4532. {
  4533. //
  4534. // PrintCreateBanner sets the extended error.
  4535. //
  4536. bResult = FALSE;
  4537. }
  4538. GlobalUnlock(pPD->hDevNames);
  4539. }
  4540. //
  4541. // If the driver says it can do copies, pay attention to what the
  4542. // app requested. If it cannot do copies, check & disable the
  4543. // checkbox.
  4544. //
  4545. if (pPD->hDevMode)
  4546. {
  4547. if (!(pDM = GlobalLock(pPD->hDevMode)))
  4548. {
  4549. StoreExtendedError(CDERR_MEMLOCKFAILURE);
  4550. return (FALSE);
  4551. }
  4552. //
  4553. // Enable print quality, if it exists.
  4554. //
  4555. if (hCtl = GetDlgItem(hDlg, ID_PRINT_S_QUALITY))
  4556. {
  4557. EnableWindow(hCtl, TRUE);
  4558. }
  4559. if (hCtl = GetDlgItem(hDlg, ID_PRINT_C_QUALITY))
  4560. {
  4561. EnableWindow(hCtl, TRUE);
  4562. PrintInitQuality( hCtl,
  4563. pDM->dmSpecVersion <= 0x0300 ? 0L : pPD,
  4564. pDM->dmPrintQuality );
  4565. }
  4566. //
  4567. // If PD_USEDEVMODECOPIES(COLLATE), disable collate if the driver
  4568. // cannot collate.
  4569. //
  4570. if (hCtl = GetDlgItem(hDlg, ID_PRINT_X_COLLATE))
  4571. {
  4572. if ( pDM->dmFields & DM_COLLATE ||
  4573. !(pPD->Flags & PD_USEDEVMODECOPIES) )
  4574. {
  4575. EnableWindow(hCtl, TRUE);
  4576. CheckDlgButton( hDlg,
  4577. ID_PRINT_X_COLLATE,
  4578. (pPI->Status & PI_COLLATE_REQUESTED)
  4579. ? TRUE : FALSE );
  4580. }
  4581. else
  4582. {
  4583. EnableWindow(hCtl, FALSE);
  4584. CheckDlgButton(hDlg, ID_PRINT_X_COLLATE, FALSE);
  4585. }
  4586. }
  4587. //
  4588. // If PD_USEDEVMODECOPIES(COLLATE), disable copies if the driver
  4589. // cannot copy.
  4590. //
  4591. if (hCtl = GetDlgItem(hDlg, ID_PRINT_E_COPIES))
  4592. {
  4593. if ( pDM->dmFields & DM_COPIES ||
  4594. !(pPD->Flags & PD_USEDEVMODECOPIES) )
  4595. {
  4596. SetDlgItemInt(hDlg, ID_PRINT_E_COPIES, pPD->nCopies, FALSE);
  4597. EnableWindow(hCtl, TRUE);
  4598. }
  4599. else
  4600. {
  4601. SetDlgItemInt(hDlg, ID_PRINT_E_COPIES, 1, FALSE);
  4602. EnableWindow(hCtl, FALSE);
  4603. }
  4604. }
  4605. //
  4606. // Display the appropriate collate icon.
  4607. //
  4608. if (hCtl = GetDlgItem(hDlg, ID_PRINT_I_COLLATE))
  4609. {
  4610. SetWindowLong( hCtl,
  4611. GWL_STYLE,
  4612. GetWindowLong(hCtl, GWL_STYLE) | SS_CENTERIMAGE );
  4613. ShowWindow(hCtl, SW_HIDE);
  4614. SendMessage( hCtl,
  4615. STM_SETICON,
  4616. IsDlgButtonChecked(hDlg, ID_PRINT_X_COLLATE)
  4617. ? (LONG_PTR)hIconCollate
  4618. : (LONG_PTR)hIconNoCollate,
  4619. 0L );
  4620. ShowWindow(hCtl, SW_SHOW);
  4621. }
  4622. GlobalUnlock(pPD->hDevMode);
  4623. }
  4624. else
  4625. {
  4626. //
  4627. // Disable the print quality, collate, and copies.
  4628. //
  4629. if (hCtl = GetDlgItem(hDlg, ID_PRINT_S_QUALITY))
  4630. {
  4631. EnableWindow(hCtl, FALSE);
  4632. }
  4633. if (hCtl = GetDlgItem(hDlg, ID_PRINT_C_QUALITY))
  4634. {
  4635. EnableWindow(hCtl, FALSE);
  4636. }
  4637. if (hCtl = GetDlgItem(hDlg, ID_PRINT_X_COLLATE))
  4638. {
  4639. EnableWindow(hCtl, FALSE);
  4640. }
  4641. if (hCtl = GetDlgItem(hDlg, ID_PRINT_E_COPIES))
  4642. {
  4643. EnableWindow(hCtl, FALSE);
  4644. }
  4645. }
  4646. return (bResult);
  4647. }
  4648. ////////////////////////////////////////////////////////////////////////////
  4649. //
  4650. // PrintCreateBanner
  4651. //
  4652. // Create "Printer: Prn on Port" or "Printer: System Printer (Prn)".
  4653. //
  4654. ////////////////////////////////////////////////////////////////////////////
  4655. BOOL PrintCreateBanner(
  4656. HWND hDlg,
  4657. LPDEVNAMES pDN,
  4658. LPTSTR psBanner,
  4659. UINT cchBanner)
  4660. {
  4661. if (GetDlgItem(hDlg, ID_BOTH_S_PRINTER))
  4662. {
  4663. psBanner[0] = CHAR_NULL;
  4664. }
  4665. else if (!CDLoadString( g_hinst,
  4666. iszPrinter,
  4667. psBanner,
  4668. cchBanner ))
  4669. {
  4670. goto LoadStrFailure;
  4671. }
  4672. if (pDN->wDefault & DN_DEFAULTPRN)
  4673. {
  4674. TCHAR szSysPrn[MAX_DEV_SECT];
  4675. if (!CDLoadString(g_hinst, iszSysPrn, szSysPrn, MAX_DEV_SECT))
  4676. {
  4677. goto LoadStrFailure;
  4678. }
  4679. StrCatBuff(psBanner, (LPTSTR)szSysPrn, cchBanner);
  4680. StrCatBuff(psBanner, (LPTSTR)pDN + pDN->wDeviceOffset, cchBanner);
  4681. StrCatBuff(psBanner, (LPTSTR)TEXT(")"), cchBanner);
  4682. }
  4683. else
  4684. {
  4685. TCHAR szPrnOnPort[64];
  4686. if (!CDLoadString(g_hinst, iszPrnOnPort, szPrnOnPort, 64))
  4687. {
  4688. goto LoadStrFailure;
  4689. }
  4690. StrCatBuff(psBanner, (LPTSTR)pDN + pDN->wDeviceOffset, cchBanner);
  4691. StrCatBuff(psBanner, (LPTSTR)szPrnOnPort, cchBanner);
  4692. StrCatBuff(psBanner, (LPTSTR)pDN + pDN->wOutputOffset, cchBanner);
  4693. }
  4694. return (TRUE);
  4695. LoadStrFailure:
  4696. StoreExtendedError(CDERR_LOADSTRFAILURE);
  4697. return (FALSE);
  4698. }
  4699. ////////////////////////////////////////////////////////////////////////////
  4700. //
  4701. // PrintInitQuality
  4702. //
  4703. // Initializes the Printer Quality Combobox.
  4704. //
  4705. // Assumes pPD structure filled by caller. If non-NULL, it's a 3.1 or
  4706. // later driver. If NULL, fill with default for 3.0.
  4707. //
  4708. ////////////////////////////////////////////////////////////////////////////
  4709. VOID PrintInitQuality(
  4710. HANDLE hCmb,
  4711. LPPRINTDLG pPD,
  4712. SHORT nQuality)
  4713. {
  4714. SHORT nStringID;
  4715. SHORT i;
  4716. TCHAR szBuf[64];
  4717. LPDEVMODE pDM = NULL;
  4718. LPDEVNAMES pDN = NULL;
  4719. SendMessage(hCmb, CB_RESETCONTENT, 0, 0L);
  4720. //
  4721. // Enum print qualities.
  4722. //
  4723. if (pPD && pPD->hDevMode && pPD->hDevNames)
  4724. {
  4725. HANDLE hPrnQ; // Memory handle for print qualities
  4726. DWORD dw; // return from DC_ENUMRESOLUTIONS
  4727. LPLONG pLong; // Pointer to pairs of longs
  4728. LPTSTR psDevice;
  4729. LPTSTR psPort;
  4730. pDM = GlobalLock(pPD->hDevMode);
  4731. pDN = GlobalLock(pPD->hDevNames);
  4732. if (pDM->dmSpecVersion < 0x030A)
  4733. {
  4734. goto EnumResNotSupported;
  4735. }
  4736. psDevice = (LPTSTR)pDN + pDN->wDeviceOffset;
  4737. psPort = (LPTSTR)pDN + pDN->wOutputOffset;
  4738. dw = DeviceCapabilities( psDevice,
  4739. psPort,
  4740. DC_ENUMRESOLUTIONS,
  4741. NULL,
  4742. NULL );
  4743. if (!dw || (dw == (DWORD)(-1)))
  4744. {
  4745. goto EnumResNotSupported;
  4746. }
  4747. hPrnQ = GlobalAlloc(GHND, dw * 2 * sizeof(LONG));
  4748. if (!hPrnQ)
  4749. {
  4750. goto EnumResNotSupported;
  4751. }
  4752. if (pLong = GlobalLock(hPrnQ))
  4753. {
  4754. dw = DeviceCapabilities( psDevice,
  4755. psPort,
  4756. DC_ENUMRESOLUTIONS,
  4757. (LPTSTR)pLong,
  4758. 0 );
  4759. for (nStringID = 0, i = (SHORT)(LOWORD(dw) - 1); i >= 0; i--)
  4760. {
  4761. DWORD xRes, yRes;
  4762. if ((xRes = pLong[i * 2]) != (yRes = pLong[i * 2 + 1]) )
  4763. {
  4764. wsprintf(szBuf, TEXT("%ld dpi x %ld dpi"), xRes, yRes);
  4765. }
  4766. else
  4767. {
  4768. wsprintf(szBuf, TEXT("%ld dpi"), yRes);
  4769. }
  4770. SendMessage(hCmb, CB_INSERTSTRING, 0, (LONG_PTR)(LPTSTR)szBuf);
  4771. SendMessage(hCmb, CB_SETITEMDATA, 0, xRes);
  4772. if ( ((SHORT)xRes == nQuality) &&
  4773. ( (wWinVer < 0x030A) ||
  4774. !pDM->dmYResolution ||
  4775. (pDM->dmYResolution == (SHORT)yRes) ) )
  4776. {
  4777. nStringID = i;
  4778. }
  4779. }
  4780. GlobalUnlock(hPrnQ);
  4781. }
  4782. GlobalFree(hPrnQ);
  4783. SendMessage(hCmb, CB_SETCURSEL, (WPARAM)nStringID, 0L);
  4784. }
  4785. else
  4786. {
  4787. EnumResNotSupported:
  4788. for ( i = -1, nStringID = iszDraftPrnQ;
  4789. nStringID >= iszHighPrnQ;
  4790. i--, nStringID-- )
  4791. {
  4792. if (!CDLoadString(g_hinst, nStringID, szBuf, 64))
  4793. {
  4794. return;
  4795. }
  4796. SendMessage(hCmb, CB_INSERTSTRING, 0, (LONG_PTR)(LPTSTR)szBuf);
  4797. SendMessage(hCmb, CB_SETITEMDATA, 0, MAKELONG(i, 0));
  4798. }
  4799. if ((nQuality >= 0) || (nQuality < -4))
  4800. {
  4801. //
  4802. // Set to HIGH.
  4803. //
  4804. nQuality = -4;
  4805. }
  4806. SendMessage(hCmb, CB_SETCURSEL, (WPARAM)(nQuality + 4), 0L);
  4807. }
  4808. if (pDM)
  4809. {
  4810. GlobalUnlock(pPD->hDevMode);
  4811. }
  4812. if (pDN)
  4813. {
  4814. GlobalUnlock(pPD->hDevNames);
  4815. }
  4816. }
  4817. ////////////////////////////////////////////////////////////////////////////
  4818. //
  4819. // PrintChangeProperties
  4820. //
  4821. // Puts up the dialog to modify the properties.
  4822. //
  4823. ////////////////////////////////////////////////////////////////////////////
  4824. VOID PrintChangeProperties(
  4825. HWND hDlg,
  4826. UINT Id,
  4827. PPRINTINFO pPI)
  4828. {
  4829. LPPRINTDLG pPD = pPI->pPD;
  4830. LPDEVMODE pDM;
  4831. LONG cbNeeded;
  4832. HANDLE hDevMode;
  4833. WORD nCopies, nCollate;
  4834. BOOL bTest;
  4835. HWND hCtl;
  4836. //
  4837. // There must be a devmode already.
  4838. //
  4839. if (!pPD->hDevMode)
  4840. {
  4841. return;
  4842. }
  4843. //
  4844. // Get the number of bytes needed for the devmode.
  4845. //
  4846. cbNeeded = DocumentProperties( hDlg,
  4847. pPI->hCurPrinter,
  4848. (pPI->pCurPrinter)
  4849. ? pPI->pCurPrinter->pPrinterName
  4850. : NULL,
  4851. NULL,
  4852. NULL,
  4853. 0 );
  4854. //
  4855. // Reallocate the devmode to be sure there is enough room in it, and
  4856. // then put up the document properties dialog box.
  4857. //
  4858. if ( (cbNeeded > 0) &&
  4859. (hDevMode = GlobalReAlloc(pPD->hDevMode, cbNeeded, GHND)) &&
  4860. (pDM = GlobalLock(hDevMode)) )
  4861. {
  4862. //
  4863. // This is done here to make sure that the ReAlloc succeeded
  4864. // before trashing the old hDevMode.
  4865. //
  4866. pPD->hDevMode = hDevMode;
  4867. //
  4868. // Set the number of copies and collation in the devmode before
  4869. // calling DocumentProperties, if appropriate.
  4870. //
  4871. nCopies = pDM->dmCopies;
  4872. nCollate = pDM->dmCollate;
  4873. if (Id == ID_PRINT_C_NAME)
  4874. {
  4875. //
  4876. // Get the number of copies from the edit control.
  4877. //
  4878. pDM->dmCopies = (WORD)GetDlgItemInt( hDlg,
  4879. ID_PRINT_E_COPIES,
  4880. &bTest,
  4881. FALSE );
  4882. if ((!bTest) || (!pDM->dmCopies))
  4883. {
  4884. pDM->dmCopies = nCopies;
  4885. }
  4886. //
  4887. // Get the collation from the check box.
  4888. //
  4889. if ( (hCtl = GetDlgItem(hDlg, ID_PRINT_X_COLLATE)) &&
  4890. IsWindowEnabled(hCtl) )
  4891. {
  4892. SetField( pDM,
  4893. dmCollate,
  4894. (IsDlgButtonChecked(hDlg, ID_PRINT_X_COLLATE))
  4895. ? DMCOLLATE_TRUE
  4896. : DMCOLLATE_FALSE );
  4897. }
  4898. }
  4899. else // ID_SETUP_C_NAME
  4900. {
  4901. if ( (pDM->dmFields & DM_COPIES) &&
  4902. (pPI->ProcessVersion < 0x40000) &&
  4903. (!(pPD->Flags & PD_USEDEVMODECOPIES)) &&
  4904. (pPD->nCopies) )
  4905. {
  4906. pDM->dmCopies = pPD->nCopies;
  4907. if (pDM->dmFields & DM_COLLATE)
  4908. {
  4909. //
  4910. // DM_COLLATE was specified, so dmCollate exists.
  4911. //
  4912. pDM->dmCollate = (pPD->Flags & PD_COLLATE)
  4913. ? DMCOLLATE_TRUE
  4914. : DMCOLLATE_FALSE;
  4915. }
  4916. }
  4917. }
  4918. //
  4919. // Put up the Document Properties dialog box.
  4920. //
  4921. if (DocumentProperties( hDlg,
  4922. pPI->hCurPrinter,
  4923. (pPI->pCurPrinter)
  4924. ? pPI->pCurPrinter->pPrinterName
  4925. : NULL,
  4926. pDM,
  4927. pDM,
  4928. DM_PROMPT | DM_MODIFY | DM_COPY ) == IDOK)
  4929. {
  4930. //
  4931. // Save the new number of copies and collation, if appropriate.
  4932. //
  4933. if (pDM->dmFields & DM_COPIES)
  4934. {
  4935. pPD->nCopies = pDM->dmCopies;
  4936. }
  4937. if (pDM->dmFields & DM_COLLATE)
  4938. {
  4939. if (pDM->dmCollate == DMCOLLATE_FALSE)
  4940. {
  4941. pPD->Flags &= ~PD_COLLATE;
  4942. pPI->Status &= ~PI_COLLATE_REQUESTED;
  4943. }
  4944. else
  4945. {
  4946. pPD->Flags |= PD_COLLATE;
  4947. pPI->Status |= PI_COLLATE_REQUESTED;
  4948. }
  4949. }
  4950. //
  4951. // Update the dialog.
  4952. //
  4953. if (Id == ID_PRINT_C_NAME)
  4954. {
  4955. //
  4956. // Update the print dialog with the new info.
  4957. //
  4958. PrintInitBannerAndQuality(hDlg, pPI, pPD);
  4959. }
  4960. else // ID_SETUP_C_NAME
  4961. {
  4962. //
  4963. // Update the print setup dialog with the new info.
  4964. //
  4965. PrintUpdateSetupDlg(hDlg, pPI, pDM, FALSE);
  4966. }
  4967. }
  4968. else
  4969. {
  4970. //
  4971. // Operation cancelled. Restore the number of copies
  4972. // and the collation in the devmode.
  4973. //
  4974. pDM->dmCopies = nCopies;
  4975. SetField(pDM, dmCollate, nCollate);
  4976. }
  4977. GlobalUnlock(pPD->hDevMode);
  4978. SendMessage( hDlg,
  4979. WM_NEXTDLGCTL,
  4980. (WPARAM)GetDlgItem(hDlg, IDOK),
  4981. 1L );
  4982. }
  4983. }
  4984. ////////////////////////////////////////////////////////////////////////////
  4985. //
  4986. // PrintPrinterChanged
  4987. //
  4988. ////////////////////////////////////////////////////////////////////////////
  4989. VOID PrintPrinterChanged(
  4990. HWND hDlg,
  4991. UINT Id,
  4992. PPRINTINFO pPI)
  4993. {
  4994. LPPRINTDLG pPD = pPI->pPD;
  4995. HANDLE hDM = NULL;
  4996. LPDEVMODE pDM = NULL;
  4997. LPDEVMODE pDMOld = NULL;
  4998. HWND hCtl;
  4999. UINT Orientation;
  5000. LONG cbSize;
  5001. DWORD dmSize;
  5002. HourGlass(TRUE);
  5003. //
  5004. // Close the old printer, if necessary.
  5005. //
  5006. if (pPI->hCurPrinter)
  5007. {
  5008. ClosePrinter(pPI->hCurPrinter);
  5009. pPI->hCurPrinter = 0;
  5010. }
  5011. //
  5012. // Get the current printer from the combo box.
  5013. //
  5014. if (Id && (hCtl = GetDlgItem(hDlg, Id)))
  5015. {
  5016. TCHAR szPrinter[MAX_PRINTERNAME];
  5017. DWORD ctr;
  5018. SendMessage( hCtl,
  5019. CB_GETLBTEXT,
  5020. (WPARAM)SendMessage(hCtl, CB_GETCURSEL, 0, 0),
  5021. (LPARAM)(LPTSTR)szPrinter );
  5022. pPI->pCurPrinter = NULL;
  5023. for (ctr = 0; ctr < pPI->cPrinters; ctr++)
  5024. {
  5025. if (!lstrcmp(pPI->pPrinters[ctr].pPrinterName, szPrinter))
  5026. {
  5027. pPI->pCurPrinter = &pPI->pPrinters[ctr];
  5028. break;
  5029. }
  5030. }
  5031. if (!pPI->pCurPrinter)
  5032. {
  5033. HourGlass(FALSE);
  5034. return;
  5035. }
  5036. }
  5037. //
  5038. // Open the current printer.
  5039. //
  5040. OpenPrinter(pPI->pCurPrinter->pPrinterName, &pPI->hCurPrinter, NULL);
  5041. //
  5042. // Build the device names.
  5043. //
  5044. PrintBuildDevNames(pPI);
  5045. //
  5046. // Get the devmode information.
  5047. //
  5048. cbSize = DocumentProperties( hDlg,
  5049. pPI->hCurPrinter,
  5050. pPI->pCurPrinter->pPrinterName,
  5051. NULL,
  5052. NULL,
  5053. 0 );
  5054. if (cbSize > 0)
  5055. {
  5056. hDM = GlobalAlloc(GHND, cbSize);
  5057. //
  5058. // Get the default DevMode for the new printer.
  5059. //
  5060. if (hDM && (pDM = GlobalLock(hDM)) &&
  5061. (DocumentProperties( hDlg,
  5062. pPI->hCurPrinter,
  5063. pPI->pCurPrinter->pPrinterName,
  5064. pDM,
  5065. NULL,
  5066. DM_COPY ) == IDOK))
  5067. {
  5068. //
  5069. // See if we need to merge in old DevMode settings.
  5070. //
  5071. if (pPD->hDevMode && (pDMOld = GlobalLock(pPD->hDevMode)))
  5072. {
  5073. //
  5074. // Reset the PaperSource back to the Document Default.
  5075. //
  5076. if (pDM->dmFields & DM_DEFAULTSOURCE)
  5077. {
  5078. pDMOld->dmFields |= DM_DEFAULTSOURCE;
  5079. pDMOld->dmDefaultSource = pDM->dmDefaultSource;
  5080. }
  5081. else
  5082. {
  5083. pDMOld->dmFields &= ~DM_DEFAULTSOURCE;
  5084. }
  5085. //
  5086. // Copy relevant info from the old devmode to the new
  5087. // devmode.
  5088. //
  5089. dmSize = min(pDM->dmSize, pDMOld->dmSize);
  5090. if (dmSize > FIELD_OFFSET(DEVMODE, dmFields))
  5091. {
  5092. CopyMemory( &(pDM->dmFields),
  5093. &(pDMOld->dmFields),
  5094. dmSize - FIELD_OFFSET(DEVMODE, dmFields) );
  5095. }
  5096. //
  5097. // Free the old devmode.
  5098. //
  5099. GlobalUnlock(pPD->hDevMode);
  5100. GlobalFree(pPD->hDevMode);
  5101. }
  5102. //
  5103. // Save the new DevMode in the pPD structure.
  5104. //
  5105. pPD->hDevMode = hDM;
  5106. //
  5107. // Get the newly merged DevMode.
  5108. //
  5109. pDM->dmFields = pDM->dmFields & (DM_ORIENTATION | DM_PAPERSIZE |
  5110. DM_PAPERLENGTH | DM_PAPERWIDTH |
  5111. DM_SCALE | DM_COPIES |
  5112. DM_COLLATE | DM_FORMNAME |
  5113. DM_DEFAULTSOURCE);
  5114. DocumentProperties( hDlg,
  5115. pPI->hCurPrinter,
  5116. pPI->pCurPrinter->pPrinterName,
  5117. pDM,
  5118. pDM,
  5119. DM_MODIFY | DM_COPY );
  5120. GlobalUnlock(hDM);
  5121. }
  5122. else if (hDM)
  5123. {
  5124. if (pDM)
  5125. {
  5126. GlobalUnlock(hDM);
  5127. }
  5128. GlobalFree(hDM);
  5129. }
  5130. }
  5131. //
  5132. // Fill in the appropriate information for the rest of the
  5133. // Print or Print Setup dialog box.
  5134. //
  5135. if (Id == ID_PRINT_C_NAME)
  5136. {
  5137. PrintInitBannerAndQuality(hDlg, pPI, pPD);
  5138. }
  5139. else // ID_SETUP_C_NAME
  5140. {
  5141. if (pPD->hDevMode && (pDM = GlobalLock(pPD->hDevMode)))
  5142. {
  5143. if (hCtl = GetDlgItem(hDlg, ID_SETUP_C_SIZE))
  5144. {
  5145. PrintInitPaperCombo( pPI,
  5146. hCtl,
  5147. GetDlgItem(hDlg, ID_SETUP_S_SIZE),
  5148. pPI->pCurPrinter,
  5149. pDM,
  5150. DC_PAPERNAMES,
  5151. CCHPAPERNAME,
  5152. DC_PAPERS );
  5153. }
  5154. if (hCtl = GetDlgItem(hDlg, ID_SETUP_C_SOURCE))
  5155. {
  5156. PrintInitPaperCombo( pPI,
  5157. hCtl,
  5158. GetDlgItem(hDlg, ID_SETUP_S_SOURCE),
  5159. pPI->pCurPrinter,
  5160. pDM,
  5161. DC_BINNAMES,
  5162. CCHBINNAME,
  5163. DC_BINS );
  5164. }
  5165. PrintInitOrientation(hDlg, pPI, pDM);
  5166. Orientation = (pDM->dmOrientation == DMORIENT_PORTRAIT)
  5167. ? ID_SETUP_R_PORTRAIT
  5168. : ID_SETUP_R_LANDSCAPE;
  5169. PrintSetOrientation(hDlg, pPI, pDM, Orientation, Orientation);
  5170. PrintInitDuplex(hDlg, pDM);
  5171. PrintSetDuplex( hDlg,
  5172. pDM,
  5173. pDM->dmDuplex + ID_SETUP_R_NONE - DMDUP_SIMPLEX );
  5174. GlobalUnlock(pPD->hDevMode);
  5175. }
  5176. }
  5177. //
  5178. // Update the status information.
  5179. //
  5180. PrintUpdateStatus(hDlg, pPI);
  5181. HourGlass(FALSE);
  5182. }
  5183. ////////////////////////////////////////////////////////////////////////////
  5184. //
  5185. // PrintCancelPrinterChanged
  5186. //
  5187. // Opens the old printer since the user hit cancel. The devmode and
  5188. // devnames structures have already been set back to the old ones.
  5189. //
  5190. ////////////////////////////////////////////////////////////////////////////
  5191. VOID PrintCancelPrinterChanged(
  5192. PPRINTINFO pPI,
  5193. LPTSTR pPrinterName)
  5194. {
  5195. LPPRINTDLG pPD = pPI->pPD;
  5196. PPRINTER_INFO_2 pCurPrinter;
  5197. //
  5198. // Make sure we have a previous printer and a devmode.
  5199. //
  5200. if ((pPrinterName[0] == 0) || (!pPD->hDevMode))
  5201. {
  5202. return;
  5203. }
  5204. //
  5205. // Turn on the hour glass.
  5206. //
  5207. HourGlass(TRUE);
  5208. //
  5209. // Find the current printer in the list.
  5210. //
  5211. pCurPrinter = PrintSearchForPrinter(pPI, pPrinterName);
  5212. if (!pCurPrinter)
  5213. {
  5214. HourGlass(FALSE);
  5215. return;
  5216. }
  5217. //
  5218. // Close the old printer, if necessary.
  5219. //
  5220. if (pPI->hCurPrinter)
  5221. {
  5222. ClosePrinter(pPI->hCurPrinter);
  5223. pPI->hCurPrinter = 0;
  5224. }
  5225. //
  5226. // Save the current printer.
  5227. //
  5228. pPI->pCurPrinter = pCurPrinter;
  5229. //
  5230. // Open the current printer.
  5231. //
  5232. OpenPrinter(pPI->pCurPrinter->pPrinterName, &pPI->hCurPrinter, NULL);
  5233. //
  5234. // Turn off the hour glass.
  5235. //
  5236. HourGlass(FALSE);
  5237. }
  5238. ////////////////////////////////////////////////////////////////////////////
  5239. //
  5240. // PrintUpdateStatus
  5241. //
  5242. ////////////////////////////////////////////////////////////////////////////
  5243. VOID PrintUpdateStatus(
  5244. HWND hDlg,
  5245. PPRINTINFO pPI)
  5246. {
  5247. TCHAR szSeparator[] = TEXT("; ");
  5248. TCHAR szText[256];
  5249. TCHAR szJobs[64];
  5250. LPDEVMODE pDM;
  5251. UINT Length;
  5252. DWORD dwStatus;
  5253. int ctr;
  5254. TCHAR *ps;
  5255. BOOL bFound;
  5256. //
  5257. // Update the printer status information in the dialog.
  5258. //
  5259. if (!GetDlgItem(hDlg, ID_BOTH_S_STATUS) || (!pPI->pCurPrinter))
  5260. {
  5261. return;
  5262. }
  5263. //
  5264. // ---------------------- Update Status ----------------------
  5265. //
  5266. szText[0] = CHAR_NULL;
  5267. if (pPI->pCurPrinter->Attributes & PRINTER_ATTRIBUTE_DEFAULT)
  5268. {
  5269. CDLoadString(g_hinst, iszStatusDefaultPrinter, szText, 32);
  5270. }
  5271. Length = lstrlen(szText);
  5272. dwStatus = pPI->pCurPrinter->Status;
  5273. for (ctr = 0; ctr++ < 32; dwStatus = dwStatus >> 1)
  5274. {
  5275. if (dwStatus & 1)
  5276. {
  5277. CDLoadString( g_hinst,
  5278. iszStatusReady + ctr,
  5279. szText + lstrlen(szText),
  5280. 32);
  5281. }
  5282. }
  5283. if (szText[Length])
  5284. {
  5285. if (CDLoadString(g_hinst, iszStatusDocumentsWaiting, szJobs, 64))
  5286. {
  5287. wsprintf( szText + lstrlen(szText),
  5288. szJobs,
  5289. pPI->pCurPrinter->cJobs );
  5290. }
  5291. }
  5292. else
  5293. {
  5294. CDLoadString(g_hinst, iszStatusReady, szText + Length, 32);
  5295. }
  5296. SetDlgItemText(hDlg, ID_BOTH_S_STATUS, szText);
  5297. UpdateWindow(GetDlgItem(hDlg, ID_BOTH_S_STATUS));
  5298. //
  5299. // ---------------------- Update Type ----------------------
  5300. //
  5301. if (pPI->pCurPrinter->pDriverName)
  5302. {
  5303. lstrcpy(szText, pPI->pCurPrinter->pDriverName);
  5304. }
  5305. else
  5306. {
  5307. szText[0] = CHAR_NULL;
  5308. }
  5309. if (pPI->pPD->hDevMode && (pDM = GlobalLock(pPI->pPD->hDevMode)))
  5310. {
  5311. if (pDM->dmSpecVersion < 0x0400)
  5312. {
  5313. lstrcat(szText, TEXT(" (3.x)")); // old driver designation
  5314. }
  5315. GlobalUnlock(pPI->pPD->hDevMode);
  5316. }
  5317. SetDlgItemText(hDlg, ID_BOTH_S_TYPE, szText);
  5318. UpdateWindow(GetDlgItem(hDlg, ID_BOTH_S_TYPE));
  5319. //
  5320. // ---------------------- Update Location ----------------------
  5321. //
  5322. if (pPI->pCurPrinter->pLocation && pPI->pCurPrinter->pLocation[0])
  5323. {
  5324. bFound = FALSE;
  5325. lstrcpy(szText, pPI->pCurPrinter->pLocation);
  5326. for (ps = szText; *ps; ps++)
  5327. {
  5328. if (ps[0] == TEXT('\r') && ps[1] == TEXT('\n'))
  5329. {
  5330. *ps++ = CHAR_SEMICOLON;
  5331. *ps = CHAR_SPACE;
  5332. }
  5333. else
  5334. {
  5335. bFound = TRUE;
  5336. }
  5337. }
  5338. if (!bFound)
  5339. {
  5340. goto ShowPortName;
  5341. }
  5342. }
  5343. else
  5344. {
  5345. ShowPortName:
  5346. if (pPI->pCurPrinter->pPortName)
  5347. {
  5348. lstrcpy(szText, pPI->pCurPrinter->pPortName);
  5349. }
  5350. else
  5351. {
  5352. szText[0] = CHAR_NULL;
  5353. }
  5354. }
  5355. EnableWindow(GetDlgItem(hDlg, ID_BOTH_S_WHERE), szText[0]);
  5356. SetDlgItemText(hDlg, ID_BOTH_S_WHERE, szText);
  5357. UpdateWindow(GetDlgItem(hDlg, ID_BOTH_S_WHERE));
  5358. //
  5359. // ---------------------- Update Comment ----------------------
  5360. //
  5361. if (pPI->pCurPrinter->pComment && pPI->pCurPrinter->pComment[0])
  5362. {
  5363. bFound = FALSE;
  5364. lstrcpy(szText, pPI->pCurPrinter->pComment);
  5365. for (ps = szText; *ps; ps++)
  5366. {
  5367. if (ps[0] == TEXT('\r') && ps[1] == TEXT('\n'))
  5368. {
  5369. *ps++ = CHAR_SEMICOLON;
  5370. *ps = CHAR_SPACE;
  5371. }
  5372. else
  5373. {
  5374. bFound = TRUE;
  5375. }
  5376. }
  5377. if (!bFound)
  5378. {
  5379. //
  5380. // This is needed in case the comment field only has a
  5381. // carriage return in it. Without this check, it will
  5382. // show a ";" in the comment field. In this case, it
  5383. // should show "" in the comment field.
  5384. //
  5385. szText[0] = CHAR_NULL;
  5386. }
  5387. }
  5388. else
  5389. {
  5390. szText[0] = CHAR_NULL;
  5391. }
  5392. EnableWindow(GetDlgItem(hDlg, ID_BOTH_S_COMMENT), szText[0]);
  5393. SetDlgItemText(hDlg, ID_BOTH_S_COMMENT, szText);
  5394. UpdateWindow(GetDlgItem(hDlg, ID_BOTH_S_COMMENT));
  5395. }
  5396. ////////////////////////////////////////////////////////////////////////////
  5397. //
  5398. // PrintGetSetupInfo
  5399. //
  5400. // Purpose: Retrieve info from Print Setup dialog elements
  5401. // Assumes: hDevMode handle to valid DEVMODE structure
  5402. // Returns: TRUE if hDevMode valid, FALSE otherwise
  5403. //
  5404. ////////////////////////////////////////////////////////////////////////////
  5405. BOOL PrintGetSetupInfo(
  5406. HWND hDlg,
  5407. LPPRINTDLG pPD)
  5408. {
  5409. LPDEVMODE pDM = NULL;
  5410. LPDEVNAMES pDN = NULL;
  5411. HWND hCmb;
  5412. int nInd;
  5413. if ( !pPD->hDevMode ||
  5414. !(pDM = GlobalLock(pPD->hDevMode)) )
  5415. {
  5416. return (FALSE);
  5417. }
  5418. // Don't need to do this - this is kept up to date.
  5419. // pDM->dmFields |= DM_ORIENTATION;
  5420. if (hCmb = GetDlgItem(hDlg, ID_SETUP_C_SIZE))
  5421. {
  5422. nInd = (int) SendMessage(hCmb, CB_GETCURSEL, 0, 0L);
  5423. if (nInd != CB_ERR)
  5424. {
  5425. // pDM->dmFields |= DM_PAPERSIZE;
  5426. pDM->dmPaperSize = (SHORT)SendMessage( hCmb,
  5427. CB_GETITEMDATA,
  5428. nInd,
  5429. 0 );
  5430. #ifndef WINNT
  5431. if (pDM->dmSpecVersion >= 0x0400)
  5432. #endif
  5433. {
  5434. // pDM->dmFields |= DM_FORMNAME;
  5435. SendMessage( hCmb,
  5436. CB_GETLBTEXT,
  5437. nInd,
  5438. (LPARAM)pDM->dmFormName );
  5439. }
  5440. }
  5441. }
  5442. if (hCmb = GetDlgItem(hDlg, ID_SETUP_C_SOURCE))
  5443. {
  5444. nInd = (int) SendMessage(hCmb, CB_GETCURSEL, 0 , 0L);
  5445. if (nInd != CB_ERR)
  5446. {
  5447. // pDM->dmFields |= DM_DEFAULTSOURCE;
  5448. pDM->dmDefaultSource = (SHORT)SendMessage( hCmb,
  5449. CB_GETITEMDATA,
  5450. nInd,
  5451. 0 );
  5452. }
  5453. }
  5454. if ( (pPD->hDevNames) &&
  5455. (pDN = GlobalLock(pPD->hDevNames)) )
  5456. {
  5457. PrintReturnICDC(pPD, pDN, pDM);
  5458. GlobalUnlock(pPD->hDevNames);
  5459. }
  5460. GlobalUnlock(pPD->hDevMode);
  5461. return (TRUE);
  5462. }
  5463. ////////////////////////////////////////////////////////////////////////////
  5464. //
  5465. // PrintSearchForPrinter
  5466. //
  5467. // Returns the pointer to the PRINTER_INFO_2 structure for the printer
  5468. // with the name pPrinterName.
  5469. //
  5470. ////////////////////////////////////////////////////////////////////////////
  5471. PPRINTER_INFO_2 PrintSearchForPrinter(
  5472. PPRINTINFO pPI,
  5473. LPCTSTR lpsPrinterName)
  5474. {
  5475. DWORD ctr;
  5476. //
  5477. // Search for the printer.
  5478. //
  5479. for (ctr = 0; ctr < pPI->cPrinters; ctr++)
  5480. {
  5481. if (!lstrcmp(pPI->pPrinters[ctr].pPrinterName, lpsPrinterName))
  5482. {
  5483. //
  5484. // Found it.
  5485. //
  5486. return (&pPI->pPrinters[ctr]);
  5487. }
  5488. }
  5489. //
  5490. // Did not find the printer.
  5491. //
  5492. return (NULL);
  5493. }
  5494. ////////////////////////////////////////////////////////////////////////////
  5495. //
  5496. // PrintGetExtDeviceMode
  5497. //
  5498. ////////////////////////////////////////////////////////////////////////////
  5499. #ifdef UNICODE
  5500. VOID PrintGetExtDeviceMode(
  5501. HWND hDlg,
  5502. PPRINTINFO pPI)
  5503. {
  5504. DWORD ctr;
  5505. LPDEVMODEA pDMA;
  5506. LPDEVMODEW pDMW;
  5507. int iResult;
  5508. CHAR szPrinterNameA[MAX_PRINTERNAME];
  5509. if (!pPI->bUseExtDeviceMode)
  5510. {
  5511. return;
  5512. }
  5513. //
  5514. // Allocate the array to hold whether or not a new devmode has been
  5515. // allocated for each of the printers.
  5516. //
  5517. // This is necessary because if the call to ExtDeviceMode fails, then
  5518. // nothing was allocated. The one that is currently in the pPrinters
  5519. // array is actually part of the big pPrinters array (from the call
  5520. // to GetPrinter - it wants one giant buffer).
  5521. //
  5522. if (pPI->cPrinters)
  5523. {
  5524. if (pPI->pAllocInfo)
  5525. {
  5526. GlobalFree(pPI->pAllocInfo);
  5527. }
  5528. pPI->pAllocInfo = (LPBOOL)GlobalAlloc( GPTR,
  5529. pPI->cPrinters * sizeof(BOOL) );
  5530. }
  5531. if (pPI->pAllocInfo)
  5532. {
  5533. //
  5534. // If we were called from a WOW app with a NULL devmode,
  5535. // then call ExtDeviceMode to get a default devmode.
  5536. //
  5537. for (ctr = 0; ctr < pPI->cPrinters; ctr++)
  5538. {
  5539. //
  5540. // Convert the printer name from Unicode to ANSI.
  5541. //
  5542. SHUnicodeToAnsi(pPI->pPrinters[ctr].pPrinterName, szPrinterNameA, ARRAYSIZE(szPrinterNameA));
  5543. //
  5544. // Call ExtDeviceMode with 0 flags to find out the
  5545. // size of the devmode structure we need.
  5546. //
  5547. iResult = ExtDeviceMode( hDlg,
  5548. NULL,
  5549. NULL,
  5550. szPrinterNameA,
  5551. NULL,
  5552. NULL,
  5553. NULL,
  5554. 0 );
  5555. if (iResult < 0)
  5556. {
  5557. continue;
  5558. }
  5559. //
  5560. // Allocate the space.
  5561. //
  5562. pDMA = GlobalAlloc(GPTR, iResult);
  5563. if (!pDMA)
  5564. {
  5565. continue;
  5566. }
  5567. //
  5568. // Call ExtDeviceMode to get the dummy devmode structure.
  5569. //
  5570. iResult = ExtDeviceMode( hDlg,
  5571. NULL,
  5572. pDMA,
  5573. szPrinterNameA,
  5574. NULL,
  5575. NULL,
  5576. NULL,
  5577. DM_COPY );
  5578. if (iResult < 0)
  5579. {
  5580. GlobalFree(pDMA);
  5581. continue;
  5582. }
  5583. //
  5584. // Call AllocateUnicodeDevMode to allocate and copy the unicode
  5585. // version of this ANSI dev mode.
  5586. //
  5587. pDMW = AllocateUnicodeDevMode(pDMA);
  5588. if (!pDMW)
  5589. {
  5590. GlobalFree(pDMA);
  5591. continue;
  5592. }
  5593. //
  5594. // Store the pointer to the new devmode in the old pointer
  5595. // position. We don't have to worry about freeing the
  5596. // current contents of pPrinter[ctr].pDevMode before sticking
  5597. // in the new pointer because in reality the pPrinter memory
  5598. // buffer is just one long allocation (the memory pDevmode
  5599. // points to is part of the pPrinters buffer). So, when the
  5600. // buffer is freed at the end, the old devmode will be freed
  5601. // with it.
  5602. //
  5603. pPI->pPrinters[ctr].pDevMode = pDMW;
  5604. pPI->pAllocInfo[ctr] = TRUE;
  5605. //
  5606. // Free the ANSI dev mode.
  5607. //
  5608. GlobalFree(pDMA);
  5609. }
  5610. }
  5611. }
  5612. #endif
  5613. ////////////////////////////////////////////////////////////////////////////
  5614. //
  5615. // PrintEnumAndSelect
  5616. //
  5617. // This routine enumerates the LOCAL and CONNECTED printers.
  5618. // It is called at initialization and when a new printer is
  5619. // added via the NETWORK... button.
  5620. //
  5621. // If the second parameter is set, the first parameter is overridden.
  5622. // When the second parameter is NULL, the first parameter is used.
  5623. // In this case, if the first parameter is greater than the total
  5624. // number of printers enumerated, then the last one in the list is
  5625. // selected.
  5626. //
  5627. ////////////////////////////////////////////////////////////////////////////
  5628. BOOL PrintEnumAndSelect(
  5629. HWND hDlg,
  5630. UINT Id,
  5631. PPRINTINFO pPI,
  5632. LPTSTR lpsPrinterToSelect,
  5633. BOOL bEnumPrinters)
  5634. {
  5635. HWND hCtl = ((hDlg && Id) ? GetDlgItem(hDlg, Id) : 0);
  5636. LPPRINTDLG pPD = pPI->pPD;
  5637. TCHAR szPrinter[MAX_PRINTERNAME];
  5638. DWORD cbNeeded;
  5639. DWORD cReturned;
  5640. DWORD ctr;
  5641. PPRINTER_INFO_2 pPrinters = NULL;
  5642. //
  5643. // Enumerate the printers, if necessary.
  5644. //
  5645. if (bEnumPrinters)
  5646. {
  5647. Print_Enumerate:
  5648. //
  5649. // Save lpsPrinterToSelect in a local before it gets freed.
  5650. //
  5651. if (lpsPrinterToSelect)
  5652. {
  5653. lstrcpyn(szPrinter, lpsPrinterToSelect, ARRAYSIZE(szPrinter));
  5654. lpsPrinterToSelect = szPrinter;
  5655. }
  5656. //
  5657. // Close and free any open printers.
  5658. //
  5659. PrintClosePrinters(pPI);
  5660. //
  5661. // Clear out the error code.
  5662. //
  5663. StoreExtendedError(CDERR_GENERALCODES);
  5664. //
  5665. // Enumerate the printers.
  5666. //
  5667. if (!EnumPrinters( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
  5668. NULL,
  5669. 2,
  5670. NULL,
  5671. 0,
  5672. &cbNeeded,
  5673. &cReturned ))
  5674. {
  5675. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  5676. {
  5677. if (pPrinters = GlobalAlloc(GPTR, cbNeeded))
  5678. {
  5679. if (EnumPrinters( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
  5680. NULL,
  5681. 2,
  5682. (LPBYTE)pPrinters,
  5683. cbNeeded,
  5684. &cbNeeded,
  5685. &cReturned ))
  5686. {
  5687. pPI->cPrinters = cReturned;
  5688. pPI->pPrinters = pPrinters;
  5689. pPI->Status |= PI_PRINTERS_ENUMERATED;
  5690. }
  5691. else
  5692. {
  5693. StoreExtendedError(PDERR_NODEFAULTPRN);
  5694. }
  5695. }
  5696. else
  5697. {
  5698. StoreExtendedError(CDERR_MEMALLOCFAILURE);
  5699. }
  5700. }
  5701. else
  5702. {
  5703. StoreExtendedError(PDERR_NODEFAULTPRN);
  5704. }
  5705. }
  5706. else
  5707. {
  5708. StoreExtendedError(PDERR_NODEFAULTPRN);
  5709. }
  5710. if (GetStoredExtendedError())
  5711. {
  5712. if (pPrinters)
  5713. {
  5714. GlobalFree(pPrinters);
  5715. }
  5716. return (FALSE);
  5717. }
  5718. //
  5719. // Make modifications for a WOW app.
  5720. //
  5721. #ifdef UNICODE
  5722. if (pPI->bUseExtDeviceMode)
  5723. {
  5724. PrintGetExtDeviceMode(hDlg, pPI);
  5725. }
  5726. #endif
  5727. //
  5728. // Try the selected printer.
  5729. //
  5730. if (lpsPrinterToSelect)
  5731. {
  5732. pPI->pCurPrinter = PrintSearchForPrinter(pPI, lpsPrinterToSelect);
  5733. }
  5734. //
  5735. // Open the current printer.
  5736. //
  5737. if (pPI->pCurPrinter)
  5738. {
  5739. //
  5740. // Open the current printer.
  5741. //
  5742. OpenPrinter(pPI->pCurPrinter->pPrinterName, &pPI->hCurPrinter, NULL);
  5743. }
  5744. else
  5745. {
  5746. //
  5747. // If there isn't a current printer, try the printers in
  5748. // the list until either one is found that can be opened or
  5749. // until there are no more printers in the list.
  5750. //
  5751. for (ctr = 0; ctr < pPI->cPrinters; ctr++)
  5752. {
  5753. pPI->pCurPrinter = &pPI->pPrinters[ctr];
  5754. //
  5755. // Try to open the printer.
  5756. //
  5757. if (OpenPrinter( pPI->pCurPrinter->pPrinterName,
  5758. &pPI->hCurPrinter,
  5759. NULL ))
  5760. {
  5761. break;
  5762. }
  5763. }
  5764. }
  5765. }
  5766. else
  5767. {
  5768. //
  5769. // If there isn't a current printer, then try to enumerate.
  5770. // This means something isn't setup properly.
  5771. //
  5772. if ((!pPI->pCurPrinter) || (!pPI->pPrinters))
  5773. {
  5774. goto Print_Enumerate;
  5775. }
  5776. }
  5777. if (hCtl)
  5778. {
  5779. //
  5780. // Reset the contents of the list box.
  5781. //
  5782. SendMessage(hCtl, CB_RESETCONTENT, 0, 0);
  5783. //
  5784. // Add all of the printer name strings to the list box.
  5785. //
  5786. for (ctr = 0; ctr < pPI->cPrinters; ctr++)
  5787. {
  5788. SendMessage( hCtl,
  5789. CB_ADDSTRING,
  5790. 0,
  5791. (LPARAM)pPI->pPrinters[ctr].pPrinterName );
  5792. }
  5793. //
  5794. // Set the current selection in the list box.
  5795. //
  5796. SendMessage( hCtl,
  5797. CB_SETCURSEL,
  5798. SendMessage( hCtl,
  5799. CB_FINDSTRINGEXACT,
  5800. (WPARAM)-1,
  5801. (LPARAM)pPI->pCurPrinter->pPrinterName ),
  5802. 0L );
  5803. }
  5804. return (TRUE);
  5805. }
  5806. ////////////////////////////////////////////////////////////////////////////
  5807. //
  5808. // PrintBuildDevNames
  5809. //
  5810. ////////////////////////////////////////////////////////////////////////////
  5811. VOID PrintBuildDevNames(
  5812. PPRINTINFO pPI)
  5813. {
  5814. LPPRINTDLG pPD = pPI->pPD;
  5815. LPTSTR pPrinterName = NULL;
  5816. LPTSTR pPortName = NULL;
  5817. TCHAR szBuffer[MAX_PATH];
  5818. TCHAR szPort[MAX_PATH];
  5819. LPTSTR pStr;
  5820. LPDEVNAMES pDN;
  5821. DWORD cbDevNames;
  5822. HANDLE hPrinter ;
  5823. PPRINTER_INFO_2 pPrinter = NULL;
  5824. //
  5825. // If this is called from PrintReturnDefault, there is no
  5826. // PrinterInfo (pPI->pCurPrinter) because the printers were not
  5827. // enumerated. So, build the DEVNAME from win.ini.
  5828. //
  5829. pStr = szBuffer;
  5830. if (!pPI->pCurPrinter)
  5831. {
  5832. //
  5833. // Get the default printer from the "Windows" section of win.ini.
  5834. // (eg. device=\\server\local,winspool,Ne00:)
  5835. //
  5836. if ( (pPD->Flags & PD_RETURNDEFAULT) &&
  5837. GetProfileString( szTextWindows,
  5838. szTextDevice,
  5839. szTextNull,
  5840. szBuffer,
  5841. MAX_PATH ) )
  5842. {
  5843. // Examples of szBuffer:
  5844. // "My Local Printer,winspool,LPT1:" or
  5845. // "\\server\local,winspool,Ne00:"
  5846. //
  5847. // Skip leading space (if any).
  5848. //
  5849. while (*pStr == CHAR_SPACE)
  5850. {
  5851. pStr++;
  5852. }
  5853. //
  5854. // First token is the printer name.
  5855. //
  5856. pPrinterName = pStr;
  5857. while (*pStr && *pStr != CHAR_COMMA)
  5858. {
  5859. pStr++;
  5860. }
  5861. //
  5862. // NULL terminate the printer name.
  5863. //
  5864. *pStr++ = CHAR_NULL;
  5865. // For Newer Apps return the port name from the PRINT_INFO_2 structure.
  5866. // For older apps return the short port name give in the win.ini
  5867. if (pPI->ProcessVersion >= 0x40000)
  5868. {
  5869. //Newer App
  5870. if (OpenPrinter(pPrinterName, &hPrinter, NULL))
  5871. {
  5872. if (pPrinter = PrintGetPrinterInfo2(hPrinter))
  5873. {
  5874. lstrcpy(szPort, pPrinter->pPortName);
  5875. pPortName = szPort;
  5876. GlobalFree(pPrinter);
  5877. }
  5878. ClosePrinter(hPrinter);
  5879. }
  5880. else
  5881. {
  5882. //Unable to Open Printer so return
  5883. return ;
  5884. }
  5885. }
  5886. else
  5887. {
  5888. //Old App
  5889. //
  5890. // Skip the driver name (second token).
  5891. //
  5892. while (*pStr && *pStr++ != CHAR_COMMA)
  5893. {
  5894. ;
  5895. }
  5896. //
  5897. // Skip leading space (if any).
  5898. //
  5899. while (*pStr == CHAR_SPACE)
  5900. {
  5901. pStr++;
  5902. }
  5903. //
  5904. // Third (and last) token is the port name.
  5905. //
  5906. pPortName = pStr;
  5907. }
  5908. }
  5909. else
  5910. {
  5911. return;
  5912. }
  5913. }
  5914. else
  5915. {
  5916. //
  5917. // Get the printer name from the PrinterInfo2 structure
  5918. // for the current printer.
  5919. //
  5920. pPrinterName = pPI->pCurPrinter->pPrinterName;
  5921. //
  5922. // Newer Apps:
  5923. // Get the port name from the PrinterInfo2 structure for the
  5924. // current printer. Want to use the PrinterInfo2 structure
  5925. // for newer apps so that we can support multiple ports for
  5926. // one printer.
  5927. //
  5928. // Older Apps:
  5929. // First try to get the port name from the "devices" section
  5930. // of win.ini. If that fails, then use the PrinterInfo2
  5931. // structure for the current printer.
  5932. //
  5933. // This needs to use the "devices" section first due to a bug
  5934. // in AutoCAD. AutoCAD only allows 13 characters for the port
  5935. // name and it does not check the length when it tries to copy
  5936. // it to its own buffer.
  5937. //
  5938. #ifdef WINNT
  5939. if ( (pPI->ProcessVersion >= 0x40000) ||
  5940. (!GetProfileString( szTextDevices,
  5941. pPrinterName,
  5942. szTextNull,
  5943. szBuffer,
  5944. MAX_PATH )) ||
  5945. (!(pPortName = StrChr(szBuffer, CHAR_COMMA))) ||
  5946. (!((++pPortName)[0])) )
  5947. #endif
  5948. {
  5949. //
  5950. // Get the port name from the PrinterInfo2 structure
  5951. // for the current printer.
  5952. //
  5953. pPortName = pPI->pCurPrinter->pPortName;
  5954. }
  5955. }
  5956. //
  5957. // Compute the size of the DevNames structure.
  5958. //
  5959. cbDevNames = lstrlen(szDriver) + 1 +
  5960. lstrlen(pPortName) + 1 +
  5961. lstrlen(pPrinterName) + 1 +
  5962. DN_PADDINGCHARS;
  5963. cbDevNames *= sizeof(TCHAR);
  5964. cbDevNames += sizeof(DEVNAMES);
  5965. //
  5966. // Allocate the new DevNames structure.
  5967. //
  5968. pDN = NULL;
  5969. if (pPD->hDevNames)
  5970. {
  5971. HANDLE handle;
  5972. handle = GlobalReAlloc(pPD->hDevNames, cbDevNames, GHND);
  5973. //Make sure the Realloc succeeded.
  5974. if (handle)
  5975. {
  5976. pPD->hDevNames = handle;
  5977. }
  5978. else
  5979. {
  5980. //Realloc didn't succeed. Free the old the memory
  5981. pPD->hDevNames = GlobalFree(pPD->hDevNames);
  5982. }
  5983. }
  5984. else
  5985. {
  5986. pPD->hDevNames = GlobalAlloc(GHND, cbDevNames);
  5987. }
  5988. //
  5989. // Fill in the DevNames structure with the appropriate information.
  5990. //
  5991. if ( (pPD->hDevNames) &&
  5992. (pDN = GlobalLock(pPD->hDevNames)) )
  5993. {
  5994. pDN->wDriverOffset = sizeof(DEVNAMES) / sizeof(TCHAR);
  5995. lstrcpy((LPTSTR)pDN + pDN->wDriverOffset, szDriver);
  5996. pDN->wDeviceOffset = pDN->wDriverOffset + lstrlen(szDriver) + 1;
  5997. lstrcpy((LPTSTR)pDN + pDN->wDeviceOffset, pPrinterName);
  5998. pDN->wOutputOffset = pDN->wDeviceOffset + lstrlen(pPrinterName) + 1;
  5999. lstrcpy((LPTSTR)pDN + pDN->wOutputOffset, pPortName);
  6000. if ( (pPD->Flags & PD_RETURNDEFAULT) ||
  6001. !lstrcmp(pPrinterName, pPI->szDefaultPrinter) )
  6002. {
  6003. pDN->wDefault = DN_DEFAULTPRN;
  6004. }
  6005. else
  6006. {
  6007. pDN->wDefault = 0;
  6008. }
  6009. GlobalUnlock(pPD->hDevNames);
  6010. }
  6011. }
  6012. ////////////////////////////////////////////////////////////////////////////
  6013. //
  6014. // PrintGetDevMode
  6015. //
  6016. // Create and/or fill DEVMODE structure.
  6017. //
  6018. ////////////////////////////////////////////////////////////////////////////
  6019. HANDLE PrintGetDevMode(
  6020. HWND hDlg,
  6021. HANDLE hPrinter,
  6022. LPTSTR lpsDeviceName,
  6023. HANDLE hDevMode)
  6024. {
  6025. LONG cbNeeded;
  6026. LPDEVMODE pDM;
  6027. cbNeeded = DocumentProperties( hDlg,
  6028. hPrinter,
  6029. lpsDeviceName,
  6030. (PDEVMODE)NULL,
  6031. (PDEVMODE)NULL,
  6032. 0 );
  6033. if (cbNeeded > 0)
  6034. {
  6035. if (hDevMode)
  6036. {
  6037. HANDLE h = GlobalReAlloc(hDevMode, cbNeeded, GHND);
  6038. //Make sure realloc succeeded.
  6039. if (h)
  6040. {
  6041. hDevMode = h;
  6042. }
  6043. else
  6044. {
  6045. //Realloc didn't succeed. Free the memory occupied
  6046. GlobalFree(hDevMode);
  6047. hDevMode = NULL;
  6048. }
  6049. }
  6050. else
  6051. {
  6052. hDevMode = GlobalAlloc(GHND, cbNeeded);
  6053. }
  6054. if (hDevMode && (pDM = GlobalLock(hDevMode)))
  6055. {
  6056. if (DocumentProperties( hDlg,
  6057. hPrinter,
  6058. lpsDeviceName,
  6059. pDM,
  6060. NULL,
  6061. DM_COPY ) != IDOK)
  6062. {
  6063. StoreExtendedError(PDERR_NODEFAULTPRN);
  6064. GlobalUnlock(hDevMode);
  6065. GlobalFree(hDevMode);
  6066. return (NULL);
  6067. }
  6068. GlobalUnlock(hDevMode);
  6069. }
  6070. else
  6071. {
  6072. if (hDevMode)
  6073. {
  6074. StoreExtendedError(CDERR_MEMLOCKFAILURE);
  6075. GlobalFree(hDevMode);
  6076. }
  6077. else
  6078. {
  6079. StoreExtendedError(CDERR_MEMALLOCFAILURE);
  6080. }
  6081. return (NULL);
  6082. }
  6083. }
  6084. else
  6085. {
  6086. DWORD dwErrCode;
  6087. hDevMode = NULL;
  6088. dwErrCode = GetLastError();
  6089. if ( (dwErrCode == ERROR_UNKNOWN_PRINTER_DRIVER) ||
  6090. (dwErrCode == ERROR_MOD_NOT_FOUND) )
  6091. {
  6092. if (hDlg)
  6093. {
  6094. PrintEditError(hDlg, 0, iszUnknownDriver, lpsDeviceName);
  6095. }
  6096. }
  6097. }
  6098. return (hDevMode);
  6099. }
  6100. ////////////////////////////////////////////////////////////////////////////
  6101. //
  6102. // PrintReturnICDC
  6103. //
  6104. // Retrieve either the hDC or the hIC if either flag is set.
  6105. // Assumes the PD_PRINTOFILE flag is appropriately set.
  6106. //
  6107. ////////////////////////////////////////////////////////////////////////////
  6108. VOID PrintReturnICDC(
  6109. LPPRINTDLG pPD,
  6110. LPDEVNAMES pDN,
  6111. LPDEVMODE pDM)
  6112. {
  6113. if (pPD->Flags & PD_PRINTTOFILE)
  6114. {
  6115. lstrcpy((LPTSTR)pDN + pDN->wOutputOffset, szFilePort);
  6116. }
  6117. #ifdef UNICODE
  6118. //
  6119. // The dmCollate field wasn't part of the Win3.1 DevMode struct. The way
  6120. // 16-bit apps achieved collation was by checking the PD_COLLATE flag in
  6121. // the PrintDlg struct. The app would then figure out the page printing
  6122. // order to achieve collation. So what we're doing here is making sure
  6123. // that PD_COLLATE is the only collation mechanism for 16-bit apps. If we
  6124. // let DM_COLLATE get into the DC we'd end up with the driver trying to
  6125. // collate a job that the app is already trying to collate!
  6126. //
  6127. if ((pPD->Flags & CD_WOWAPP) && pDM)
  6128. {
  6129. if (pDM->dmFields & DM_COLLATE)
  6130. {
  6131. pPD->Flags |= PD_COLLATE;
  6132. }
  6133. // these should always be off for WOW apps
  6134. pDM->dmCollate = DMCOLLATE_FALSE;
  6135. pDM->dmFields &= ~DM_COLLATE;
  6136. }
  6137. #endif
  6138. switch (pPD->Flags & (PD_RETURNDC | PD_RETURNIC))
  6139. {
  6140. case ( PD_RETURNIC ) :
  6141. {
  6142. pPD->hDC = CreateIC( (LPTSTR)pDN + pDN->wDriverOffset,
  6143. (LPTSTR)pDN + pDN->wDeviceOffset,
  6144. (LPTSTR)pDN + pDN->wOutputOffset,
  6145. pDM);
  6146. if (pPD->hDC)
  6147. {
  6148. break;
  6149. }
  6150. // else fall thru...
  6151. }
  6152. case ( PD_RETURNDC ) :
  6153. case ( PD_RETURNDC | PD_RETURNIC ) :
  6154. {
  6155. //
  6156. // PD_RETURNDC has priority if they are both set.
  6157. //
  6158. pPD->hDC = CreateDC( (LPTSTR)pDN + pDN->wDriverOffset,
  6159. (LPTSTR)pDN + pDN->wDeviceOffset,
  6160. (LPTSTR)pDN + pDN->wOutputOffset,
  6161. pDM );
  6162. break;
  6163. }
  6164. }
  6165. }
  6166. ////////////////////////////////////////////////////////////////////////////
  6167. //
  6168. // PrintMeasureItem
  6169. //
  6170. ////////////////////////////////////////////////////////////////////////////
  6171. VOID PrintMeasureItem(
  6172. HANDLE hDlg,
  6173. LPMEASUREITEMSTRUCT mis)
  6174. {
  6175. HDC hDC;
  6176. TEXTMETRIC TM;
  6177. HANDLE hFont;
  6178. if (hDC = GetDC(hDlg))
  6179. {
  6180. hFont = (HANDLE)SendMessage(hDlg, WM_GETFONT, 0, 0L);
  6181. if (!hFont)
  6182. {
  6183. hFont = GetStockObject(SYSTEM_FONT);
  6184. }
  6185. hFont = SelectObject(hDC, hFont);
  6186. GetTextMetrics(hDC, &TM);
  6187. mis->itemHeight = (WORD)TM.tmHeight;
  6188. SelectObject(hDC, hFont);
  6189. ReleaseDC(hDlg, hDC);
  6190. }
  6191. }
  6192. ////////////////////////////////////////////////////////////////////////////
  6193. //
  6194. // PrintInitOrientation
  6195. //
  6196. // Enable/Disable Paper Orientation controls
  6197. //
  6198. // NOTE: If the driver doesn't support orientation AND is smart
  6199. // enough to tell us about it, disable the appropriate dialog items.
  6200. // "Smart enough" means the driver must support DC_ORIENTATION in its
  6201. // DeviceCapabilities routine. This was introduced for 3.1, hence the
  6202. // version test. NotBadDriver() may need to be incorporated if a
  6203. // problem driver is found in testing.
  6204. //
  6205. ////////////////////////////////////////////////////////////////////////////
  6206. VOID PrintInitOrientation(
  6207. HWND hDlg,
  6208. PPRINTINFO pPI,
  6209. LPDEVMODE pDM)
  6210. {
  6211. BOOL bEnable = TRUE;
  6212. HWND hCtl;
  6213. HDC hDC;
  6214. int iHeight;
  6215. PPRINTER_INFO_2 pPrinter = pPI->pCurPrinter;
  6216. if (!pPrinter)
  6217. {
  6218. return;
  6219. }
  6220. if (pDM->dmSpecVersion >= 0x030A)
  6221. {
  6222. pPI->dwRotation = DeviceCapabilities( pPrinter->pPrinterName,
  6223. pPrinter->pPortName,
  6224. DC_ORIENTATION,
  6225. NULL,
  6226. pDM );
  6227. switch (pPI->dwRotation)
  6228. {
  6229. case ( ROTATE_LEFT ) :
  6230. case ( ROTATE_RIGHT ) :
  6231. {
  6232. bEnable = TRUE;
  6233. break;
  6234. }
  6235. default :
  6236. {
  6237. pPI->dwRotation = 0;
  6238. bEnable = FALSE;
  6239. pDM->dmOrientation = DMORIENT_PORTRAIT;
  6240. CheckRadioButton( hDlg,
  6241. ID_SETUP_R_PORTRAIT,
  6242. ID_SETUP_R_LANDSCAPE,
  6243. ID_SETUP_R_PORTRAIT );
  6244. break;
  6245. }
  6246. }
  6247. }
  6248. if ( (pDM->dmOrientation != DMORIENT_PORTRAIT) &&
  6249. (pDM->dmOrientation != DMORIENT_LANDSCAPE) )
  6250. {
  6251. pDM->dmOrientation = DMORIENT_PORTRAIT;
  6252. }
  6253. if (hCtl = GetDlgItem(hDlg, ID_SETUP_R_LANDSCAPE))
  6254. {
  6255. //
  6256. // Landscape
  6257. //
  6258. if ( !( (pPI->pPSD) &&
  6259. (pPI->pPSD->Flags & PSD_DISABLEORIENTATION) ) )
  6260. {
  6261. EnableWindow(hCtl, bEnable);
  6262. }
  6263. }
  6264. if (hCtl = GetDlgItem(hDlg, ID_SETUP_I_ORIENTATION))
  6265. {
  6266. //
  6267. // Orientation of icon.
  6268. //
  6269. SetWindowLong( hCtl,
  6270. GWL_STYLE,
  6271. GetWindowLong(hCtl, GWL_STYLE) | SS_CENTERIMAGE );
  6272. }
  6273. if ( (!pPI->RtSampleXYWH.left) &&
  6274. (hCtl = GetDlgItem(hDlg, ID_SETUP_W_SAMPLE)) )
  6275. {
  6276. GetWindowRect(hCtl, (LPRECT)&pPI->RtSampleXYWH);
  6277. ScreenToClient(hDlg, (LPPOINT)&pPI->RtSampleXYWH.left);
  6278. ScreenToClient(hDlg, (LPPOINT)&pPI->RtSampleXYWH.right);
  6279. iHeight = pPI->RtSampleXYWH.bottom - pPI->RtSampleXYWH.top;
  6280. pPI->RtSampleXYWH.bottom = iHeight;
  6281. if (hDC = GetDC(0))
  6282. {
  6283. iHeight = iHeight * GetDeviceCaps(hDC, LOGPIXELSX) /
  6284. GetDeviceCaps(hDC, LOGPIXELSY);
  6285. ReleaseDC(0, hDC);
  6286. }
  6287. pPI->RtSampleXYWH.left =
  6288. (pPI->RtSampleXYWH.left + pPI->RtSampleXYWH.right - iHeight) / 2;
  6289. pPI->RtSampleXYWH.right = iHeight;
  6290. }
  6291. }
  6292. ////////////////////////////////////////////////////////////////////////////
  6293. //
  6294. // PrintSetOrientation
  6295. //
  6296. // Switch icon, check button, for Portrait or LandScape printing mode.
  6297. //
  6298. ////////////////////////////////////////////////////////////////////////////
  6299. VOID PrintSetOrientation(
  6300. HWND hDlg,
  6301. PPRINTINFO pPI,
  6302. LPDEVMODE pDM,
  6303. UINT uiOldId,
  6304. UINT uiNewId)
  6305. {
  6306. BOOL bPortrait;
  6307. HWND hIcn;
  6308. bPortrait = (uiNewId == ID_SETUP_R_PORTRAIT);
  6309. pDM->dmOrientation = ( bPortrait
  6310. ? DMORIENT_PORTRAIT
  6311. : DMORIENT_LANDSCAPE );
  6312. CheckRadioButton(hDlg, ID_SETUP_R_PORTRAIT, ID_SETUP_R_LANDSCAPE, uiNewId);
  6313. if (hIcn = GetDlgItem(hDlg, ID_SETUP_I_ORIENTATION))
  6314. {
  6315. ShowWindow(hIcn, SW_HIDE);
  6316. SendMessage( hIcn,
  6317. STM_SETICON,
  6318. bPortrait ? (LONG_PTR)hIconPortrait : (LONG_PTR)hIconLandscape,
  6319. 0L );
  6320. ShowWindow(hIcn, SW_SHOW);
  6321. }
  6322. //
  6323. // Update the page setup dialog, if necessary.
  6324. //
  6325. if (pPI->pPSD)
  6326. {
  6327. PrintUpdatePageSetup(hDlg, pPI, pDM, uiOldId, uiNewId);
  6328. }
  6329. }
  6330. ////////////////////////////////////////////////////////////////////////////
  6331. //
  6332. // PrintUpdatePageSetup
  6333. //
  6334. // Update the page setup information.
  6335. //
  6336. ////////////////////////////////////////////////////////////////////////////
  6337. VOID PrintUpdatePageSetup(
  6338. HWND hDlg,
  6339. PPRINTINFO pPI,
  6340. LPDEVMODE pDM,
  6341. UINT uiOldId,
  6342. UINT uiNewId)
  6343. {
  6344. BOOL bPortrait = (uiNewId == ID_SETUP_R_PORTRAIT);
  6345. LPPAGESETUPDLG pPSD = pPI->pPSD;
  6346. LPPRINTDLG pPD = pPI->pPD;
  6347. HWND hWndSample;
  6348. HWND hWndShadowRight;
  6349. HWND hWndShadowBottom;
  6350. HWND hWndSize;
  6351. LONG lTemp;
  6352. if (!pPSD)
  6353. {
  6354. return;
  6355. }
  6356. if (uiOldId != uiNewId)
  6357. {
  6358. RECT aRtMinMargin = pPSD->rtMinMargin;
  6359. RECT aRtMargin = pPSD->rtMargin;
  6360. HWND hWndLeft = GetDlgItem(hDlg, ID_SETUP_E_LEFT);
  6361. HWND hWndTop = GetDlgItem(hDlg, ID_SETUP_E_TOP);
  6362. HWND hWndRight = GetDlgItem(hDlg, ID_SETUP_E_RIGHT);
  6363. HWND hWndBottom = GetDlgItem(hDlg, ID_SETUP_E_BOTTOM);
  6364. TCHAR szLeft [8];
  6365. TCHAR szTop [8];
  6366. TCHAR szRight [8];
  6367. TCHAR szBottom[8];
  6368. GetWindowText(hWndLeft, szLeft, 8);
  6369. GetWindowText(hWndTop, szTop, 8);
  6370. GetWindowText(hWndRight, szRight, 8);
  6371. GetWindowText(hWndBottom, szBottom, 8);
  6372. switch (uiNewId + pPI->dwRotation)
  6373. {
  6374. case ( ID_SETUP_R_PORTRAIT + ROTATE_RIGHT ) : // HP PCL
  6375. case ( ID_SETUP_R_LANDSCAPE + ROTATE_LEFT ) : // dot-matrix
  6376. {
  6377. pPSD->rtMinMargin.left = aRtMinMargin.top;
  6378. pPSD->rtMinMargin.top = aRtMinMargin.right;
  6379. pPSD->rtMinMargin.right = aRtMinMargin.bottom;
  6380. pPSD->rtMinMargin.bottom = aRtMinMargin.left;
  6381. pPSD->rtMargin.left = aRtMargin.top;
  6382. pPSD->rtMargin.top = aRtMargin.right;
  6383. pPSD->rtMargin.right = aRtMargin.bottom;
  6384. pPSD->rtMargin.bottom = aRtMargin.left;
  6385. SetWindowText(hWndLeft, szTop);
  6386. SetWindowText(hWndRight, szBottom);
  6387. SetWindowText(hWndTop, szRight);
  6388. SetWindowText(hWndBottom, szLeft);
  6389. break;
  6390. }
  6391. case ( ID_SETUP_R_PORTRAIT + ROTATE_LEFT ) : // dot-matrix
  6392. case ( ID_SETUP_R_LANDSCAPE + ROTATE_RIGHT ) : // HP PCL
  6393. {
  6394. pPSD->rtMinMargin.left = aRtMinMargin.bottom;
  6395. pPSD->rtMinMargin.top = aRtMinMargin.left;
  6396. pPSD->rtMinMargin.right = aRtMinMargin.top;
  6397. pPSD->rtMinMargin.bottom = aRtMinMargin.right;
  6398. pPSD->rtMargin.left = aRtMargin.bottom;
  6399. pPSD->rtMargin.top = aRtMargin.left;
  6400. pPSD->rtMargin.right = aRtMargin.top;
  6401. pPSD->rtMargin.bottom = aRtMargin.right;
  6402. SetWindowText(hWndLeft, szBottom);
  6403. SetWindowText(hWndRight, szTop);
  6404. SetWindowText(hWndTop, szLeft);
  6405. SetWindowText(hWndBottom, szRight);
  6406. break;
  6407. }
  6408. }
  6409. }
  6410. pPI->uiOrientationID = uiNewId;
  6411. //
  6412. // Update ptPaperSize.
  6413. //
  6414. pPI->PtPaperSizeMMs.x = 0;
  6415. pPI->PtPaperSizeMMs.y = 0;
  6416. pPD->Flags &= ~PI_WPAPER_ENVELOPE;
  6417. if ((hWndSize = GetDlgItem(hDlg, ID_SETUP_C_SIZE)) && (pPI->pCurPrinter))
  6418. {
  6419. PPRINTER_INFO_2 pPrinter = pPI->pCurPrinter;
  6420. DWORD dwNumber;
  6421. LPWORD lpPapers;
  6422. LPPOINT lpPaperSize;
  6423. int nInd;
  6424. DWORD i;
  6425. dwNumber = DeviceCapabilities( pPrinter->pPrinterName,
  6426. pPrinter->pPortName,
  6427. DC_PAPERS,
  6428. NULL,
  6429. pDM );
  6430. if ( dwNumber &&
  6431. (dwNumber != (DWORD)-1) &&
  6432. (lpPapers = LocalAlloc( LPTR,
  6433. dwNumber *
  6434. (sizeof(WORD) + sizeof(POINT)) * 2 )) )
  6435. {
  6436. lpPaperSize = (LPPOINT)(lpPapers + dwNumber * 2);
  6437. DeviceCapabilities( pPrinter->pPrinterName,
  6438. pPrinter->pPortName,
  6439. DC_PAPERS,
  6440. (LPTSTR)lpPapers,
  6441. pDM );
  6442. DeviceCapabilities( pPrinter->pPrinterName,
  6443. pPrinter->pPortName,
  6444. DC_PAPERSIZE,
  6445. (LPTSTR)lpPaperSize,
  6446. pDM );
  6447. if ((nInd = (int) SendMessage(hWndSize, CB_GETCURSEL, 0, 0)) != CB_ERR)
  6448. {
  6449. pPI->wPaper = (WORD)SendMessage( hWndSize,
  6450. CB_GETITEMDATA,
  6451. nInd,
  6452. 0 );
  6453. pDM->dmPaperSize = pPI->wPaper;
  6454. }
  6455. else
  6456. {
  6457. pPI->wPaper = pDM->dmPaperSize;
  6458. }
  6459. #ifndef WINNT
  6460. if (pDM->dmSpecVersion >= 0x0400)
  6461. #endif
  6462. {
  6463. SendMessage( hWndSize,
  6464. CB_GETLBTEXT,
  6465. nInd,
  6466. (LPARAM)pDM->dmFormName );
  6467. }
  6468. switch (pPI->wPaper)
  6469. {
  6470. case ( DMPAPER_ENV_9 ) :
  6471. case ( DMPAPER_ENV_10 ) :
  6472. case ( DMPAPER_ENV_11 ) :
  6473. case ( DMPAPER_ENV_12 ) :
  6474. case ( DMPAPER_ENV_14 ) :
  6475. case ( DMPAPER_ENV_DL ) :
  6476. case ( DMPAPER_ENV_C5 ) :
  6477. case ( DMPAPER_ENV_C3 ) :
  6478. case ( DMPAPER_ENV_C4 ) :
  6479. case ( DMPAPER_ENV_C6 ) :
  6480. case ( DMPAPER_ENV_C65 ) :
  6481. case ( DMPAPER_ENV_B4 ) :
  6482. case ( DMPAPER_ENV_B5 ) :
  6483. case ( DMPAPER_ENV_B6 ) :
  6484. case ( DMPAPER_ENV_ITALY ) :
  6485. case ( DMPAPER_ENV_MONARCH ) :
  6486. case ( DMPAPER_ENV_PERSONAL ) :
  6487. case ( DMPAPER_ENV_INVITE ) :
  6488. case ( DMPAPER_JENV_KAKU2 ) :
  6489. case ( DMPAPER_JENV_KAKU3 ) :
  6490. case ( DMPAPER_JENV_CHOU3 ) :
  6491. case ( DMPAPER_JENV_CHOU4 ) :
  6492. case ( DMPAPER_JENV_KAKU2_ROTATED ) :
  6493. case ( DMPAPER_JENV_KAKU3_ROTATED ) :
  6494. case ( DMPAPER_JENV_CHOU3_ROTATED ) :
  6495. case ( DMPAPER_JENV_CHOU4_ROTATED ) :
  6496. case ( DMPAPER_JENV_YOU4 ) :
  6497. case ( DMPAPER_JENV_YOU4_ROTATED ) :
  6498. case ( DMPAPER_PENV_1 ) :
  6499. case ( DMPAPER_PENV_2 ) :
  6500. case ( DMPAPER_PENV_3 ) :
  6501. case ( DMPAPER_PENV_4 ) :
  6502. case ( DMPAPER_PENV_5 ) :
  6503. case ( DMPAPER_PENV_6 ) :
  6504. case ( DMPAPER_PENV_7 ) :
  6505. case ( DMPAPER_PENV_8 ) :
  6506. case ( DMPAPER_PENV_9 ) :
  6507. case ( DMPAPER_PENV_10 ) :
  6508. case ( DMPAPER_PENV_1_ROTATED ) :
  6509. case ( DMPAPER_PENV_2_ROTATED ) :
  6510. case ( DMPAPER_PENV_3_ROTATED ) :
  6511. case ( DMPAPER_PENV_4_ROTATED ) :
  6512. case ( DMPAPER_PENV_5_ROTATED ) :
  6513. case ( DMPAPER_PENV_6_ROTATED ) :
  6514. case ( DMPAPER_PENV_7_ROTATED ) :
  6515. case ( DMPAPER_PENV_8_ROTATED ) :
  6516. case ( DMPAPER_PENV_9_ROTATED ) :
  6517. case ( DMPAPER_PENV_10_ROTATED ) :
  6518. {
  6519. pPD->Flags |= PI_WPAPER_ENVELOPE;
  6520. break;
  6521. }
  6522. }
  6523. for (i = 0; i < dwNumber; i++)
  6524. {
  6525. if (lpPapers[i] == pPI->wPaper)
  6526. {
  6527. //
  6528. // In tenths of MMs.
  6529. //
  6530. *(LPPOINT)&pPI->PtPaperSizeMMs = lpPaperSize[i];
  6531. break;
  6532. }
  6533. }
  6534. LocalFree(lpPapers);
  6535. }
  6536. }
  6537. //
  6538. // If the paper size could not be found, use something reasonable
  6539. // (eg. letter).
  6540. //
  6541. if (!pPI->PtPaperSizeMMs.x)
  6542. {
  6543. pPI->PtPaperSizeMMs.x = 85 * MMS_PER_INCH / 10;
  6544. }
  6545. if (!pPI->PtPaperSizeMMs.y)
  6546. {
  6547. pPI->PtPaperSizeMMs.y = 11 * MMS_PER_INCH;
  6548. }
  6549. //
  6550. // Rotate envelopes as needed.
  6551. //
  6552. if ( (pPD->Flags & PI_WPAPER_ENVELOPE) &&
  6553. (!pPI->dwRotation) &&
  6554. (pPI->PtPaperSizeMMs.x < pPI->PtPaperSizeMMs.y) )
  6555. {
  6556. lTemp = pPI->PtPaperSizeMMs.x;
  6557. pPI->PtPaperSizeMMs.x = pPI->PtPaperSizeMMs.y;
  6558. pPI->PtPaperSizeMMs.y = lTemp;
  6559. }
  6560. //
  6561. // Maintain everything in accordance with the orientation
  6562. // so that apps have to do as little work as possible.
  6563. //
  6564. if (!bPortrait)
  6565. {
  6566. lTemp = pPI->PtPaperSizeMMs.x;
  6567. pPI->PtPaperSizeMMs.x = pPI->PtPaperSizeMMs.y;
  6568. pPI->PtPaperSizeMMs.y = lTemp;
  6569. }
  6570. //
  6571. // Set up return ptPaperSize value.
  6572. //
  6573. if (pPSD->Flags & PSD_INTHOUSANDTHSOFINCHES)
  6574. {
  6575. pPSD->ptPaperSize.x = pPI->PtPaperSizeMMs.x * 1000 / MMS_PER_INCH;
  6576. pPSD->ptPaperSize.y = pPI->PtPaperSizeMMs.y * 1000 / MMS_PER_INCH;
  6577. }
  6578. else // PSD_INHUNDREDTHSOFMILLIMETERS
  6579. {
  6580. pPSD->ptPaperSize.x = pPI->PtPaperSizeMMs.x * 10;
  6581. pPSD->ptPaperSize.y = pPI->PtPaperSizeMMs.y * 10;
  6582. }
  6583. //
  6584. // Update RtMinMarginMMs and rtMinMargin for new papersize/orientation.
  6585. //
  6586. PrintSetMinMargins(hDlg, pPI, pDM);
  6587. //
  6588. // Don't let margins overlap (page might have shrunk).
  6589. //
  6590. if (pPSD->rtMargin.left + pPSD->rtMargin.right > pPSD->ptPaperSize.x)
  6591. {
  6592. lTemp = (pPD->Flags & PSD_INTHOUSANDTHSOFINCHES) ? 1000 : MMS_PER_INCH;
  6593. pPSD->rtMargin.left = (pPSD->ptPaperSize.x - lTemp) / 2;
  6594. pPSD->rtMargin.right = (pPSD->ptPaperSize.x - lTemp) / 2;
  6595. }
  6596. if (pPSD->rtMargin.top + pPSD->rtMargin.bottom > pPSD->ptPaperSize.y)
  6597. {
  6598. lTemp = (pPD->Flags & PSD_INTHOUSANDTHSOFINCHES) ? 1000 : MMS_PER_INCH;
  6599. pPSD->rtMargin.top = (pPSD->ptPaperSize.y - lTemp) / 2;
  6600. pPSD->rtMargin.bottom = (pPSD->ptPaperSize.y - lTemp) / 2;
  6601. }
  6602. //
  6603. // There are new minimal margins, so adjust rtMargin
  6604. // (min margins might have grown).
  6605. //
  6606. if (pPSD->rtMargin.left < pPSD->rtMinMargin.left)
  6607. pPSD->rtMargin.left = pPSD->rtMinMargin.left;
  6608. if (pPSD->rtMargin.top < pPSD->rtMinMargin.top)
  6609. pPSD->rtMargin.top = pPSD->rtMinMargin.top;
  6610. if (pPSD->rtMargin.right < pPSD->rtMinMargin.right)
  6611. pPSD->rtMargin.right = pPSD->rtMinMargin.right;
  6612. if (pPSD->rtMargin.bottom < pPSD->rtMinMargin.bottom)
  6613. pPSD->rtMargin.bottom = pPSD->rtMinMargin.bottom;
  6614. //
  6615. // The margins were adjusted, so update the ui.
  6616. //
  6617. PrintSetMargin(hDlg, pPI, ID_SETUP_E_LEFT, pPSD->rtMargin.left);
  6618. PrintSetMargin(hDlg, pPI, ID_SETUP_E_TOP, pPSD->rtMargin.top);
  6619. PrintSetMargin(hDlg, pPI, ID_SETUP_E_RIGHT, pPSD->rtMargin.right);
  6620. PrintSetMargin(hDlg, pPI, ID_SETUP_E_BOTTOM, pPSD->rtMargin.bottom);
  6621. //
  6622. // Update the sample window size & shadow.
  6623. //
  6624. if ( (hWndSample = GetDlgItem(hDlg, ID_SETUP_W_SAMPLE)) &&
  6625. (hWndShadowRight = GetDlgItem(hDlg, ID_SETUP_W_SHADOWRIGHT)) &&
  6626. (hWndShadowBottom = GetDlgItem(hDlg, ID_SETUP_W_SHADOWBOTTOM)) )
  6627. {
  6628. int iWidth = pPI->PtPaperSizeMMs.x;
  6629. int iLength = pPI->PtPaperSizeMMs.y;
  6630. int iExtent;
  6631. RECT aRtSampleXYWH = pPI->RtSampleXYWH;
  6632. int iX = aRtSampleXYWH.right / 16;
  6633. int iY = aRtSampleXYWH.bottom / 16;
  6634. if (iWidth > iLength)
  6635. {
  6636. iExtent = aRtSampleXYWH.bottom * iLength / iWidth;
  6637. aRtSampleXYWH.top += (aRtSampleXYWH.bottom - iExtent) / 2;
  6638. aRtSampleXYWH.bottom = iExtent;
  6639. }
  6640. else
  6641. {
  6642. iExtent = aRtSampleXYWH.right * iWidth / iLength;
  6643. aRtSampleXYWH.left += (aRtSampleXYWH.right - iExtent) / 2;
  6644. aRtSampleXYWH.right = iExtent;
  6645. }
  6646. SetWindowPos( hWndSample,
  6647. 0,
  6648. aRtSampleXYWH.left,
  6649. aRtSampleXYWH.top,
  6650. aRtSampleXYWH.right,
  6651. aRtSampleXYWH.bottom,
  6652. SWP_NOZORDER );
  6653. SetWindowPos( hWndShadowRight,
  6654. 0,
  6655. aRtSampleXYWH.left + aRtSampleXYWH.right,
  6656. aRtSampleXYWH.top + iY,
  6657. iX,
  6658. aRtSampleXYWH.bottom,
  6659. SWP_NOZORDER );
  6660. SetWindowPos( hWndShadowBottom,
  6661. 0,
  6662. aRtSampleXYWH.left + iX,
  6663. aRtSampleXYWH.top + aRtSampleXYWH.bottom,
  6664. aRtSampleXYWH.right,
  6665. iY,
  6666. SWP_NOZORDER );
  6667. InvalidateRect(hWndSample, NULL, TRUE);
  6668. UpdateWindow(hDlg);
  6669. UpdateWindow(hWndSample);
  6670. UpdateWindow(hWndShadowRight);
  6671. UpdateWindow(hWndShadowBottom);
  6672. }
  6673. }
  6674. ////////////////////////////////////////////////////////////////////////////
  6675. //
  6676. // PrintInitDuplex
  6677. //
  6678. // Enable/Disable Paper Duplexing controls.
  6679. //
  6680. // Returns TRUE iff buttons used to be disabled, now enabled.
  6681. // Returns FALSE otherwise.
  6682. //
  6683. ////////////////////////////////////////////////////////////////////////////
  6684. VOID PrintInitDuplex(
  6685. HWND hDlg,
  6686. LPDEVMODE pDM)
  6687. {
  6688. BOOL bEnable;
  6689. HWND hCtl;
  6690. bEnable = (pDM->dmFields & DM_DUPLEX);
  6691. if (hCtl = GetDlgItem(hDlg, ID_SETUP_G_DUPLEX))
  6692. {
  6693. EnableWindow(hCtl, bEnable);
  6694. }
  6695. if (hCtl = GetDlgItem(hDlg, ID_SETUP_R_NONE))
  6696. {
  6697. EnableWindow(hCtl, bEnable);
  6698. }
  6699. if (hCtl = GetDlgItem(hDlg, ID_SETUP_R_LONG))
  6700. {
  6701. EnableWindow(hCtl, bEnable);
  6702. }
  6703. if (hCtl = GetDlgItem(hDlg, ID_SETUP_R_SHORT))
  6704. {
  6705. EnableWindow(hCtl, bEnable);
  6706. }
  6707. if (hCtl = GetDlgItem(hDlg, ID_SETUP_I_DUPLEX))
  6708. {
  6709. SetWindowLong( hCtl,
  6710. GWL_STYLE,
  6711. GetWindowLong(hCtl, GWL_STYLE) | SS_CENTERIMAGE );
  6712. if (!bEnable)
  6713. {
  6714. ShowWindow(hCtl, SW_HIDE);
  6715. SendMessage(hCtl, STM_SETICON, (LONG_PTR)hIconPDuplexNone, 0L);
  6716. ShowWindow(hCtl, SW_SHOW);
  6717. }
  6718. }
  6719. }
  6720. ////////////////////////////////////////////////////////////////////////////
  6721. //
  6722. // PrintSetDuplex
  6723. //
  6724. // This routine will operate on pDocDetails->pDMInput PSDEVMODE structure,
  6725. // making sure that is a structure we know about and can handle.
  6726. //
  6727. // If the pd doesn't have DM_DUPLEX caps then just display the appropriate
  6728. // paper icon for DMDUP_SIMPLEX (case where nRad = ID_SETUP_R_NONE).
  6729. //
  6730. // If nRad = 0, update icon but don't change radio button.
  6731. //
  6732. ////////////////////////////////////////////////////////////////////////////
  6733. VOID PrintSetDuplex(
  6734. HWND hDlg,
  6735. LPDEVMODE pDM,
  6736. UINT nRad)
  6737. {
  6738. BOOL bPortrait;
  6739. HANDLE hDuplexIcon;
  6740. HWND hCtl;
  6741. bPortrait = (pDM->dmOrientation == DMORIENT_PORTRAIT);
  6742. if (!(pDM->dmFields & DM_DUPLEX))
  6743. {
  6744. nRad = ID_SETUP_R_NONE;
  6745. }
  6746. //
  6747. // Boundary checking - default to ID_SETUP_R_NONE.
  6748. //
  6749. if (GetDlgItem(hDlg, ID_SETUP_R_NONE))
  6750. {
  6751. if ((nRad < ID_SETUP_R_NONE) || (nRad > ID_SETUP_R_SHORT))
  6752. {
  6753. if (IsDlgButtonChecked(hDlg, ID_SETUP_R_SHORT))
  6754. {
  6755. nRad = ID_SETUP_R_SHORT;
  6756. }
  6757. else if (IsDlgButtonChecked(hDlg, ID_SETUP_R_LONG))
  6758. {
  6759. nRad = ID_SETUP_R_LONG;
  6760. }
  6761. else
  6762. {
  6763. nRad = ID_SETUP_R_NONE;
  6764. }
  6765. }
  6766. else
  6767. {
  6768. CheckRadioButton(hDlg, ID_SETUP_R_NONE, ID_SETUP_R_SHORT, nRad);
  6769. }
  6770. }
  6771. if (hCtl = GetDlgItem(hDlg, ID_SETUP_I_DUPLEX))
  6772. {
  6773. switch (nRad)
  6774. {
  6775. case ( ID_SETUP_R_LONG ) : // Long Side - 2 sided printing
  6776. {
  6777. pDM->dmDuplex = DMDUP_VERTICAL;
  6778. hDuplexIcon = bPortrait ? hIconPDuplexNoTumble : hIconLDuplexTumble;
  6779. break;
  6780. }
  6781. case ( ID_SETUP_R_SHORT ) : // Short Side - 2 sided printing
  6782. {
  6783. pDM->dmDuplex = DMDUP_HORIZONTAL;
  6784. hDuplexIcon = bPortrait ? hIconPDuplexTumble : hIconLDuplexNoTumble;
  6785. break;
  6786. }
  6787. default : // None - 2 sided printing
  6788. {
  6789. pDM->dmDuplex = DMDUP_SIMPLEX;
  6790. hDuplexIcon = bPortrait ? hIconPDuplexNone : hIconLDuplexNone;
  6791. break;
  6792. }
  6793. }
  6794. //
  6795. // Set the appropriate icon.
  6796. //
  6797. ShowWindow(hCtl, SW_HIDE);
  6798. SendMessage(hCtl, STM_SETICON, (LONG_PTR)hDuplexIcon, 0L);
  6799. ShowWindow(hCtl, SW_SHOW);
  6800. }
  6801. }
  6802. ////////////////////////////////////////////////////////////////////////////
  6803. //
  6804. // PrintInitPaperCombo
  6805. //
  6806. ////////////////////////////////////////////////////////////////////////////
  6807. VOID PrintInitPaperCombo(
  6808. PPRINTINFO pPI,
  6809. HWND hCmb,
  6810. HWND hStc,
  6811. PPRINTER_INFO_2 pPrinter,
  6812. LPDEVMODE pDM,
  6813. WORD fwCap1,
  6814. WORD cchSize1,
  6815. WORD fwCap2)
  6816. {
  6817. DWORD cStr1, cStr2, cRet1, cRet2, i;
  6818. LPTSTR lpsOut1;
  6819. LPWORD lpwOut2;
  6820. BOOL fFill;
  6821. HourGlass(TRUE);
  6822. SendMessage(hCmb, CB_RESETCONTENT, 0, 0L);
  6823. cStr1 = DeviceCapabilities( pPrinter->pPrinterName,
  6824. pPrinter->pPortName,
  6825. fwCap1,
  6826. NULL,
  6827. pDM );
  6828. cStr2 = DeviceCapabilities( pPrinter->pPrinterName,
  6829. pPrinter->pPortName,
  6830. fwCap2,
  6831. NULL,
  6832. pDM );
  6833. //
  6834. // Check for error from DeviceCapabilities calls. If either
  6835. // call failed, simply set cStr1 to be 0 so that the windows will be
  6836. // disabled and nothing will be initialized.
  6837. //
  6838. if ((cStr1 == (DWORD)(-1)) || (cStr2 == (DWORD)(-1)))
  6839. {
  6840. cStr1 = 0;
  6841. }
  6842. fFill = (cStr1 > 0) && (cStr1 == cStr2);
  6843. if (!((pPI->pPSD) && (pPI->pPSD->Flags & PSD_DISABLEPAPER)))
  6844. {
  6845. //
  6846. // If no entries, disable hCmb and hStc.
  6847. //
  6848. EnableWindow(hCmb, fFill);
  6849. EnableWindow(hStc, fFill);
  6850. }
  6851. if (fFill)
  6852. {
  6853. lpsOut1 = LocalAlloc(LPTR, cStr1 * cchSize1 * sizeof(TCHAR));
  6854. lpwOut2 = LocalAlloc(LPTR, cStr2 * sizeof(WORD));
  6855. if (lpsOut1 && lpwOut2)
  6856. {
  6857. cRet1 = DeviceCapabilities( pPrinter->pPrinterName,
  6858. pPrinter->pPortName,
  6859. fwCap1,
  6860. (LPTSTR)lpsOut1,
  6861. pDM );
  6862. cRet2 = DeviceCapabilities( pPrinter->pPrinterName,
  6863. pPrinter->pPortName,
  6864. fwCap2,
  6865. (LPTSTR)lpwOut2,
  6866. pDM );
  6867. if ((pPI->dwRotation =
  6868. DeviceCapabilities( pPrinter->pPrinterName,
  6869. pPrinter->pPortName,
  6870. DC_ORIENTATION,
  6871. NULL,
  6872. pDM )) == (DWORD)(-1))
  6873. {
  6874. pPI->dwRotation = 0;
  6875. }
  6876. if ((cRet1 == cStr1) && (cRet2 == cStr2))
  6877. {
  6878. LPTSTR lpsT1 = lpsOut1;
  6879. LPWORD lpwT2 = lpwOut2;
  6880. int nInd;
  6881. LPTSTR lpFound = NULL;
  6882. LPTSTR lpFirst = NULL;
  6883. for (i = 0; i < cRet1; i++, lpsT1 += cchSize1, lpwT2++)
  6884. {
  6885. #ifndef WINNT
  6886. LPTSTR lpsT3;
  6887. LPWORD lpwT4;
  6888. //
  6889. // Various checks for HP LaserJet and PostScript
  6890. // driver bugs.
  6891. //
  6892. //
  6893. // Look for duplicate names.
  6894. //
  6895. for (lpsT3 = lpsOut1; lpsT3 <= lpsT1; lpsT3 += cchSize1)
  6896. {
  6897. if (!lstrcmp(lpsT3, lpsT1))
  6898. {
  6899. break;
  6900. }
  6901. }
  6902. if (lpsT3 != lpsT1)
  6903. {
  6904. //
  6905. // Duplicate found, so ignore.
  6906. //
  6907. continue;
  6908. }
  6909. //
  6910. // Look for duplicate values.
  6911. //
  6912. for (lpwT4 = lpwOut2; lpwT4 <= lpwT2; lpwT4++)
  6913. {
  6914. if (*lpwT4 == *lpwT2)
  6915. {
  6916. break;
  6917. }
  6918. }
  6919. if (lpwT4 != lpwT2)
  6920. {
  6921. //
  6922. // Duplicate found, so ignore.
  6923. //
  6924. continue;
  6925. }
  6926. #endif
  6927. //
  6928. // Look for a blank name entry.
  6929. //
  6930. if (!*lpsT1)
  6931. {
  6932. //
  6933. // Blank entry, so ignore.
  6934. //
  6935. continue;
  6936. }
  6937. //
  6938. // Add the string to the list box.
  6939. //
  6940. nInd = (int) SendMessage( hCmb,
  6941. CB_ADDSTRING,
  6942. 0,
  6943. (LPARAM)lpsT1 );
  6944. if (nInd != CB_ERR)
  6945. {
  6946. //
  6947. // Set the data associated with the string that
  6948. // was just added to the list box.
  6949. //
  6950. SendMessage( hCmb,
  6951. CB_SETITEMDATA,
  6952. nInd,
  6953. (LPARAM)*lpwT2 );
  6954. //
  6955. // See if this item should be selected.
  6956. //
  6957. if (!lpFound)
  6958. {
  6959. if (!lpFirst)
  6960. {
  6961. lpFirst = lpsT1;
  6962. }
  6963. if ( (fwCap1 == DC_PAPERNAMES) &&
  6964. (pDM->dmFields & DM_PAPERSIZE) &&
  6965. (pDM->dmPaperSize == (SHORT)*lpwT2) )
  6966. {
  6967. lpFound = lpsT1;
  6968. }
  6969. else if ( (fwCap1 == DC_BINNAMES) &&
  6970. (pDM->dmFields & DM_DEFAULTSOURCE) &&
  6971. (pDM->dmDefaultSource == (SHORT)*lpwT2) )
  6972. {
  6973. lpFound = lpsT1;
  6974. }
  6975. }
  6976. }
  6977. }
  6978. //
  6979. // Set the appropriate selection.
  6980. //
  6981. if (lpFound)
  6982. {
  6983. SendMessage( hCmb,
  6984. CB_SETCURSEL,
  6985. SendMessage( hCmb,
  6986. CB_FINDSTRINGEXACT,
  6987. (WPARAM)-1,
  6988. (LPARAM)lpFound ),
  6989. 0 );
  6990. }
  6991. else
  6992. {
  6993. if (fwCap1 == DC_PAPERNAMES)
  6994. {
  6995. //
  6996. // Check for a default FORM name.
  6997. //
  6998. if (!( (pDM->dmFields & DM_FORMNAME) &&
  6999. ((nInd = (int)
  7000. SendMessage( hCmb,
  7001. CB_SELECTSTRING,
  7002. (WPARAM)-1,
  7003. (LPARAM)pDM->dmFormName )) != CB_ERR) ))
  7004. {
  7005. //
  7006. // Always select the first *enumerated* entry
  7007. // if no other selection was found.
  7008. //
  7009. SendMessage( hCmb,
  7010. CB_SETCURSEL,
  7011. (lpFirst)
  7012. ? SendMessage( hCmb,
  7013. CB_FINDSTRINGEXACT,
  7014. (WPARAM)-1,
  7015. (LPARAM)lpFirst )
  7016. : 0,
  7017. 0 );
  7018. }
  7019. else
  7020. {
  7021. //
  7022. // Save the paper size since the form name exists
  7023. // in the list box.
  7024. //
  7025. // pDM->dmFields |= DM_PAPERSIZE;
  7026. pDM->dmPaperSize =
  7027. (SHORT)SendMessage( hCmb,
  7028. CB_GETITEMDATA,
  7029. nInd,
  7030. 0 );
  7031. }
  7032. }
  7033. else
  7034. {
  7035. //
  7036. // Set the SOURCE to the Default if it exists.
  7037. //
  7038. nInd = (int) SendMessage( hCmb,
  7039. CB_SELECTSTRING,
  7040. (WPARAM)-1,
  7041. (LPARAM)szDefaultSrc );
  7042. if (nInd != CB_ERR)
  7043. {
  7044. // pDM->dmFields |= DM_DEFAULTSOURCE;
  7045. pDM->dmDefaultSource =
  7046. (SHORT)SendMessage( hCmb,
  7047. CB_GETITEMDATA,
  7048. nInd,
  7049. 0 );
  7050. }
  7051. else
  7052. {
  7053. //
  7054. // Always select the first *enumerated* entry
  7055. // if no other selection was found.
  7056. //
  7057. SendMessage( hCmb,
  7058. CB_SETCURSEL,
  7059. (lpFirst)
  7060. ? SendMessage( hCmb,
  7061. CB_FINDSTRINGEXACT,
  7062. (WPARAM)-1,
  7063. (LPARAM)lpFirst )
  7064. : 0,
  7065. 0 );
  7066. }
  7067. }
  7068. }
  7069. }
  7070. }
  7071. if (lpsOut1)
  7072. {
  7073. LocalFree((HLOCAL)lpsOut1);
  7074. }
  7075. if (lpwOut2)
  7076. {
  7077. LocalFree((HLOCAL)lpwOut2);
  7078. }
  7079. }
  7080. HourGlass(FALSE);
  7081. }
  7082. ////////////////////////////////////////////////////////////////////////////
  7083. //
  7084. // PrintEditError
  7085. //
  7086. // Set focus to an edit control and select the entire contents.
  7087. // This is generally used when an improper value was found at OK time.
  7088. //
  7089. // Assumes edit control not disabled.
  7090. //
  7091. ////////////////////////////////////////////////////////////////////////////
  7092. VOID PrintEditError(
  7093. HWND hDlg,
  7094. int Id,
  7095. UINT MessageId,
  7096. ...)
  7097. {
  7098. HWND hEdit;
  7099. TCHAR pszTitle[MAX_PATH];
  7100. TCHAR pszFormat[MAX_PATH];
  7101. TCHAR pszMessage[MAX_PATH];
  7102. //
  7103. // Put up the error message box.
  7104. //
  7105. if ( GetWindowText(hDlg, pszTitle, ARRAYSIZE(pszTitle)) &&
  7106. CDLoadString(g_hinst, MessageId, pszFormat, ARRAYSIZE(pszFormat)) )
  7107. {
  7108. va_list ArgList;
  7109. va_start(ArgList, MessageId);
  7110. wvnsprintf(pszMessage, ARRAYSIZE(pszMessage), pszFormat, ArgList);
  7111. va_end(ArgList);
  7112. MessageBeep(MB_ICONEXCLAMATION);
  7113. MessageBox(hDlg, pszMessage, pszTitle, MB_ICONEXCLAMATION | MB_OK);
  7114. }
  7115. //
  7116. // Highlight the invalid value.
  7117. //
  7118. if (hEdit = ((Id == 0) ? NULL : GetDlgItem(hDlg, Id)))
  7119. {
  7120. SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)hEdit, 1L);
  7121. SendMessage(hEdit, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
  7122. }
  7123. }
  7124. ////////////////////////////////////////////////////////////////////////////
  7125. //
  7126. // PrintOpenPrinter
  7127. //
  7128. // If the OpenPrinter call is successful, this sets hPrinter, pPrinter,
  7129. // cPrinters, and pCurPrinter.
  7130. //
  7131. ////////////////////////////////////////////////////////////////////////////
  7132. VOID PrintOpenPrinter(
  7133. PPRINTINFO pPI,
  7134. LPTSTR pPrinterName)
  7135. {
  7136. if (OpenPrinter(pPrinterName, &pPI->hCurPrinter, NULL))
  7137. {
  7138. if (pPI->pPrinters = PrintGetPrinterInfo2(pPI->hCurPrinter))
  7139. {
  7140. pPI->cPrinters = 1;
  7141. #ifdef UNICODE
  7142. if (pPI->bUseExtDeviceMode)
  7143. {
  7144. PrintGetExtDeviceMode(NULL, pPI);
  7145. }
  7146. #endif
  7147. }
  7148. pPI->pCurPrinter = pPI->pPrinters;
  7149. }
  7150. else
  7151. {
  7152. //
  7153. // Cannot trust the OpenPrinter call.
  7154. //
  7155. pPI->hCurPrinter = NULL;
  7156. }
  7157. }
  7158. ////////////////////////////////////////////////////////////////////////////
  7159. //
  7160. // PrintClosePrinters
  7161. //
  7162. ////////////////////////////////////////////////////////////////////////////
  7163. BOOL PrintClosePrinters(
  7164. PPRINTINFO pPI)
  7165. {
  7166. if (pPI->hCurPrinter)
  7167. {
  7168. ClosePrinter(pPI->hCurPrinter);
  7169. pPI->hCurPrinter = 0;
  7170. }
  7171. pPI->pCurPrinter = NULL;
  7172. FreePrinterArray(pPI);
  7173. return (TRUE);
  7174. }
  7175. ////////////////////////////////////////////////////////////////////////////
  7176. //
  7177. // UpdateSpoolerInfo
  7178. //
  7179. ////////////////////////////////////////////////////////////////////////////
  7180. #ifdef UNICODE
  7181. VOID UpdateSpoolerInfo(
  7182. PPRINTINFO pPI)
  7183. {
  7184. LPDEVMODEA pDMA;
  7185. CHAR szPrinterNameA[33];
  7186. LPDEVMODEW pDMW;
  7187. //
  7188. // Get a pointer to the devmode structure.
  7189. //
  7190. pDMW = GlobalLock(pPI->pPD->hDevMode);
  7191. if ((!pDMW) || (!pPI->pCurPrinter))
  7192. {
  7193. return;
  7194. }
  7195. //
  7196. // Convert the printer name from Unicode to ANSI.
  7197. //
  7198. SHUnicodeToAnsi(pPI->pCurPrinter->pPrinterName, szPrinterNameA, ARRAYSIZE(szPrinterNameA));
  7199. //
  7200. // Allocate and convert the Unicode devmode to ANSI.
  7201. //
  7202. pDMA = AllocateAnsiDevMode(pDMW);
  7203. if (!pDMA)
  7204. {
  7205. GlobalUnlock(pPI->pPD->hDevMode);
  7206. return;
  7207. }
  7208. //
  7209. // Update the spooler's information.
  7210. //
  7211. ExtDeviceMode( NULL,
  7212. NULL,
  7213. NULL,
  7214. szPrinterNameA,
  7215. NULL,
  7216. pDMA,
  7217. NULL,
  7218. DM_UPDATE | DM_MODIFY );
  7219. //
  7220. // Free the buffer.
  7221. //
  7222. GlobalFree(pDMA);
  7223. GlobalUnlock(pPI->pPD->hDevMode);
  7224. }
  7225. #endif
  7226. ////////////////////////////////////////////////////////////////////////////
  7227. //
  7228. // PrintGetPrinterInfo2
  7229. //
  7230. ////////////////////////////////////////////////////////////////////////////
  7231. PPRINTER_INFO_2 PrintGetPrinterInfo2(
  7232. HANDLE hPrinter)
  7233. {
  7234. PPRINTER_INFO_2 pPrinter = NULL;
  7235. DWORD cbPrinter = 0;
  7236. StoreExtendedError(CDERR_GENERALCODES);
  7237. if (!GetPrinter(hPrinter, 2, NULL, 0, &cbPrinter) &&
  7238. (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
  7239. {
  7240. if (pPrinter = GlobalAlloc(GPTR, cbPrinter))
  7241. {
  7242. if (!GetPrinter( hPrinter,
  7243. 2,
  7244. (LPBYTE)pPrinter,
  7245. cbPrinter,
  7246. &cbPrinter ))
  7247. {
  7248. GlobalFree(pPrinter);
  7249. pPrinter = NULL;
  7250. StoreExtendedError(PDERR_PRINTERNOTFOUND);
  7251. }
  7252. }
  7253. else
  7254. {
  7255. StoreExtendedError(CDERR_MEMALLOCFAILURE);
  7256. }
  7257. }
  7258. else
  7259. {
  7260. StoreExtendedError(PDERR_SETUPFAILURE);
  7261. }
  7262. return (pPrinter);
  7263. }
  7264. ////////////////////////////////////////////////////////////////////////////
  7265. //
  7266. // ConvertStringToInteger
  7267. //
  7268. // Converts a string to an integer. Stops at the first non digit.
  7269. //
  7270. ////////////////////////////////////////////////////////////////////////////
  7271. int ConvertStringToInteger(
  7272. LPCTSTR pSrc)
  7273. {
  7274. int Number = 0;
  7275. BOOL bNeg = FALSE;
  7276. if (*pSrc == TEXT('-'))
  7277. {
  7278. bNeg = TRUE;
  7279. pSrc++;
  7280. }
  7281. while (ISDIGIT(*pSrc))
  7282. {
  7283. Number *= 10;
  7284. Number += *pSrc - TEXT('0');
  7285. pSrc++;
  7286. }
  7287. return ( bNeg ? -Number : Number );
  7288. }
  7289. ////////////////////////////////////////////////////////////////////////////
  7290. //
  7291. // FreePrinterArray
  7292. //
  7293. // Purpose: Frees the buffer allocated to store printers.
  7294. //
  7295. // Parameters: PPRINTINFO pPI
  7296. //
  7297. // Return: void
  7298. //
  7299. ////////////////////////////////////////////////////////////////////////////
  7300. VOID FreePrinterArray(
  7301. PPRINTINFO pPI)
  7302. {
  7303. PPRINTER_INFO_2 pPrinters = pPI->pPrinters;
  7304. #ifdef UNICODE
  7305. DWORD dwCount;
  7306. #endif
  7307. //
  7308. // If NULL, we can return now.
  7309. //
  7310. if (!pPrinters)
  7311. {
  7312. return;
  7313. }
  7314. #ifdef UNICODE
  7315. //
  7316. // If we made calls to ExtDeviceMode, then we need to
  7317. // free the buffers allocated for each devmode.
  7318. //
  7319. if (pPI->bUseExtDeviceMode)
  7320. {
  7321. if (pPI->pAllocInfo)
  7322. {
  7323. //
  7324. // Loop through each of the printers.
  7325. //
  7326. for (dwCount = 0; dwCount < pPI->cPrinters; dwCount++)
  7327. {
  7328. //
  7329. // If pDevMode exists, free it.
  7330. //
  7331. if ((pPrinters[dwCount].pDevMode) &&
  7332. (pPI->pAllocInfo[dwCount]))
  7333. {
  7334. GlobalFree(pPrinters[dwCount].pDevMode);
  7335. pPrinters[dwCount].pDevMode = NULL;
  7336. }
  7337. }
  7338. GlobalFree(pPI->pAllocInfo);
  7339. pPI->pAllocInfo = NULL;
  7340. }
  7341. }
  7342. #endif
  7343. //
  7344. // Free the entire block.
  7345. //
  7346. GlobalFree(pPI->pPrinters);
  7347. pPI->pPrinters = NULL;
  7348. pPI->cPrinters = 0;
  7349. }
  7350. ////////////////////////////////////////////////////////////////////////////
  7351. //
  7352. // TermPrint
  7353. //
  7354. ////////////////////////////////////////////////////////////////////////////
  7355. VOID TermPrint(void)
  7356. {
  7357. #ifdef WINNT
  7358. Print_UnloadLibraries(); // printnew.cpp
  7359. #endif
  7360. }
  7361. /*========================================================================*/
  7362. /* Page Setup <-> Print Dialog */
  7363. /*========================================================================*/
  7364. ////////////////////////////////////////////////////////////////////////////
  7365. //
  7366. // TransferPSD2PD
  7367. //
  7368. ////////////////////////////////////////////////////////////////////////////
  7369. VOID TransferPSD2PD(
  7370. PPRINTINFO pPI)
  7371. {
  7372. if (pPI->pPSD && pPI->pPD)
  7373. {
  7374. pPI->pPD->hDevMode = pPI->pPSD->hDevMode;
  7375. pPI->pPD->hDevNames = pPI->pPSD->hDevNames;
  7376. }
  7377. }
  7378. ////////////////////////////////////////////////////////////////////////////
  7379. //
  7380. // TransferPD2PSD
  7381. //
  7382. ////////////////////////////////////////////////////////////////////////////
  7383. VOID TransferPD2PSD(
  7384. PPRINTINFO pPI)
  7385. {
  7386. if (pPI->pPSD && pPI->pPD)
  7387. {
  7388. pPI->pPSD->hDevMode = pPI->pPD->hDevMode;
  7389. pPI->pPSD->hDevNames = pPI->pPD->hDevNames;
  7390. }
  7391. }
  7392. #ifdef UNICODE
  7393. ////////////////////////////////////////////////////////////////////////////
  7394. //
  7395. // TransferPSD2PDA
  7396. //
  7397. ////////////////////////////////////////////////////////////////////////////
  7398. VOID TransferPSD2PDA(
  7399. PPRINTINFO pPI)
  7400. {
  7401. if (pPI->pPSD && pPI->pPDA)
  7402. {
  7403. pPI->pPDA->hDevMode = pPI->pPSD->hDevMode;
  7404. pPI->pPDA->hDevNames = pPI->pPSD->hDevNames;
  7405. }
  7406. }
  7407. ////////////////////////////////////////////////////////////////////////////
  7408. //
  7409. // TransferPDA2PSD
  7410. //
  7411. ////////////////////////////////////////////////////////////////////////////
  7412. VOID TransferPDA2PSD(
  7413. PPRINTINFO pPI)
  7414. {
  7415. if (pPI->pPSD && pPI->pPDA)
  7416. {
  7417. pPI->pPSD->hDevMode = pPI->pPDA->hDevMode;
  7418. pPI->pPSD->hDevNames = pPI->pPDA->hDevNames;
  7419. }
  7420. }
  7421. #endif
  7422. /*========================================================================*/
  7423. /* Ansi->Unicode Thunk routines */
  7424. /*========================================================================*/
  7425. #ifdef UNICODE
  7426. ////////////////////////////////////////////////////////////////////////////
  7427. //
  7428. // ThunkPageSetupDlg
  7429. //
  7430. ////////////////////////////////////////////////////////////////////////////
  7431. BOOL ThunkPageSetupDlg(
  7432. PPRINTINFO pPI,
  7433. LPPAGESETUPDLGA pPSDA)
  7434. {
  7435. LPPRINTDLGA pPDA;
  7436. if (!pPSDA)
  7437. {
  7438. StoreExtendedError(CDERR_INITIALIZATION);
  7439. return (FALSE);
  7440. }
  7441. if (pPSDA->lStructSize != sizeof(PAGESETUPDLGA))
  7442. {
  7443. StoreExtendedError(CDERR_STRUCTSIZE);
  7444. return (FALSE);
  7445. }
  7446. if ((pPSDA->Flags & PSD_RETURNDEFAULT) &&
  7447. (pPSDA->hDevNames || pPSDA->hDevMode))
  7448. {
  7449. StoreExtendedError(PDERR_RETDEFFAILURE);
  7450. return (FALSE);
  7451. }
  7452. //
  7453. // Reset the size of the pPSD structure to the UNICODE size and
  7454. // save it in the pPI structure.
  7455. //
  7456. // NOTE: This must be reset back to the ANSI size before
  7457. // returning to the caller.
  7458. //
  7459. pPSDA->lStructSize = sizeof(PAGESETUPDLGW);
  7460. pPI->pPSD = (LPPAGESETUPDLG)pPSDA;
  7461. pPI->ApiType = COMDLG_ANSI;
  7462. //
  7463. // Create the ANSI version of the print dialog structure.
  7464. //
  7465. if (pPDA = GlobalAlloc(GPTR, sizeof(PRINTDLGA)))
  7466. {
  7467. pPI->pPDA = pPDA;
  7468. pPDA->lStructSize = sizeof(PRINTDLGA);
  7469. pPDA->hwndOwner = pPSDA->hwndOwner;
  7470. pPDA->Flags = PD_PAGESETUP |
  7471. (pPSDA->Flags &
  7472. (PSD_NOWARNING |
  7473. PSD_SHOWHELP |
  7474. PSD_ENABLEPAGESETUPHOOK |
  7475. PSD_ENABLEPAGESETUPTEMPLATE |
  7476. PSD_ENABLEPAGESETUPTEMPLATEHANDLE |
  7477. CD_WX86APP |
  7478. PSD_NONETWORKBUTTON));
  7479. pPDA->hInstance = pPSDA->hInstance;
  7480. pPDA->lCustData = pPSDA->lCustData;
  7481. pPDA->lpfnSetupHook = pPSDA->lpfnPageSetupHook;
  7482. pPDA->lpSetupTemplateName = pPSDA->lpPageSetupTemplateName;
  7483. pPDA->hSetupTemplate = pPSDA->hPageSetupTemplate;
  7484. pPDA->hDevMode = pPSDA->hDevMode;
  7485. pPDA->hDevNames = pPSDA->hDevNames;
  7486. }
  7487. else
  7488. {
  7489. StoreExtendedError(CDERR_MEMALLOCFAILURE);
  7490. return (FALSE);
  7491. }
  7492. return (TRUE);
  7493. }
  7494. ////////////////////////////////////////////////////////////////////////////
  7495. //
  7496. // FreeThunkPageSetupDlg
  7497. //
  7498. ////////////////////////////////////////////////////////////////////////////
  7499. VOID FreeThunkPageSetupDlg(
  7500. PPRINTINFO pPI)
  7501. {
  7502. //
  7503. // Reset the size of the pPSD structure to the correct value.
  7504. //
  7505. if (pPI->pPSD)
  7506. {
  7507. pPI->pPSD->lStructSize = sizeof(PAGESETUPDLGA);
  7508. }
  7509. //
  7510. // Free the ANSI print dialog structure.
  7511. //
  7512. if (pPI->pPDA)
  7513. {
  7514. GlobalFree(pPI->pPDA);
  7515. pPI->pPDA = NULL;
  7516. }
  7517. }
  7518. ////////////////////////////////////////////////////////////////////////////
  7519. //
  7520. // ThunkPrintDlg
  7521. //
  7522. ////////////////////////////////////////////////////////////////////////////
  7523. BOOL ThunkPrintDlg(
  7524. PPRINTINFO pPI,
  7525. LPPRINTDLGA pPDA)
  7526. {
  7527. LPPRINTDLGW pPDW;
  7528. LPDEVMODEA pDMA;
  7529. DWORD cbLen;
  7530. if (!pPDA)
  7531. {
  7532. StoreExtendedError(CDERR_INITIALIZATION);
  7533. return (FALSE);
  7534. }
  7535. if (pPDA->lStructSize != sizeof(PRINTDLGA))
  7536. {
  7537. StoreExtendedError(CDERR_STRUCTSIZE);
  7538. return (FALSE);
  7539. }
  7540. if (!(pPDW = GlobalAlloc(GPTR, sizeof(PRINTDLGW))))
  7541. {
  7542. StoreExtendedError(CDERR_MEMALLOCFAILURE);
  7543. return (FALSE);
  7544. }
  7545. //
  7546. // IN-only constant stuff.
  7547. //
  7548. pPDW->lStructSize = sizeof(PRINTDLGW);
  7549. pPDW->hwndOwner = pPDA->hwndOwner;
  7550. pPDW->hInstance = pPDA->hInstance;
  7551. pPDW->lpfnPrintHook = pPDA->lpfnPrintHook;
  7552. pPDW->lpfnSetupHook = pPDA->lpfnSetupHook;
  7553. pPDW->hPrintTemplate = pPDA->hPrintTemplate;
  7554. pPDW->hSetupTemplate = pPDA->hSetupTemplate;
  7555. //
  7556. // IN-OUT Variable Structs.
  7557. //
  7558. if ((pPDA->hDevMode) && (pDMA = GlobalLock(pPDA->hDevMode)))
  7559. {
  7560. //
  7561. // Make sure the device name in the devmode is not too long such that
  7562. // it has overwritten the other devmode fields.
  7563. //
  7564. if ((pDMA->dmSize < MIN_DEVMODE_SIZEA) ||
  7565. (lstrlenA(pDMA->dmDeviceName) > CCHDEVICENAME))
  7566. {
  7567. pPDW->hDevMode = NULL;
  7568. }
  7569. else
  7570. {
  7571. pPDW->hDevMode = GlobalAlloc( GHND,
  7572. sizeof(DEVMODEW) + pDMA->dmDriverExtra );
  7573. }
  7574. GlobalUnlock(pPDA->hDevMode);
  7575. }
  7576. else
  7577. {
  7578. pPDW->hDevMode = NULL;
  7579. }
  7580. //
  7581. // Thunk Device Names A => W
  7582. //
  7583. pPDW->hDevNames = NULL;
  7584. if (pPDA->hDevNames)
  7585. {
  7586. // ignore the error case since we can't handle it either way.
  7587. HRESULT hr = ThunkDevNamesA2W(pPDA->hDevNames, &pPDW->hDevNames);
  7588. ASSERT(SUCCEEDED(hr));
  7589. }
  7590. //
  7591. // IN-only constant strings.
  7592. //
  7593. // Init Print TemplateName constant.
  7594. //
  7595. if ((pPDA->Flags & PD_ENABLEPRINTTEMPLATE) && (pPDA->lpPrintTemplateName))
  7596. {
  7597. //
  7598. // See if it's a string or an integer.
  7599. //
  7600. if (!IS_INTRESOURCE(pPDA->lpPrintTemplateName))
  7601. {
  7602. //
  7603. // String.
  7604. //
  7605. cbLen = lstrlenA(pPDA->lpPrintTemplateName) + 1;
  7606. if (!(pPDW->lpPrintTemplateName =
  7607. GlobalAlloc( GPTR,
  7608. (cbLen * sizeof(WCHAR)) )))
  7609. {
  7610. StoreExtendedError(CDERR_MEMALLOCFAILURE);
  7611. return (FALSE);
  7612. }
  7613. else
  7614. {
  7615. pPI->fPrintTemplateAlloc = TRUE;
  7616. SHAnsiToUnicode(pPDA->lpPrintTemplateName,(LPWSTR)pPDW->lpPrintTemplateName, cbLen);
  7617. }
  7618. }
  7619. else
  7620. {
  7621. //
  7622. // Integer.
  7623. //
  7624. (DWORD_PTR)pPDW->lpPrintTemplateName = (DWORD_PTR)pPDA->lpPrintTemplateName;
  7625. }
  7626. }
  7627. else
  7628. {
  7629. pPDW->lpPrintTemplateName = NULL;
  7630. }
  7631. //
  7632. // Init Print Setup TemplateName constant.
  7633. //
  7634. if ((pPDA->Flags & PD_ENABLESETUPTEMPLATE) && (pPDA->lpSetupTemplateName))
  7635. {
  7636. //
  7637. // See if it's a string or an integer.
  7638. //
  7639. if (!IS_INTRESOURCE(pPDA->lpSetupTemplateName))
  7640. {
  7641. //
  7642. // String.
  7643. //
  7644. cbLen = lstrlenA(pPDA->lpSetupTemplateName) + 1;
  7645. if (!(pPDW->lpSetupTemplateName =
  7646. GlobalAlloc( GPTR,
  7647. (cbLen * sizeof(WCHAR)) )))
  7648. {
  7649. StoreExtendedError(CDERR_MEMALLOCFAILURE);
  7650. return (FALSE);
  7651. }
  7652. else
  7653. {
  7654. pPI->fSetupTemplateAlloc = TRUE;
  7655. SHAnsiToUnicode(pPDA->lpSetupTemplateName,(LPWSTR)pPDW->lpSetupTemplateName,cbLen);
  7656. }
  7657. }
  7658. else
  7659. {
  7660. //
  7661. // Integer.
  7662. //
  7663. (DWORD_PTR)pPDW->lpSetupTemplateName = (DWORD_PTR)pPDA->lpSetupTemplateName;
  7664. }
  7665. }
  7666. else
  7667. {
  7668. pPDW->lpSetupTemplateName = NULL;
  7669. }
  7670. pPI->pPD = pPDW;
  7671. pPI->pPDA = pPDA;
  7672. pPI->ApiType = COMDLG_ANSI;
  7673. return (TRUE);
  7674. }
  7675. ////////////////////////////////////////////////////////////////////////////
  7676. //
  7677. // FreeThunkPrintDlg
  7678. //
  7679. ////////////////////////////////////////////////////////////////////////////
  7680. VOID FreeThunkPrintDlg(
  7681. PPRINTINFO pPI)
  7682. {
  7683. LPPRINTDLGW pPDW = pPI->pPD;
  7684. if (!pPDW)
  7685. {
  7686. return;
  7687. }
  7688. if (pPDW->hDevNames)
  7689. {
  7690. GlobalFree(pPDW->hDevNames);
  7691. }
  7692. if (pPDW->hDevMode)
  7693. {
  7694. GlobalFree(pPDW->hDevMode);
  7695. }
  7696. if (pPI->fPrintTemplateAlloc)
  7697. {
  7698. GlobalFree((LPWSTR)(pPDW->lpPrintTemplateName));
  7699. }
  7700. if (pPI->fSetupTemplateAlloc)
  7701. {
  7702. GlobalFree((LPWSTR)(pPDW->lpSetupTemplateName));
  7703. }
  7704. GlobalFree(pPDW);
  7705. pPI->pPD = NULL;
  7706. }
  7707. ////////////////////////////////////////////////////////////////////////////
  7708. //
  7709. // ThunkPrintDlgA2W
  7710. //
  7711. ////////////////////////////////////////////////////////////////////////////
  7712. VOID ThunkPrintDlgA2W(
  7713. PPRINTINFO pPI)
  7714. {
  7715. LPPRINTDLGW pPDW = pPI->pPD;
  7716. LPPRINTDLGA pPDA = pPI->pPDA;
  7717. //
  7718. // Copy info A => W
  7719. //
  7720. pPDW->hDC = pPDA->hDC;
  7721. pPDW->Flags = pPDA->Flags;
  7722. pPDW->nFromPage = pPDA->nFromPage;
  7723. pPDW->nToPage = pPDA->nToPage;
  7724. pPDW->nMinPage = pPDA->nMinPage;
  7725. pPDW->nMaxPage = pPDA->nMaxPage;
  7726. pPDW->nCopies = pPDA->nCopies;
  7727. pPDW->lCustData = pPDA->lCustData;
  7728. pPDW->lpfnPrintHook = pPDA->lpfnPrintHook;
  7729. pPDW->lpfnSetupHook = pPDA->lpfnSetupHook;
  7730. //
  7731. // Thunk Device Names A => W
  7732. //
  7733. if (pPDA->hDevNames)
  7734. {
  7735. // ignore the error case since we can't handle it either way.
  7736. HRESULT hr = ThunkDevNamesA2W(pPDA->hDevNames, &pPDW->hDevNames);
  7737. ASSERT(SUCCEEDED(hr));
  7738. }
  7739. //
  7740. // Thunk Device Mode A => W
  7741. //
  7742. if (pPDA->hDevMode && pPDW->hDevMode)
  7743. {
  7744. LPDEVMODEW pDMW = GlobalLock(pPDW->hDevMode);
  7745. LPDEVMODEA pDMA = GlobalLock(pPDA->hDevMode);
  7746. ThunkDevModeA2W(pDMA, pDMW);
  7747. GlobalUnlock(pPDW->hDevMode);
  7748. GlobalUnlock(pPDA->hDevMode);
  7749. }
  7750. }
  7751. ////////////////////////////////////////////////////////////////////////////
  7752. //
  7753. // ThunkPrintDlgW2A
  7754. //
  7755. ////////////////////////////////////////////////////////////////////////////
  7756. VOID ThunkPrintDlgW2A(
  7757. PPRINTINFO pPI)
  7758. {
  7759. LPPRINTDLGA pPDA = pPI->pPDA;
  7760. LPPRINTDLGW pPDW = pPI->pPD;
  7761. //
  7762. // Copy info W => A
  7763. //
  7764. pPDA->hDC = pPDW->hDC;
  7765. pPDA->Flags = pPDW->Flags;
  7766. pPDA->nFromPage = pPDW->nFromPage;
  7767. pPDA->nToPage = pPDW->nToPage;
  7768. pPDA->nMinPage = pPDW->nMinPage;
  7769. pPDA->nMaxPage = pPDW->nMaxPage;
  7770. pPDA->nCopies = pPDW->nCopies;
  7771. pPDA->lCustData = pPDW->lCustData;
  7772. pPDA->lpfnPrintHook = pPDW->lpfnPrintHook;
  7773. pPDA->lpfnSetupHook = pPDW->lpfnSetupHook;
  7774. //
  7775. // Thunk Device Names W => A
  7776. //
  7777. if (pPDW->hDevNames)
  7778. {
  7779. // ignore the error case since we can't handle it either way.
  7780. HRESULT hr = ThunkDevNamesW2A(pPDW->hDevNames, &pPDA->hDevNames);
  7781. ASSERT(SUCCEEDED(hr));
  7782. }
  7783. //
  7784. // Thunk Device Mode W => A
  7785. //
  7786. if (pPDW->hDevMode)
  7787. {
  7788. LPDEVMODEW pDMW = GlobalLock(pPDW->hDevMode);
  7789. LPDEVMODEA pDMA;
  7790. if (pPDA->hDevMode)
  7791. {
  7792. HANDLE handle;
  7793. handle = GlobalReAlloc( pPDA->hDevMode,
  7794. sizeof(DEVMODEA) + pDMW->dmDriverExtra,
  7795. GHND );
  7796. //Make sure realloc succeeded.
  7797. if (handle)
  7798. {
  7799. pPDA->hDevMode = handle;
  7800. }
  7801. else
  7802. {
  7803. //Realloc didn't succeed. Free the memory occupied
  7804. pPDA->hDevMode = GlobalFree(pPDA->hDevMode);
  7805. }
  7806. }
  7807. else
  7808. {
  7809. pPDA->hDevMode = GlobalAlloc( GHND,
  7810. sizeof(DEVMODEA) + pDMW->dmDriverExtra );
  7811. }
  7812. if (pPDA->hDevMode)
  7813. {
  7814. pDMA = GlobalLock(pPDA->hDevMode);
  7815. ThunkDevModeW2A(pDMW, pDMA);
  7816. GlobalUnlock(pPDA->hDevMode);
  7817. }
  7818. GlobalUnlock(pPDW->hDevMode);
  7819. }
  7820. }
  7821. ////////////////////////////////////////////////////////////////////////////
  7822. //
  7823. // ThunkDevModeA2W
  7824. //
  7825. ////////////////////////////////////////////////////////////////////////////
  7826. VOID ThunkDevModeA2W(
  7827. LPDEVMODEA pDMA,
  7828. LPDEVMODEW pDMW)
  7829. {
  7830. LPDEVMODEA pDevModeA;
  7831. if (!pDMA || !pDMW)
  7832. {
  7833. return;
  7834. }
  7835. //
  7836. // Make sure the device name in the devmode is not too long such that
  7837. // it has overwritten the other devmode fields.
  7838. //
  7839. if ((pDMA->dmSize < MIN_DEVMODE_SIZEA) ||
  7840. (lstrlenA(pDMA->dmDeviceName) > CCHDEVICENAME))
  7841. {
  7842. return;
  7843. }
  7844. //
  7845. // We need to create a temporary ANSI that is a known size.
  7846. // The problem is if we are being called from WOW, the WOW
  7847. // app could be either a Windows 3.1 or 3.0 app. The size
  7848. // of the devmode structure was different for both of these
  7849. // versions compared to the DEVMODE structure in NT.
  7850. // By copying the ANSI devmode to one we allocate, then we
  7851. // can access all of the fields (26 currently) without causing
  7852. // an access violation.
  7853. //
  7854. pDevModeA = GlobalAlloc(GPTR, sizeof(DEVMODEA) + pDMA->dmDriverExtra);
  7855. if (!pDevModeA)
  7856. {
  7857. return;
  7858. }
  7859. CopyMemory( (LPBYTE)pDevModeA,
  7860. (LPBYTE)pDMA,
  7861. min(sizeof(DEVMODEA), pDMA->dmSize) );
  7862. CopyMemory( (LPBYTE)pDevModeA + sizeof(DEVMODEA),
  7863. (LPBYTE)pDMA + pDMA->dmSize,
  7864. pDMA->dmDriverExtra );
  7865. //
  7866. // Now we can thunk the contents of the ANSI structure to the
  7867. // Unicode structure.
  7868. //
  7869. SHAnsiToUnicode((LPSTR)pDevModeA->dmDeviceName,(LPWSTR)pDMW->dmDeviceName,CCHDEVICENAME );
  7870. pDMW->dmSpecVersion = pDevModeA->dmSpecVersion;
  7871. pDMW->dmDriverVersion = pDevModeA->dmDriverVersion;
  7872. pDMW->dmSize = sizeof(DEVMODEW);
  7873. pDMW->dmDriverExtra = pDevModeA->dmDriverExtra;
  7874. pDMW->dmFields = pDevModeA->dmFields;
  7875. pDMW->dmOrientation = pDevModeA->dmOrientation;
  7876. pDMW->dmPaperSize = pDevModeA->dmPaperSize;
  7877. pDMW->dmPaperLength = pDevModeA->dmPaperLength;
  7878. pDMW->dmPaperWidth = pDevModeA->dmPaperWidth;
  7879. pDMW->dmScale = pDevModeA->dmScale;
  7880. pDMW->dmCopies = pDevModeA->dmCopies;
  7881. pDMW->dmDefaultSource = pDevModeA->dmDefaultSource;
  7882. pDMW->dmPrintQuality = pDevModeA->dmPrintQuality;
  7883. pDMW->dmColor = pDevModeA->dmColor;
  7884. pDMW->dmDuplex = pDevModeA->dmDuplex;
  7885. pDMW->dmYResolution = pDevModeA->dmYResolution;
  7886. pDMW->dmTTOption = pDevModeA->dmTTOption;
  7887. pDMW->dmCollate = pDevModeA->dmCollate;
  7888. SHAnsiToUnicode((LPSTR)pDevModeA->dmFormName,(LPWSTR)pDMW->dmFormName,CCHFORMNAME );
  7889. pDMW->dmLogPixels = pDevModeA->dmLogPixels;
  7890. pDMW->dmBitsPerPel = pDevModeA->dmBitsPerPel;
  7891. pDMW->dmPelsWidth = pDevModeA->dmPelsWidth;
  7892. pDMW->dmPelsHeight = pDevModeA->dmPelsHeight;
  7893. pDMW->dmDisplayFlags = pDevModeA->dmDisplayFlags;
  7894. pDMW->dmDisplayFrequency = pDevModeA->dmDisplayFrequency;
  7895. pDMW->dmICMMethod = pDevModeA->dmICMMethod;
  7896. pDMW->dmICMIntent = pDevModeA->dmICMIntent;
  7897. pDMW->dmMediaType = pDevModeA->dmMediaType;
  7898. pDMW->dmDitherType = pDevModeA->dmDitherType;
  7899. pDMW->dmReserved1 = pDevModeA->dmReserved1;
  7900. pDMW->dmReserved2 = pDevModeA->dmReserved2;
  7901. pDMW->dmPanningWidth = pDevModeA->dmPanningWidth;
  7902. pDMW->dmPanningHeight = pDevModeA->dmPanningHeight;
  7903. CopyMemory( (pDMW + 1),
  7904. (pDevModeA + 1),
  7905. pDevModeA->dmDriverExtra );
  7906. //
  7907. // Free the memory we allocated.
  7908. //
  7909. GlobalFree(pDevModeA);
  7910. }
  7911. ////////////////////////////////////////////////////////////////////////////
  7912. //
  7913. // ThunkDevModeW2A
  7914. //
  7915. ////////////////////////////////////////////////////////////////////////////
  7916. VOID ThunkDevModeW2A(
  7917. LPDEVMODEW pDMW,
  7918. LPDEVMODEA pDMA)
  7919. {
  7920. if (!pDMW || !pDMA)
  7921. {
  7922. return;
  7923. }
  7924. SHUnicodeToAnsi((LPWSTR)pDMW->dmDeviceName,(LPSTR)pDMA->dmDeviceName,CCHDEVICENAME);
  7925. pDMA->dmSpecVersion = pDMW->dmSpecVersion;
  7926. pDMA->dmDriverVersion = pDMW->dmDriverVersion;
  7927. pDMA->dmSize = sizeof(DEVMODEA);
  7928. pDMA->dmDriverExtra = pDMW->dmDriverExtra;
  7929. pDMA->dmFields = pDMW->dmFields;
  7930. pDMA->dmOrientation = pDMW->dmOrientation;
  7931. pDMA->dmPaperSize = pDMW->dmPaperSize;
  7932. pDMA->dmPaperLength = pDMW->dmPaperLength;
  7933. pDMA->dmPaperWidth = pDMW->dmPaperWidth;
  7934. pDMA->dmScale = pDMW->dmScale;
  7935. pDMA->dmCopies = pDMW->dmCopies;
  7936. pDMA->dmDefaultSource = pDMW->dmDefaultSource;
  7937. pDMA->dmPrintQuality = pDMW->dmPrintQuality;
  7938. pDMA->dmColor = pDMW->dmColor;
  7939. pDMA->dmDuplex = pDMW->dmDuplex;
  7940. pDMA->dmYResolution = pDMW->dmYResolution;
  7941. pDMA->dmTTOption = pDMW->dmTTOption;
  7942. pDMA->dmCollate = pDMW->dmCollate;
  7943. SHUnicodeToAnsi((LPWSTR)pDMW->dmFormName,(LPSTR)pDMA->dmFormName,CCHFORMNAME);
  7944. pDMA->dmLogPixels = pDMW->dmLogPixels;
  7945. pDMA->dmBitsPerPel = pDMW->dmBitsPerPel;
  7946. pDMA->dmPelsWidth = pDMW->dmPelsWidth;
  7947. pDMA->dmPelsHeight = pDMW->dmPelsHeight;
  7948. pDMA->dmDisplayFlags = pDMW->dmDisplayFlags;
  7949. pDMA->dmDisplayFrequency = pDMW->dmDisplayFrequency;
  7950. pDMA->dmICMMethod = pDMW->dmICMMethod;
  7951. pDMA->dmICMIntent = pDMW->dmICMIntent;
  7952. pDMA->dmMediaType = pDMW->dmMediaType;
  7953. pDMA->dmDitherType = pDMW->dmDitherType;
  7954. pDMA->dmReserved1 = pDMW->dmReserved1;
  7955. pDMA->dmReserved2 = pDMW->dmReserved2;
  7956. pDMA->dmPanningWidth = pDMW->dmPanningWidth;
  7957. pDMA->dmPanningHeight = pDMW->dmPanningHeight;
  7958. CopyMemory( (pDMA + 1),
  7959. (pDMW + 1),
  7960. pDMA->dmDriverExtra );
  7961. }
  7962. ////////////////////////////////////////////////////////////////////////////
  7963. //
  7964. // AllocateUnicodeDevMode
  7965. //
  7966. // Purpose: Allocates a Unicode devmode structure, and calls
  7967. // the thunk function to fill it in.
  7968. //
  7969. // Parameters: LPDEVMODEA pANSIDevMode
  7970. //
  7971. // Return: LPDEVMODEW - pointer to new devmode if successful
  7972. // NULL if not.
  7973. //
  7974. ////////////////////////////////////////////////////////////////////////////
  7975. LPDEVMODEW AllocateUnicodeDevMode(
  7976. LPDEVMODEA pANSIDevMode)
  7977. {
  7978. int iSize;
  7979. LPDEVMODEW pUnicodeDevMode;
  7980. //
  7981. // Check for NULL pointer.
  7982. //
  7983. if (!pANSIDevMode)
  7984. {
  7985. return (NULL);
  7986. }
  7987. //
  7988. // Determine output structure size. This has two components: the
  7989. // DEVMODEW structure size, plus any private data area. The latter
  7990. // is only meaningful when a structure is passed in.
  7991. //
  7992. iSize = sizeof(DEVMODEW);
  7993. iSize += pANSIDevMode->dmDriverExtra;
  7994. pUnicodeDevMode = GlobalAlloc(GPTR, iSize);
  7995. if (!pUnicodeDevMode)
  7996. {
  7997. return (NULL);
  7998. }
  7999. //
  8000. // Now call the thunk routine to copy the ANSI devmode to the
  8001. // Unicode devmode.
  8002. //
  8003. ThunkDevModeA2W(pANSIDevMode, pUnicodeDevMode);
  8004. //
  8005. // Return the pointer.
  8006. //
  8007. return (pUnicodeDevMode);
  8008. }
  8009. ////////////////////////////////////////////////////////////////////////////
  8010. //
  8011. // AllocateAnsiDevMode
  8012. //
  8013. // Purpose: Allocates a Ansi devmode structure, and calls
  8014. // the thunk function to fill it in.
  8015. //
  8016. // Parameters: LPDEVMODEW pUnicodeDevMode
  8017. //
  8018. // Return: LPDEVMODEA - pointer to new devmode if successful
  8019. // NULL if not.
  8020. //
  8021. ////////////////////////////////////////////////////////////////////////////
  8022. LPDEVMODEA AllocateAnsiDevMode(
  8023. LPDEVMODEW pUnicodeDevMode)
  8024. {
  8025. int iSize;
  8026. LPDEVMODEA pANSIDevMode;
  8027. //
  8028. // Check for NULL pointer.
  8029. //
  8030. if (!pUnicodeDevMode)
  8031. {
  8032. return (NULL);
  8033. }
  8034. //
  8035. // Determine output structure size. This has two components: the
  8036. // DEVMODEW structure size, plus any private data area. The latter
  8037. // is only meaningful when a structure is passed in.
  8038. //
  8039. iSize = sizeof(DEVMODEA);
  8040. iSize += pUnicodeDevMode->dmDriverExtra;
  8041. pANSIDevMode = GlobalAlloc(GPTR, iSize);
  8042. if (!pANSIDevMode)
  8043. {
  8044. return (NULL);
  8045. }
  8046. //
  8047. // Now call the thunk routine to copy the Unicode devmode to the
  8048. // ANSI devmode.
  8049. //
  8050. ThunkDevModeW2A(pUnicodeDevMode, pANSIDevMode);
  8051. //
  8052. // Return the pointer.
  8053. //
  8054. return (pANSIDevMode);
  8055. }
  8056. #ifdef WINNT
  8057. ////////////////////////////////////////////////////////////////////////////
  8058. //
  8059. // Ssync_ANSI_UNICODE_PD_For_WOW
  8060. //
  8061. // Function to allow NT WOW to keep the ANSI & UNICODE versions of
  8062. // the CHOOSEFONT structure in ssync as required by many 16-bit apps.
  8063. // See notes for Ssync_ANSI_UNICODE_Struct_For_WOW() in dlgs.c.
  8064. //
  8065. ////////////////////////////////////////////////////////////////////////////
  8066. VOID Ssync_ANSI_UNICODE_PD_For_WOW(
  8067. HWND hDlg,
  8068. BOOL f_ANSI_to_UNICODE)
  8069. {
  8070. PPRINTINFO pPI;
  8071. if (pPI = (PPRINTINFO)GetProp(hDlg, PRNPROP))
  8072. {
  8073. if (pPI->pPD && pPI->pPDA)
  8074. {
  8075. if (f_ANSI_to_UNICODE)
  8076. {
  8077. ThunkPrintDlgA2W(pPI);
  8078. }
  8079. else
  8080. {
  8081. ThunkPrintDlgW2A(pPI);
  8082. }
  8083. }
  8084. }
  8085. }
  8086. #endif
  8087. #endif
  8088. ////////////////////////////////////////////////////////////////////////////
  8089. //
  8090. // SetCopiesEditWidth
  8091. //
  8092. // Adjust the width of the copies edit control using the current
  8093. // font and the scroll bar width. This is necessary to handle the
  8094. // the up down control from encroching on the space in the edit
  8095. // control when we are in High Contrast (extra large) mode.
  8096. //
  8097. ////////////////////////////////////////////////////////////////////////////
  8098. VOID SetCopiesEditWidth(
  8099. HWND hDlg,
  8100. HWND hControl)
  8101. {
  8102. HDC hDC = NULL;
  8103. LONG MaxDigitExtant = 0;
  8104. LONG EditControlWidth = 0;
  8105. LONG CurrentWidth = 0;
  8106. UINT i = 0;
  8107. INT aDigitWidth[10];
  8108. WINDOWPLACEMENT WndPl;
  8109. //
  8110. // Acquire the edit controls device context.
  8111. //
  8112. hDC = GetDC( hControl );
  8113. if (hDC)
  8114. {
  8115. //
  8116. // Determine max width of the digit group.
  8117. //
  8118. if (GetCharWidth32( hDC, TEXT('0'), TEXT('9'), aDigitWidth))
  8119. {
  8120. for (i = 0; i < ARRAYSIZE(aDigitWidth); i++)
  8121. {
  8122. if (aDigitWidth[i] > MaxDigitExtant)
  8123. {
  8124. MaxDigitExtant = aDigitWidth[i];
  8125. }
  8126. }
  8127. //
  8128. // Get the edit control placement.
  8129. //
  8130. WndPl.length = sizeof( WndPl );
  8131. if (GetWindowPlacement( hControl, &WndPl ))
  8132. {
  8133. //
  8134. // Calculate the edit control current width.
  8135. //
  8136. EditControlWidth = MaxDigitExtant * COPIES_EDIT_SIZE;
  8137. //
  8138. // Calculate the current width of the edit control.
  8139. //
  8140. CurrentWidth = WndPl.rcNormalPosition.right - WndPl.rcNormalPosition.left;
  8141. //
  8142. // Set the new position of the edit control.
  8143. //
  8144. WndPl.rcNormalPosition.left = WndPl.rcNormalPosition.left - (EditControlWidth - CurrentWidth);
  8145. //
  8146. // Place the control.
  8147. //
  8148. SetWindowPlacement( hControl, &WndPl );
  8149. }
  8150. }
  8151. //
  8152. // Release the device context.
  8153. //
  8154. ReleaseDC( hControl, hDC );
  8155. }
  8156. }
  8157. ////////////////////////////////////////////////////////////////////////////
  8158. //
  8159. // CountDigits
  8160. //
  8161. // Count how many digits is needed for a specific number
  8162. //
  8163. ////////////////////////////////////////////////////////////////////////////
  8164. WORD
  8165. CountDigits(
  8166. DWORD dwNumber)
  8167. {
  8168. WORD cDigits = 0;
  8169. if(dwNumber == 0)
  8170. {
  8171. return 1;
  8172. }
  8173. while(dwNumber > 0)
  8174. {
  8175. cDigits++;
  8176. dwNumber /= 10;
  8177. }
  8178. return cDigits++;
  8179. }