Leaked source code of windows server 2003
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.

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