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

1387 lines
44 KiB

  1. // Copyright (c) 1996-1997, Microsoft Corp. All rights reserved.
  2. #include "header.h"
  3. #include "contain.h"
  4. #include "cprint.h"
  5. #include "secwin.h"
  6. #include "web.h"
  7. #include "contain.h"
  8. #include <exdisp.h>
  9. #include <exdispid.h>
  10. #include "cdlg.h"
  11. #include "resource.h"
  12. #include "progress.h"
  13. #include "cpaldc.h"
  14. #include "hha_strtable.h"
  15. #include "animate.h"
  16. #include <wininet.h>
  17. // #define INITGUID
  18. #include <mshtmhst.h>
  19. #include <mshtmcid.h>
  20. BOOL CPrint::OnBeginOrEnd(void)
  21. {
  22. if (m_fInitializing) {
  23. switch (m_action) {
  24. case PRINT_CUR_ALL:
  25. SetCheck(IDRADIO_PRINT_ALL);
  26. break;
  27. case PRINT_CUR_HEADING:
  28. SetCheck(IDRADIO_PRINT_BOOK);
  29. break;
  30. default:
  31. SetCheck(IDRADIO_PRINT_CURRENT);
  32. break;
  33. }
  34. }
  35. else {
  36. if (GetCheck(IDRADIO_PRINT_ALL))
  37. m_action = PRINT_CUR_ALL;
  38. else if (GetCheck(IDRADIO_PRINT_BOOK))
  39. m_action = PRINT_CUR_HEADING;
  40. else
  41. m_action = PRINT_CUR_TOPIC;
  42. }
  43. return TRUE;
  44. }
  45. void CHHWinType::OnPrint(void)
  46. {
  47. HWND hWnd;
  48. if (m_pCIExpContainer == NULL)
  49. {
  50. return;
  51. }
  52. static BOOL fCurrentlyPrinting = FALSE;
  53. if (fCurrentlyPrinting) {
  54. MsgBox(IDS_PRINTING);
  55. return;
  56. }
  57. CToc* ptoc = reinterpret_cast<CToc*>(m_aNavPane[HH_TAB_CONTENTS]) ; // HACKHACK: This should be a dynamic_cast. However, we are not compiling with RTTI.
  58. hWnd = GetFocus();
  59. int action = PRINT_CUR_TOPIC;
  60. if (IsExpandedNavPane() && curNavType == HHWIN_NAVTYPE_TOC && ptoc != NULL)
  61. {
  62. HTREEITEM hitem = TreeView_GetSelection(ptoc->m_hwndTree);
  63. if (hitem) {
  64. CPrint prt(*this);
  65. prt.SetAction(action);
  66. if (!prt.DoModal())
  67. {
  68. SetFocus(hWnd);
  69. return;
  70. }
  71. action = prt.GetAction();
  72. }
  73. }
  74. if (action == PRINT_CUR_TOPIC) {
  75. m_pCIExpContainer->m_pIE3CmdTarget->Exec(NULL, OLECMDID_PRINT,
  76. OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
  77. }
  78. else {
  79. fCurrentlyPrinting = TRUE;
  80. PrintTopics(action, ptoc, m_pCIExpContainer->m_pWebBrowserApp, GetHwnd());
  81. fCurrentlyPrinting = FALSE;
  82. }
  83. SetFocus(hWnd);
  84. }
  85. void PrintTopics(int action, CToc* ptoc, IWebBrowserAppImpl* pWebApp, HWND hWndHelp /* = NULL */)
  86. {
  87. ASSERT(pWebApp && pWebApp);
  88. if (ptoc == NULL || pWebApp == NULL)
  89. return;
  90. static BOOL fCurrentlyPrinting = FALSE;
  91. if (fCurrentlyPrinting) {
  92. MsgBox(IDS_PRINTING);
  93. return;
  94. }
  95. fCurrentlyPrinting = TRUE;
  96. CStr cszCurrentUrl;
  97. pWebApp->GetLocationURL(&cszCurrentUrl);
  98. CPrintHook ph(cszCurrentUrl, ptoc, hWndHelp);
  99. ph.BeginPrinting(action);
  100. fCurrentlyPrinting = FALSE;
  101. }
  102. /////////////////////////////////////////////////////////////////////////////
  103. // CPrintHook member functions
  104. CPrintHook::CPrintHook(PCSTR pszFirstUrl, CToc* pToc, HWND hWndHelp /* = NULL */)
  105. : m_pcp(NULL), m_dwCookie(0), m_ref(0), m_pToc(pToc), m_action(PRINT_CUR_TOPIC),
  106. m_hWndHelp(hWndHelp), m_phh(NULL), m_level(0),
  107. m_fFirstHeading(TRUE), m_fDestroyHelpWindow(FALSE), m_cszFirstUrl(pszFirstUrl),
  108. m_fIsIE3(FALSE), m_cszPrintFile("")
  109. {
  110. m_phh = pToc->m_phh;
  111. }
  112. BOOL CPrintHook::CreatePrintWindow(CStr* pcszUrl /* = NULL */)
  113. {
  114. BOOL bReturn = FALSE;
  115. HH_WINTYPE hhWinType;
  116. ZERO_STRUCTURE(hhWinType);
  117. hhWinType.cbStruct = sizeof(HH_WINTYPE);
  118. hhWinType.pszType = txtPrintWindow;
  119. hhWinType.pszCaption = GetStringResource(IDS_PRINT_CAPTION);
  120. hhWinType.rcWindowPos.left = 0;
  121. hhWinType.rcWindowPos.top = 0;
  122. hhWinType.rcWindowPos.right = 200;
  123. hhWinType.rcWindowPos.bottom = 200;
  124. hhWinType.dwStyles = WS_MINIMIZE;
  125. hhWinType.fsValidMembers = HHWIN_PARAM_RECT | HHWIN_PARAM_STYLES;
  126. xHtmlHelpA(NULL, NULL, HH_SET_WIN_TYPE, (DWORD_PTR) &hhWinType);
  127. m_hWndHelp = xHtmlHelpA(NULL, txtPrintWindow, HH_DISPLAY_TOPIC, (DWORD_PTR) (pcszUrl ? pcszUrl->psz : m_cszFirstUrl.psz));
  128. m_fDestroyHelpWindow = TRUE;
  129. if (m_hWndHelp != NULL)
  130. {
  131. StartAnimation(IDS_GATHERING_PRINTS, m_hWndHelp);
  132. m_phh = FindWindowIndex(m_hWndHelp);
  133. if (!m_fDestroyHelpWindow)
  134. m_phh->m_pCIExpContainer->m_pWebBrowserApp->Navigate((pcszUrl ? (PCSTR)*pcszUrl : (PCSTR)m_cszFirstUrl),
  135. NULL, NULL, NULL, NULL);
  136. // Set up the event sink for the WebBrowser control.
  137. LPCONNECTIONPOINTCONTAINER pcpc;
  138. HRESULT hr = m_phh->m_pCIExpContainer->m_pWebBrowserApp->m_lpDispatch->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pcpc);
  139. if (SUCCEEDED(hr))
  140. {
  141. // Try to find the connection point for DIID_DWebBrowserEvents2.
  142. // If that fails, try DIID_DWebBrowserEvents.
  143. hr = pcpc->FindConnectionPoint(DIID_DWebBrowserEvents2, &m_pcp);
  144. if (FAILED(hr))
  145. {
  146. m_fIsIE3 = TRUE;
  147. hr = pcpc->FindConnectionPoint(DIID_DWebBrowserEvents, &m_pcp);
  148. }
  149. pcpc->Release();
  150. if (SUCCEEDED(hr))
  151. {
  152. hr = m_pcp->Advise((LPUNKNOWN)(LPDISPATCH)this, &m_dwCookie);
  153. bReturn = TRUE;
  154. }
  155. }
  156. }
  157. return bReturn;
  158. }
  159. void CPrintHook::DestroyPrintWindow()
  160. {
  161. // Disconnect the event sink.
  162. if (m_pcp != NULL)
  163. {
  164. #ifdef _DEBUG
  165. HRESULT hr = m_pcp->Unadvise(m_dwCookie);
  166. ASSERT(SUCCEEDED(hr));
  167. #else
  168. m_pcp->Unadvise(m_dwCookie);
  169. #endif
  170. m_pcp->Release();
  171. m_pcp = NULL;
  172. }
  173. if (m_hWndHelp != NULL)
  174. {
  175. if (m_fDestroyHelpWindow)
  176. {
  177. DestroyWindow(m_hWndHelp);
  178. m_hWndHelp = NULL;
  179. }
  180. }
  181. DeleteFile(m_cszPrintFile);
  182. }
  183. CPrintHook::~CPrintHook()
  184. {
  185. DestroyPrintWindow();
  186. ASSERT(m_ref == 0);
  187. }
  188. // Generic OLE method implementations.
  189. STDMETHODIMP CPrintHook::QueryInterface(
  190. /* [in] */ REFIID riid,
  191. /* [iid_is][out] */ void **ppvObject)
  192. {
  193. if (DO_GUIDS_MATCH(riid, IID_IUnknown) ||
  194. DO_GUIDS_MATCH(riid, IID_IDispatch) ||
  195. DO_GUIDS_MATCH(riid, DIID_DWebBrowserEvents) ||
  196. DO_GUIDS_MATCH(riid, DIID_DWebBrowserEvents2))
  197. {
  198. *ppvObject = (LPVOID)this;
  199. AddRef();
  200. return S_OK;
  201. }
  202. else
  203. {
  204. *ppvObject = NULL;
  205. }
  206. return E_NOINTERFACE;
  207. }
  208. STDMETHODIMP_(ULONG) CPrintHook::AddRef(void)
  209. {
  210. return ++m_ref;
  211. }
  212. STDMETHODIMP_(ULONG) CPrintHook::Release(void)
  213. {
  214. return --m_ref;
  215. }
  216. // IDispatch method implementation.
  217. STDMETHODIMP CPrintHook::GetTypeInfoCount(
  218. /* [out] */ UINT *pctinfo)
  219. {
  220. return E_NOTIMPL;
  221. }
  222. STDMETHODIMP CPrintHook::GetTypeInfo(
  223. /* [in] */ UINT iTInfo,
  224. /* [in] */ LCID lcid,
  225. /* [out] */ ITypeInfo **ppTInfo)
  226. {
  227. // arg checking
  228. if (iTInfo != 0)
  229. return DISP_E_BADINDEX;
  230. if (!ppTInfo)
  231. return E_POINTER;
  232. *ppTInfo = NULL;
  233. return E_NOTIMPL;
  234. }
  235. STDMETHODIMP CPrintHook::GetIDsOfNames(
  236. /* [in] */ REFIID riid,
  237. /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
  238. /* [in] */ UINT cNames,
  239. /* [in] */ LCID lcid,
  240. /* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
  241. {
  242. return E_NOTIMPL;
  243. }
  244. STDMETHODIMP CPrintHook::Invoke(
  245. /* [in] */ DISPID dispIdMember,
  246. /* [in] */ REFIID riid,
  247. /* [in] */ LCID lcid,
  248. /* [in] */ WORD wFlags,
  249. /* [out][in] */ DISPPARAMS *pdispparams,
  250. /* [out] */ VARIANT *pVarResult,
  251. /* [out] */ EXCEPINFO *pExcepInfo,
  252. /* [out] */ UINT *puArgErr)
  253. {
  254. if (!DO_GUIDS_MATCH(riid, IID_NULL))
  255. return DISP_E_UNKNOWNINTERFACE;
  256. if (!(wFlags & DISPATCH_METHOD))
  257. return E_INVALIDARG;
  258. switch (dispIdMember)
  259. {
  260. case DISPID_BEFORENAVIGATE:
  261. DBWIN("DISPID_BEFORENAVIGATE\n");
  262. break;
  263. case DISPID_BEFORENAVIGATE2: // ie4 version.
  264. char szURL[MAX_URL];
  265. char szTFN[MAX_URL];
  266. char szHeaders[MAX_URL];
  267. WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[5].pvarVal->bstrVal, -1, szURL, sizeof(szURL), NULL, NULL);
  268. // 27-Sep-1997 [ralphw] IE 4 will send us a script command, followed
  269. // by a 1 then the current URL. We don't care about the current URL
  270. // in this case, so we nuke it.
  271. {
  272. PSTR pszCurUrl = StrChr(szURL, 1);
  273. if (pszCurUrl)
  274. *pszCurUrl = '\0';
  275. }
  276. szTFN[0] = 0;
  277. if( pdispparams->rgvarg[3].pvarVal->bstrVal )
  278. WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[3].pvarVal->bstrVal, -1, szTFN, sizeof(szTFN), NULL, NULL);
  279. szHeaders[0] = 0;
  280. if( pdispparams->rgvarg[1].pvarVal->bstrVal )
  281. WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[1].pvarVal->bstrVal, -1, szHeaders, sizeof(szHeaders), NULL, NULL);
  282. // OnBeforeNavigate(szURL, (long)pdispparams->rgvarg[4].pvarVal->lVal, szTFN,
  283. // pdispparams->rgvarg[2].pvarVal, szHeaders, (BOOL*)pdispparams->rgvarg[0].pboolVal );
  284. break;
  285. #if 0
  286. case DISPID_STATUSTEXTCHANGE:
  287. DBWIN("DISPID_STATUSTEXTCHANGE\n");
  288. break;
  289. case DISPID_DOWNLOADBEGIN:
  290. DBWIN("DISPID_DOWNLOADBEGIN\n");
  291. break;
  292. case DISPID_NEWWINDOW:
  293. DBWIN("DISPID_NEWWINDOW\n");
  294. break;
  295. case DISPID_WINDOWMOVE:
  296. DBWIN("DISPID_WINDOWMOVE\n");
  297. break;
  298. case DISPID_WINDOWRESIZE:
  299. DBWIN("DISPID_WINDOWRESIZE\n");
  300. break;
  301. case DISPID_WINDOWACTIVATE:
  302. DBWIN("DISPID_WINDOWACTIVATE\n");
  303. break;
  304. case DISPID_PROPERTYCHANGE:
  305. DBWIN("DISPID_PROPERTYCHANGE\n");
  306. break;
  307. case DISPID_TITLECHANGE:
  308. DBWIN("DISPID_TITLECHANGE\n");
  309. break;
  310. case DISPID_FRAMEBEFORENAVIGATE:
  311. DBWIN("DISPID_FRAMEBEFORENAVIGATE\n");
  312. break;
  313. case DISPID_FRAMENAVIGATECOMPLETE:
  314. DBWIN("DISPID_FRAMENAVIGATECOMPLETE\n");
  315. break;
  316. case DISPID_FRAMENEWWINDOW:
  317. DBWIN("DISPID_FRAMENEWWINDOW\n");
  318. break;
  319. case DISPID_NAVIGATECOMPLETE:
  320. DBWIN("DISPID_NAVIGATECOMPLETE\n");
  321. break;
  322. case DISPID_DOWNLOADCOMPLETE:
  323. DBWIN("DISPID_DOWNLOADCOMPLETE\n");
  324. break;
  325. case DISPID_DOCUMENTCOMPLETE:
  326. DBWIN("DISPID_DOCUMENTCOMPLETE\n");
  327. break;
  328. #endif
  329. case DISPID_PROGRESSCHANGE:
  330. ASSERT(pdispparams->cArgs == 2);
  331. DBWIN("DISPID_PROGRESSCHANGE\n");
  332. OnProgressChange(V_I4(&(pdispparams->rgvarg[1])), V_I4(&(pdispparams->rgvarg[0])));
  333. #if 1
  334. #ifdef _DEBUG
  335. char szDebug[80];
  336. wsprintf(szDebug, "ProgressChange(%li, %li)\n", V_I4(&(pdispparams->rgvarg[1])), V_I4(&(pdispparams->rgvarg[0])));
  337. DBWIN(szDebug);
  338. #endif
  339. #endif
  340. }
  341. return S_OK;
  342. }
  343. void CPrintHook::OnProgressChange(LONG lProgress, LONG lProgressMax)
  344. {
  345. if (lProgress == -1)
  346. {
  347. StopAnimation();
  348. // Print the page if it isn't a duplicate.
  349. if (m_fIsPrinting)
  350. {
  351. Print();
  352. DBWIN("Printing");
  353. }
  354. }
  355. else
  356. NextAnimation();
  357. }
  358. // This function allows the WebBrowser to handle its queued messages before continuing.
  359. BOOL CPrintHook::PumpMessages()
  360. {
  361. MSG msg;
  362. // Handle WebBrowser window messages
  363. while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  364. {
  365. if (!m_fIsPrinting)
  366. {
  367. if (m_phh && m_phh->m_pCIExpContainer && m_phh->m_pCIExpContainer->m_pWebBrowserApp)
  368. {
  369. m_phh->m_pCIExpContainer->m_pWebBrowserApp->Stop();
  370. }
  371. return FALSE;
  372. }
  373. if(!IsDialogMessage(m_hWndHelp, &msg))
  374. {
  375. TranslateMessage(&msg);
  376. DispatchMessage(&msg);
  377. }
  378. }
  379. return TRUE;
  380. }
  381. void CPrintHook::BeginPrinting(int action)
  382. {
  383. m_pos = 1;
  384. m_level = 0;
  385. m_action = action;
  386. m_fIsPrinting = TRUE;
  387. m_fFirstHeading = TRUE;
  388. SITEMAP_ENTRY* psme = NULL;
  389. TV_ITEM tvi;
  390. if (m_action == PRINT_CUR_TOPIC || m_action == PRINT_CUR_HEADING)
  391. {
  392. tvi.hItem = TreeView_GetSelection(m_pToc->m_hwndTree);
  393. if (!tvi.hItem)
  394. goto ExitBegin; // no current selection
  395. if (m_pToc->m_fBinaryTOC == FALSE)
  396. {
  397. tvi.mask = TVIF_PARAM;
  398. if (TreeView_GetItem(m_pToc->m_hwndTree, &tvi))
  399. psme = m_pToc->m_sitemap.GetSiteMapEntry((int)tvi.lParam);
  400. if (psme == NULL)
  401. goto ExitBegin;
  402. m_pos = (int)tvi.lParam;
  403. // Because the user may have selected a topic under a heading, but
  404. // wants to print all of the topics under that heading, we have to
  405. // search upward until we find the heading.
  406. if (m_action == PRINT_CUR_HEADING)
  407. {
  408. if (psme->fTopic || psme->cUrls <= 0)
  409. {
  410. while (psme != NULL && psme->fTopic && m_pos > 0)
  411. {
  412. psme = m_pToc->m_sitemap.GetSiteMapEntry(--m_pos);
  413. }
  414. }
  415. }
  416. // Set the current level for reference later. If the user just
  417. // wants to print the current topic, the level isn't significant.
  418. m_level = ((m_action == PRINT_CUR_TOPIC || psme == NULL) ? 0 : psme->level);
  419. }
  420. }
  421. if (m_pToc->m_fBinaryTOC == FALSE)
  422. {
  423. // If the user isn't printing all topics and psme is NULL,
  424. // see if this is just a single topic and, if so, print it.
  425. if (m_action != PRINT_CUR_ALL && psme == NULL)
  426. {
  427. // Get the original sitemap entry.
  428. m_pos = (int)tvi.lParam;
  429. psme = m_pToc->m_sitemap.GetSiteMapEntry(m_pos);
  430. // If there's a URL, print it.
  431. if (psme->cUrls > 0)
  432. {
  433. m_action = PRINT_CUR_TOPIC;
  434. }
  435. }
  436. }
  437. if (BuildPrintTable())
  438. {
  439. // We sit in this loop while printing because we don't want this
  440. // function to return until printing is complete.
  441. while (PumpMessages());
  442. DestroyPrintWindow();
  443. }
  444. ExitBegin:
  445. return;
  446. }
  447. BOOL CPrintHook::BuildPrintTable()
  448. {
  449. BOOL bReturn = FALSE;
  450. if (!m_fIsPrinting)
  451. return bReturn;
  452. CTable table;
  453. CStr cszCurUrl;
  454. if (m_pToc->m_fBinaryTOC)
  455. {
  456. switch (m_action)
  457. {
  458. case PRINT_CUR_TOPIC:
  459. m_pToc->m_phhctrl->m_pWebBrowserApp->GetLocationURL(&cszCurUrl);
  460. table.AddString((PCSTR)cszCurUrl);
  461. break;
  462. case PRINT_CUR_HEADING:
  463. TV_ITEM tvi;
  464. tvi.hItem = TreeView_GetSelection(m_pToc->m_hwndTree);
  465. if (!tvi.hItem)
  466. {
  467. m_pToc->m_phhctrl->m_pWebBrowserApp->GetLocationURL(&cszCurUrl);
  468. table.AddString((PCSTR)cszCurUrl);
  469. }
  470. else
  471. {
  472. tvi.mask = TVIF_PARAM;
  473. TreeView_GetItem(m_pToc->m_hwndTree, &tvi);
  474. CTreeNode *p = (CTreeNode *)tvi.lParam;
  475. CTreeNode *pParent = NULL;
  476. if (p->GetType() == TOPIC)
  477. {
  478. pParent = p->GetParent();
  479. }
  480. CHourGlass hour;
  481. m_phh->m_phmData->m_pTitleCollection->GetChildURLS((pParent ? pParent: p), &table);
  482. if (pParent)
  483. delete pParent;
  484. }
  485. break;
  486. case PRINT_CUR_ALL:
  487. if (!m_pToc->m_pBinTOCRoot)
  488. {
  489. m_pToc->m_phhctrl->m_pWebBrowserApp->GetLocationURL(&cszCurUrl);
  490. table.AddString((PCSTR)cszCurUrl);
  491. }
  492. else
  493. m_phh->m_phmData->m_pTitleCollection->GetChildURLS(m_pToc->m_pBinTOCRoot, &table); // oh my god they are printing the entire TOC
  494. break;
  495. }
  496. }
  497. else
  498. {
  499. // Get the next sitemap entry.
  500. // Print the sitemap entry URL if the its level is greater than
  501. // the saved level. If the sitemap entry is a heading at the same
  502. // level and contains a URL, proceed as well.
  503. for (SITEMAP_ENTRY* psme = m_pToc->m_sitemap.GetSiteMapEntry(m_pos);
  504. psme != NULL;
  505. psme = m_pToc->m_sitemap.GetSiteMapEntry(++m_pos))
  506. {
  507. if ((psme->level > m_level) ||
  508. (!psme->fTopic && psme->level == m_level && m_fFirstHeading))
  509. {
  510. // The top level heading could have a URL, so we
  511. // want to print it. However, we don't want to print
  512. // any other headings at that level, so set the
  513. // m_fFirstHeading flag to FALSE.
  514. if (m_action == PRINT_CUR_HEADING &&
  515. !psme->fTopic &&
  516. psme->level == m_level)
  517. {
  518. m_fFirstHeading = FALSE;
  519. }
  520. if (psme->cUrls > 0)
  521. {
  522. // Get the URL from the sitemap entry.
  523. LPCTSTR pszUrl = (psme->pUrls->urlPrimary ? psme->pUrls->urlPrimary : psme->pUrls->urlSecondary);
  524. CStr cszUrl(pszUrl);
  525. // Synchronize the TOC if we created the print window.
  526. if (m_fDestroyHelpWindow)
  527. m_pToc->Synchronize(cszUrl);
  528. // Truncate the strings at the # character if there is one.
  529. LPTSTR pszFind = StrChr(cszUrl, '#');
  530. if (pszFind != NULL)
  531. *pszFind = '\0';
  532. ConvertBackSlashToForwardSlash(cszUrl);
  533. if (table.IsStringInTable(cszUrl) == 0)
  534. table.AddString((PCSTR)cszUrl);
  535. if (m_action == PRINT_CUR_TOPIC)
  536. break;
  537. }
  538. }
  539. else
  540. break;
  541. }
  542. }
  543. if (m_pToc->m_phhctrl != NULL)
  544. {
  545. m_pToc->m_phhctrl->m_pWebBrowserApp->GetLocationURL(&cszCurUrl);
  546. m_hwndParent = m_pToc->m_phhctrl->m_hwndParent;
  547. }
  548. else if (m_pToc->m_fBinaryTOC)
  549. {
  550. cszCurUrl = m_phh->GetToc();
  551. m_hwndParent = m_phh->GetHwnd();
  552. }
  553. else
  554. {
  555. cszCurUrl = m_pToc->m_sitemap.GetSiteMapFile();
  556. if (m_phh)
  557. m_hwndParent = m_phh->GetHwnd();
  558. else
  559. m_hwndParent = m_hWndHelp;
  560. }
  561. if (ConstructFile((PCSTR)cszCurUrl, &table, &m_cszPrintFile))
  562. {
  563. bReturn = CreatePrintWindow(&m_cszPrintFile);
  564. }
  565. return bReturn;
  566. }
  567. static const char txtTmpPrefix[] = "~hh";
  568. static const char txtHtmlExtension[] = ".htm";
  569. static const char txtImg[] = "IMG";
  570. static const char txtSrc[] = "SRC";
  571. static const char txtLink[] = "LINK";
  572. static const char txtHREF[] = "HREF";
  573. static const char txtTagBeginBody[] = "BODY";
  574. static const char txtTagEndBody[] = "/BODY";
  575. static const char txtTagItAll[] = "</BODY></HTML>";
  576. static const char txtTmpPrintStinrg[] = "~hh%X.htm";
  577. static const char txtFrame[] = "FRAME";
  578. static const char txtBeginScript[] = "SCRIPT";
  579. static const char txtEndScript[] = "/SCRIPT";
  580. const int FILE_PAD = 16 * 1024;
  581. BOOL CPrintHook::ConstructFile(PCSTR pszCurrentUrl, CTable* pFileTable,
  582. CStr* pm_cszPrintFile)
  583. {
  584. char szTempPath[MAX_PATH];
  585. char szHtmlFile[MAX_PATH];
  586. char szThisURL[MAX_PATH];
  587. char szCurrentUrl[MAX_PATH];
  588. CProgress progress(GetStringResource(IDS_GATHERING_PRINTS),
  589. m_hwndParent, pFileTable->CountStrings() / 10, 10);
  590. strcpy(szCurrentUrl, pszCurrentUrl);
  591. PSTR pszFilePortion = (PSTR) FindFilePortion(szCurrentUrl);
  592. ASSERT(pszFilePortion);
  593. GetTempPath(sizeof(szHtmlFile), szHtmlFile);
  594. AddTrailingBackslash(szHtmlFile);
  595. wsprintf(szHtmlFile + strlen(szHtmlFile), txtTmpPrintStinrg, GetTickCount() & 0xFFFF);
  596. HFILE hfDst = _lcreat(szHtmlFile, 0);
  597. if (hfDst == HFILE_ERROR) {
  598. MsgBox(IDS_FILE_ERROR, szHtmlFile, MB_OK);
  599. return FALSE;
  600. }
  601. int endpos = pFileTable->CountStrings();
  602. PSTR pszMem = NULL;
  603. CStr cszTmpFile;
  604. for (int i = 1; i <= endpos; i++) {
  605. BOOL fSeenBody = FALSE;
  606. if (pszMem) {
  607. GlobalFree((HGLOBAL) pszMem);
  608. pszMem = NULL;
  609. }
  610. progress.Progress();
  611. ASSERT_COMMENT(pFileTable->CountStrings(), "Empty file list");
  612. PSTR pszFile;
  613. if (!StrChr(pFileTable->GetPointer(i), CH_COLON)) {
  614. if (*pFileTable->GetPointer(i) == '/' || *pFileTable->GetPointer(i) == '\\')
  615. {
  616. TranslateUrl(szCurrentUrl, pFileTable->GetPointer(i));
  617. }
  618. else
  619. {
  620. strcpy(pszFilePortion, pFileTable->GetPointer(i));
  621. }
  622. pszFile = szCurrentUrl;
  623. }
  624. else {
  625. pszFile = pFileTable->GetPointer(i);
  626. PSTR psz = stristr(pszFile, txtSysRoot);
  627. if (psz) {
  628. char szPath[MAX_PATH];
  629. GetRegWindowsDirectory(szPath);
  630. strcat(szPath, psz + strlen(txtSysRoot));
  631. cszTmpFile = szPath;
  632. pszFile = cszTmpFile.psz;
  633. }
  634. else if (IsCompiledHtmlFile(pszFile, &cszTmpFile)) {
  635. pszFile = cszTmpFile.psz;
  636. }
  637. }
  638. strcpy(szThisURL, pszFile);
  639. if (!ConvertToCacheFile(pszFile, szTempPath)) {
  640. // AuthorMsg(IDS_CANT_OPEN, pFileTable->GetPointer(i), m_hwndParent, NULL);
  641. continue;
  642. }
  643. int cbMem;
  644. UINT cbFile, cbFinalLen;
  645. PSTR psz, pszStart , pszTag;
  646. if ( IsCompiledURL(szTempPath ) ) {
  647. CStr cszCompiledName;
  648. PCSTR pszStream = GetCompiledName(szTempPath, &cszCompiledName);
  649. if (pszStream == NULL)
  650. continue;
  651. // BUGBUG: should use existing file system handle if available
  652. CFSClient fs;
  653. if (!fs.Initialize(cszCompiledName)) {
  654. MsgBox(IDS_FILE_ERROR, pFileTable->GetPointer(i), MB_OK);
  655. continue;
  656. }
  657. if (FAILED(fs.OpenStream(pszStream))) {
  658. // AuthorMsg(IDS_CANT_OPEN, pFileTable->GetPointer(i), m_hwndParent, NULL);
  659. continue;
  660. }
  661. cbFile = fs.SeekSub(0, SK_END);
  662. cbFinalLen = cbFile;
  663. fs.SeekSub(0, SK_SET);
  664. cbMem = cbFile + FILE_PAD;
  665. pszMem = (PSTR) GlobalAlloc(GMEM_FIXED, cbMem);
  666. ASSERT(pszMem);
  667. if (!pszMem) {
  668. GlobalFree((HGLOBAL) pszMem);
  669. fs.CloseStream();
  670. continue;
  671. }
  672. if (FAILED(fs.Read((PBYTE) pszMem, cbFile))) {
  673. fs.CloseStream();
  674. continue;
  675. }
  676. fs.CloseStream();
  677. }
  678. else {
  679. HANDLE hf = CreateFile(szTempPath, GENERIC_READ, FILE_SHARE_READ,
  680. NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  681. if (hf == INVALID_HANDLE_VALUE)
  682. goto BadFile;
  683. ASSERT(hf);
  684. cbFile = GetFileSize(hf, NULL);
  685. cbFinalLen = cbFile;
  686. cbMem = cbFile + FILE_PAD;
  687. pszMem = (PSTR) GlobalAlloc(GMEM_FIXED, cbMem);
  688. ASSERT(pszMem);
  689. if (!pszMem) {
  690. GlobalFree((HGLOBAL) pszMem);
  691. CloseHandle(hf);
  692. continue; // next HTML file might be smaller, so try again
  693. }
  694. DWORD cbRead;
  695. if (!ReadFile(hf, pszMem, cbFile, &cbRead, NULL) || cbRead != cbFile) {
  696. CloseHandle(hf);
  697. continue;
  698. }
  699. CloseHandle(hf);
  700. }
  701. pszMem[cbFile] = '\0';
  702. psz = pszMem;
  703. pszStart = psz;
  704. pszTag = psz;
  705. while ((pszTag = StrChr(pszTag, '<'))) {
  706. pszTag = FirstNonSpace(pszTag + 1);
  707. if (IsSamePrefix(pszTag, txtTagEndBody, sizeof(txtTagEndBody) - 1)) {
  708. while (*pszTag != '<') // back up to the angle bracket
  709. pszTag--;
  710. cbFile = (int)(pszTag - pszStart);
  711. break;
  712. }
  713. else if (IsSamePrefix(pszTag, txtBeginScript, sizeof(txtBeginScript) - 1)) {
  714. // skip to end tag
  715. while ((pszTag = StrChr(pszTag, '<'))) {
  716. pszTag = FirstNonSpace(pszTag + 1);
  717. if (IsSamePrefix(pszTag, txtEndScript, sizeof(txtEndScript) - 1))
  718. break;
  719. }
  720. }
  721. else if (IsSamePrefix(pszTag, txtTagBeginBody, sizeof(txtTagBeginBody) - 1)) {
  722. // If this isn't the first HTML file, then we ignore everything
  723. // up to the body tag
  724. if (i > 1 && !fSeenBody) {
  725. fSeenBody = TRUE;
  726. pszStart = StrChr(pszTag, '>');
  727. if (!pszStart) {
  728. AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL);
  729. goto BadFile;
  730. }
  731. pszStart++;
  732. cbFile -= (int)(pszStart - pszMem);
  733. }
  734. }
  735. else if (IsSamePrefix(pszTag, txtImg, sizeof(txtImg) - 1)) {
  736. // Change the URL for images to be a full path -- this lets
  737. // the browser pull it in without us having to copy it
  738. // anywhere.
  739. pszTag += sizeof(txtImg) - 1;
  740. for(;;) {
  741. while (*pszTag != ' ' && *pszTag != '>') {
  742. if (*pszTag == CH_QUOTE) {
  743. pszTag = StrChr(pszTag + 1, CH_QUOTE);
  744. if (!pszTag) {
  745. AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL);
  746. goto BadFile;
  747. }
  748. }
  749. pszTag++;
  750. }
  751. if (*pszTag == '>')
  752. goto NoSrcTag;
  753. pszTag++;
  754. if (IsSamePrefix(pszTag, txtSrc, sizeof(txtSrc) - 1))
  755. break;
  756. pszTag++;
  757. }
  758. ASSERT(IsSamePrefix(pszTag, txtSrc, sizeof(txtSrc) - 1));
  759. pszTag = StrChr(pszTag, '=');
  760. if (!pszTag) {
  761. AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL);
  762. goto BadFile;
  763. }
  764. pszTag = FirstNonSpace(pszTag + 1);
  765. char chSearch;
  766. if (*pszTag == CH_QUOTE) {
  767. chSearch = CH_QUOTE;
  768. pszTag = FirstNonSpace(pszTag + 1);
  769. }
  770. else
  771. chSearch = ' ';
  772. PSTR pszBeginUrl = pszTag;
  773. pszTag = StrChr(pszTag + 1, chSearch);
  774. if (!pszTag) {
  775. AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL);
  776. goto BadFile;
  777. }
  778. char chSave = *pszTag;
  779. *pszTag = '\0';
  780. if (!StrChr(pszBeginUrl, CH_COLON)) {
  781. // This makes it relative to the original HTML file,
  782. // but not necessarily relative to the current file
  783. CStr cszCompiledName;
  784. char fname[_MAX_FNAME]="";
  785. int diff=0;
  786. PSTR pszBeginFile='\0';
  787. strcpy(szTempPath, szThisURL);
  788. if ( IsCompiledURL(szTempPath ) )
  789. { // a compiled URL with an image in it.
  790. PCSTR pszStream = GetCompiledName(szTempPath, &cszCompiledName);
  791. SplitPath(pszStream, NULL, NULL, fname, NULL);
  792. pszBeginFile = stristr(szTempPath, fname);
  793. ASSERT( pszBeginFile );
  794. diff = (int)(strlen(szThisURL) - strlen(pszBeginFile));
  795. }else
  796. { // non-compiled URL; an html file with and image in it
  797. pszBeginFile = strrchr(szTempPath, '/');
  798. ASSERT(pszBeginFile);
  799. diff = (int)(pszBeginFile - szTempPath) + 1;
  800. }
  801. cbFile += diff;
  802. cbFinalLen += diff;
  803. while (cbFinalLen > (UINT) cbMem) {
  804. int StartDiff = (int)(pszStart - pszMem);
  805. int TagDiff = (int)(pszTag - pszMem);
  806. int BeginDiff = (int)(pszBeginUrl - pszMem);
  807. PSTR pszNew = (PSTR) GlobalReAlloc((HGLOBAL) pszMem, cbMem += FILE_PAD, GMEM_MOVEABLE);
  808. ASSERT(pszNew);
  809. if (!pszNew) {
  810. GlobalFree((HGLOBAL) pszMem);
  811. MsgBox(IDS_OOM);
  812. _lclose(hfDst);
  813. DeleteFile(szHtmlFile);
  814. if (pszMem) {
  815. GlobalFree((HGLOBAL) pszMem);
  816. pszMem = NULL;
  817. }
  818. return FALSE;
  819. }
  820. pszMem = pszNew;
  821. pszStart = pszMem + StartDiff;
  822. pszTag = pszMem + TagDiff;
  823. pszBeginUrl = pszMem + BeginDiff;
  824. }
  825. MoveMemory(pszTag + diff, pszTag, cbFinalLen - (pszTag - pszMem) - diff);
  826. if ( !IsCompiledURL(szTempPath) )
  827. {
  828. strcpy(pszBeginFile, "/");
  829. pszBeginFile ++; // pointing at the NULL
  830. }
  831. strcpy(pszBeginFile, pszBeginUrl);
  832. strcpy( pszBeginUrl, szTempPath);
  833. pszTag += diff;
  834. *pszTag = chSave;
  835. }
  836. else
  837. *pszTag = chSave;
  838. }
  839. else if (IsSamePrefix(pszTag, txtLink, sizeof(txtLink) - 1)) {
  840. // Change the URL for CSS to be a full path -- this lets
  841. // the browser pull it in without us having to copy it
  842. // anywhere.
  843. pszTag += sizeof(txtImg) - 1;
  844. for(;;) {
  845. while (*pszTag != ' ' && *pszTag != '>') {
  846. if (*pszTag == CH_QUOTE) {
  847. pszTag = StrChr(pszTag + 1, CH_QUOTE);
  848. if (!pszTag) {
  849. AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL);
  850. goto BadFile;
  851. }
  852. }
  853. pszTag++;
  854. }
  855. if (*pszTag == '>')
  856. goto NoSrcTag;
  857. pszTag++;
  858. if (IsSamePrefix(pszTag, txtHREF, sizeof(txtHREF) - 1))
  859. break;
  860. pszTag++;
  861. }
  862. ASSERT(IsSamePrefix(pszTag, txtHREF, sizeof(txtHREF) - 1));
  863. pszTag = StrChr(pszTag, '=');
  864. if (!pszTag) {
  865. AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL);
  866. goto BadFile;
  867. }
  868. pszTag = FirstNonSpace(pszTag + 1);
  869. char chSearch;
  870. if (*pszTag == CH_QUOTE) {
  871. chSearch = CH_QUOTE;
  872. pszTag = FirstNonSpace(pszTag + 1);
  873. }
  874. else
  875. chSearch = ' ';
  876. PSTR pszBeginUrl = pszTag;
  877. pszTag = StrChr(pszTag + 1, chSearch);
  878. if (!pszTag) {
  879. AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL);
  880. goto BadFile;
  881. }
  882. char chSave = *pszTag;
  883. *pszTag = '\0';
  884. char szScratch[MAX_URL];
  885. if (!StrChr(pszBeginUrl, CH_COLON)) {
  886. // BUGBUG: This makes it relative to the original HTML file,
  887. // but not necessarily relative to the current file
  888. strcpy(pszFilePortion, pszBeginUrl);
  889. strcpy(szScratch, szCurrentUrl);
  890. }
  891. else
  892. {
  893. // qualify .CHM filespec which will look like: MK@MSITStore:foo.chm::/bar.css
  894. //
  895. CExCollection* pCollection;
  896. CExTitle* pTitle;
  897. HRESULT hr;
  898. if ( (pCollection = GetCurrentCollection(NULL, pszBeginUrl)) )
  899. {
  900. if ( SUCCEEDED(hr = pCollection->URL2ExTitle( pszBeginUrl, &pTitle )) && pTitle )
  901. {
  902. const char* pszPathName;
  903. char* psz;
  904. lstrcpy(szScratch, pszBeginUrl);
  905. if ( (pszPathName = pTitle->GetPathName()) )
  906. {
  907. if ( (psz = StrChr(szScratch, CH_COLON)) )
  908. {
  909. ++psz;
  910. strcpy(psz, pszPathName);
  911. if ( (psz = StrStr(pszBeginUrl, "::")) )
  912. strcat(szScratch, psz);
  913. }
  914. }
  915. }
  916. }
  917. }
  918. int diff = (int)(strlen(szScratch) - strlen(pszBeginUrl));
  919. cbFile += diff;
  920. cbFinalLen += diff;
  921. while (cbFinalLen >= (UINT) cbMem) {
  922. int StartDiff = (int)(pszStart - pszMem);
  923. int TagDiff = (int)(pszTag - pszMem);
  924. int BeginDiff = (int)(pszBeginUrl - pszMem);
  925. PSTR pszNew = (PSTR) GlobalReAlloc((HGLOBAL) pszMem, cbMem += FILE_PAD, GMEM_MOVEABLE);
  926. ASSERT(pszNew);
  927. if (!pszNew) {
  928. GlobalFree((HGLOBAL) pszMem);
  929. MsgBox(IDS_OOM);
  930. _lclose(hfDst);
  931. DeleteFile(szHtmlFile);
  932. if (pszMem) {
  933. GlobalFree((HGLOBAL) pszMem);
  934. pszMem = NULL;
  935. }
  936. return FALSE;
  937. }
  938. pszMem = pszNew;
  939. pszStart = pszMem + StartDiff;
  940. pszTag = pszMem + TagDiff;
  941. pszBeginUrl = pszMem + BeginDiff;
  942. }
  943. MoveMemory(pszTag + diff, pszTag, cbFinalLen - (pszTag - pszMem) - diff);
  944. strcpy(pszBeginUrl, szScratch);
  945. pszTag += diff;
  946. *pszTag = chSave;
  947. }
  948. else if (IsSamePrefix(pszTag, txtFrame, sizeof(txtFrame) - 1)) {
  949. MsgBox(IDS_CANT_PRINT_FRAMESET);
  950. _lclose(hfDst);
  951. DeleteFile(szHtmlFile);
  952. if (pszMem) {
  953. GlobalFree((HGLOBAL) pszMem);
  954. pszMem = NULL;
  955. }
  956. return FALSE;
  957. }
  958. NoSrcTag:
  959. pszTag++; // skip over the '<'
  960. }
  961. if (_lwrite(hfDst, pszStart, cbFile) != cbFile) {
  962. MsgBox(IDS_INSUFFICIENT_SPACE, szHtmlFile, MB_OK);
  963. _lclose(hfDst);
  964. DeleteFile(szHtmlFile);
  965. }
  966. BadFile:
  967. continue;
  968. }
  969. if (pszMem) {
  970. GlobalFree((HGLOBAL) pszMem);
  971. pszMem = NULL;
  972. }
  973. _lclose(hfDst);
  974. *pm_cszPrintFile = szHtmlFile;
  975. return TRUE;
  976. #if 0
  977. BOOL bReturn = (GetSystemDirectory(m_szPrintFile, _MAX_PATH) > 0);
  978. if (bReturn)
  979. {
  980. StrCat(m_szPrintFile, "\\hhtest.htm");
  981. *pm_cszPrintFile = m_szPrintFile;
  982. HANDLE hFile = CreateFile(m_szPrintFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  983. if (hFile != INVALID_HANDLE_VALUE)
  984. {
  985. DWORD dwBytesWritten = 0;
  986. TCHAR szOpenHTML[] = "<HTML>\r\n<BODY>\r\n" \
  987. "<H2>Printing is not currently implemented.</H2>\r\n" \
  988. "<P></P>\r\n" \
  989. "<B>Here is the list of files that you asked to print:</B>\r\n"
  990. "<P></P>\r\n";
  991. WriteFile(hFile, (LPCVOID)szOpenHTML, strlen(szOpenHTML) * sizeof(TCHAR), &dwBytesWritten, NULL);
  992. TCHAR szFile[_MAX_PATH], szFileHTML[_MAX_PATH * 2];
  993. pFileTable->SetPosition();
  994. while (pFileTable->GetString(szFile))
  995. {
  996. wsprintf(szFileHTML, "%s <BR>\r\n", szFile);
  997. WriteFile(hFile, (LPCVOID)szFileHTML, strlen(szFileHTML) * sizeof(TCHAR), &dwBytesWritten, NULL);
  998. }
  999. TCHAR szCloseHTML[] = "<P></P>\r\n" \
  1000. "</BODY>\r\n</HTML>\r\n";
  1001. WriteFile(hFile, (LPCVOID)szCloseHTML, strlen(szCloseHTML) * sizeof(TCHAR), &dwBytesWritten, NULL);
  1002. CloseHandle(hFile);
  1003. }
  1004. else
  1005. bReturn = FALSE;
  1006. }
  1007. return bReturn;
  1008. #endif
  1009. }
  1010. BOOL CPrintHook::TranslateUrl(PSTR pszFullUrl, PSTR pszRelUrl)
  1011. {
  1012. BOOL bReturn;
  1013. URL_COMPONENTS uc;
  1014. ZERO_STRUCTURE(uc);
  1015. uc.dwStructSize = sizeof(URL_COMPONENTS);
  1016. uc.dwSchemeLength = 1;
  1017. uc.nScheme = INTERNET_SCHEME_DEFAULT ;
  1018. uc.dwHostNameLength = 1;
  1019. uc.dwUserNameLength = 1;
  1020. uc.dwPasswordLength = 1;
  1021. uc.dwUrlPathLength = 1;
  1022. uc.dwExtraInfoLength = 1;
  1023. if ((bReturn = InternetCrackUrl(pszFullUrl, 0, 0, &uc)))
  1024. {
  1025. uc.lpszUrlPath = pszRelUrl;
  1026. uc.dwUrlPathLength = 0;
  1027. // Make a copy of uc.lpszExtraInfo because it will
  1028. // be lost when InternetCreateUrl() modifies pszFullUrl.
  1029. CStr cszExtraInfo(uc.lpszExtraInfo);
  1030. uc.lpszExtraInfo = (PSTR)cszExtraInfo;
  1031. uc.dwExtraInfoLength = 0;
  1032. DWORD dwBufLen = MAX_PATH;
  1033. bReturn = InternetCreateUrl(&uc, 0, pszFullUrl, &dwBufLen);
  1034. }
  1035. return bReturn;
  1036. }
  1037. // This function just tells the WebBrowser to print the current page.
  1038. HRESULT CPrintHook::Print()
  1039. {
  1040. // Change the cursor to an hourglass.
  1041. SetClassLongPtr(m_hWndHelp, GCLP_HCURSOR, (LONG_PTR)LoadCursor(NULL, (LPCTSTR) IDC_WAIT));
  1042. HRESULT hr = E_FAIL;
  1043. HRESULT hrCancelled = (m_fIsIE3 ? 0x80040100 : 0x80040104);
  1044. LPOLECOMMANDTARGET lpOleCommandTarget = m_phh->m_pCIExpContainer->m_pIE3CmdTarget;
  1045. ASSERT(lpOleCommandTarget);
  1046. if (lpOleCommandTarget != NULL)
  1047. {
  1048. // Give printing 10 tries and then bail out if it doesn't work.
  1049. for (USHORT i = 0; i < 10 && FAILED(hr); i++)
  1050. {
  1051. if (!PumpMessages())
  1052. break;
  1053. #ifdef _DEBUG
  1054. try
  1055. {
  1056. #endif
  1057. // Call the Exec() function to print the currently displayed page.
  1058. if (m_fIsIE3)
  1059. {
  1060. hr = lpOleCommandTarget->Exec(NULL,OLECMDID_PRINT,
  1061. OLECMDEXECOPT_PROMPTUSER,
  1062. NULL, NULL);
  1063. }
  1064. else
  1065. {
  1066. hr = lpOleCommandTarget->Exec(&CGID_MSHTML,IDM_PRINT,
  1067. MSOCMDEXECOPT_PROMPTUSER,
  1068. NULL, NULL);
  1069. }
  1070. #ifdef _DEBUG
  1071. TCHAR szDebug[40];
  1072. wsprintf(szDebug, "m_pos == %i, hr == %lx", m_pos, hr);
  1073. DBWIN(szDebug);
  1074. #endif
  1075. #ifdef _DEBUG
  1076. }
  1077. catch(...)
  1078. {
  1079. ASSERT_COMMENT(TRUE, "An exception occurred when printing. " \
  1080. "Please send email to randyfe or ralphw.");
  1081. hr = E_FAIL;
  1082. }
  1083. #endif
  1084. // On IE 4, wait for printing to finish before continuing.
  1085. if (!m_fIsIE3)
  1086. {
  1087. OLECMD olecmd;
  1088. olecmd.cmdID = IDM_PRINTQUERYJOBSPENDING;
  1089. do
  1090. {
  1091. DBWIN("Waiting for printing to finish...");
  1092. olecmd.cmdf = 0;
  1093. #ifdef _DEBUG
  1094. try
  1095. {
  1096. #else
  1097. if (m_phh && m_phh->m_pCIExpContainer && m_phh->m_pCIExpContainer->m_pIE3CmdTarget)
  1098. #endif
  1099. m_phh->m_pCIExpContainer->m_pIE3CmdTarget->QueryStatus(&CGID_MSHTML, 1, &olecmd, NULL);
  1100. #ifdef _DEBUG
  1101. }
  1102. catch(...)
  1103. {
  1104. ASSERT_COMMENT(TRUE, "An exception occurred when waiting for printing to finish. " \
  1105. "Please send email to randyfe or ralphw.");
  1106. break;
  1107. }
  1108. #endif
  1109. PumpMessages();
  1110. }
  1111. while (olecmd.cmdf & OLECMDF_ENABLED);
  1112. }
  1113. if (hr == hrCancelled)
  1114. break;
  1115. }
  1116. }
  1117. m_fIsPrinting = FALSE;
  1118. // Change the cursor back to an arrow.
  1119. SetClassLongPtr(m_hWndHelp, GCLP_HCURSOR, (LONG_PTR)LoadCursor(NULL, (LPCTSTR) IDC_ARROW));
  1120. #ifdef _DEBUG
  1121. TCHAR szDebug[50];
  1122. wsprintf(szDebug, "Print complete... hr == %lx", hr);
  1123. DBWIN(szDebug);
  1124. #endif
  1125. return hr;
  1126. }
  1127. STATIC INT_PTR CALLBACK ProgressDialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  1128. const int DEFAULT_WIDTH = 200;
  1129. const int DEFAULT_HEIGHT = 50;
  1130. CProgress::CProgress(PCSTR pszCaption, HWND hwndCallersParent, int cSteps,
  1131. int cHowOften)
  1132. {
  1133. cProgress = -1;
  1134. steps = cSteps;
  1135. cFrequency = cHowOften;
  1136. pszTitle = lcStrDup(pszCaption);
  1137. fWindowCreationFailed = FALSE;
  1138. hwndProgress = NULL;
  1139. hwndParent = hwndCallersParent;
  1140. hwndFrame = NULL;
  1141. dwStartTime = GetTickCount();
  1142. counter = 0;
  1143. }
  1144. CProgress::~CProgress()
  1145. {
  1146. if (hwndFrame && IsWindow(hwndFrame))
  1147. DestroyWindow(hwndFrame);
  1148. lcFree(pszTitle);
  1149. }
  1150. void CProgress::Progress() {
  1151. if (++counter == cFrequency) {
  1152. counter = 0;
  1153. if (hwndProgress)
  1154. SendMessage(hwndProgress, PBM_STEPIT, 0, 0);
  1155. else {
  1156. cProgress++;
  1157. if (GetTickCount() - dwStartTime >= 1500)
  1158. CreateTheWindow();
  1159. }
  1160. }
  1161. }
  1162. void CProgress::CreateTheWindow(void)
  1163. {
  1164. if (fWindowCreationFailed)
  1165. return; // couldn't create the window
  1166. if (!hwndParent) {
  1167. CPalDC dc(SCREEN_IC);
  1168. rc.left = dc.GetDeviceWidth() - (DEFAULT_WIDTH / 2);
  1169. rc.top = dc.GetDeviceHeight() - (DEFAULT_HEIGHT / 2);
  1170. }
  1171. else {
  1172. RECT rcParent;
  1173. GetWindowRect(hwndParent, &rcParent);
  1174. rc.left = (RECT_WIDTH(rcParent) / 2) - (DEFAULT_WIDTH / 2);
  1175. rc.top = (RECT_HEIGHT(rcParent) / 2) - (DEFAULT_HEIGHT / 2);
  1176. }
  1177. hwndFrame = CreateDialog(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDDLG_PROGRESS),
  1178. hwndParent, ProgressDialogProc);
  1179. if (!hwndFrame) {
  1180. fWindowCreationFailed = TRUE;
  1181. return;
  1182. }
  1183. RECT rcFrame;
  1184. GetWindowRect(hwndFrame, &rcFrame);
  1185. MoveWindow(hwndFrame, rcFrame.left, rc.top, RECT_WIDTH(rcFrame),
  1186. RECT_HEIGHT(rcFrame), FALSE);
  1187. hwndProgress = GetDlgItem(hwndFrame, ID_PROGRESS);
  1188. if (steps > 0) {
  1189. SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, steps));
  1190. SendMessage(hwndProgress, PBM_SETSTEP, (WPARAM) 1, 0);
  1191. }
  1192. SetWindowText(hwndFrame, pszTitle);
  1193. while (cProgress-- >= 0)
  1194. SendMessage(hwndProgress, PBM_STEPIT, 0, 0);
  1195. ShowWindow(hwndFrame, SW_SHOW);
  1196. }
  1197. STATIC INT_PTR CALLBACK ProgressDialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1198. {
  1199. if (msg == WM_INITDIALOG)
  1200. return TRUE;
  1201. else
  1202. return FALSE;
  1203. }