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.

610 lines
16 KiB

  1. /*****************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 2000
  4. *
  5. * TITLE: status.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: RickTu
  10. *
  11. * DATE: 11/7/00
  12. *
  13. * DESCRIPTION: Implements code for the printing status page of the
  14. * print photos wizard...
  15. *
  16. *****************************************************************************/
  17. #include <precomp.h>
  18. #pragma hdrstop
  19. BOOL g_bCancelPrintJob = FALSE;
  20. /*****************************************************************************
  21. PhotoPrintAbortProc
  22. Called by GDI to see if the print job should be canceled.
  23. *****************************************************************************/
  24. BOOL CALLBACK PhotoPrintAbortProc( HDC hDC, INT iError )
  25. {
  26. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_STATUS, TEXT("PhotoPrintAbortProc(0x%x, %d)"),hDC,iError));
  27. #ifdef DEBUG
  28. if (g_bCancelPrintJob)
  29. {
  30. WIA_TRACE((TEXT("PhotoPrintAbortProc: attempting to cancel print job...")))
  31. }
  32. #endif
  33. return (!g_bCancelPrintJob);
  34. }
  35. /*****************************************************************************
  36. CStatusPage -- constructor/desctructor
  37. <Notes>
  38. *****************************************************************************/
  39. CStatusPage::CStatusPage( CWizardInfoBlob * pBlob )
  40. : _hDlg(NULL),
  41. _hWorkerThread(NULL),
  42. _dwWorkerThreadId(0)
  43. {
  44. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_STATUS, TEXT("CStatusPage::CStatusPage()")));
  45. _pWizInfo = pBlob;
  46. _pWizInfo->AddRef();
  47. //
  48. // Create worker thread
  49. //
  50. _hWorkerThread = CreateThread( NULL,
  51. 0,
  52. CStatusPage::s_StatusWorkerThreadProc,
  53. (LPVOID)this,
  54. CREATE_SUSPENDED,
  55. &_dwWorkerThreadId );
  56. //
  57. // If we created the thread, set it's priority to slight below normal so other
  58. // things run okay. This can be a CPU intensive task...
  59. //
  60. if (_hWorkerThread)
  61. {
  62. SetThreadPriority( _hWorkerThread, THREAD_PRIORITY_BELOW_NORMAL );
  63. ResumeThread( _hWorkerThread );
  64. }
  65. }
  66. CStatusPage::~CStatusPage()
  67. {
  68. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_STATUS, TEXT("CStatusPage::~CStatusPage()")));
  69. if (_pWizInfo)
  70. {
  71. _pWizInfo->Release();
  72. _pWizInfo = NULL;
  73. }
  74. }
  75. VOID CStatusPage::ShutDownBackgroundThreads()
  76. {
  77. //
  78. // Shutdown the background thread...
  79. //
  80. _OnDestroy();
  81. //
  82. // Signify that we've shutdown our threads...
  83. //
  84. if (_pWizInfo)
  85. {
  86. _pWizInfo->StatusIsShutDown();
  87. }
  88. }
  89. /*****************************************************************************
  90. CStatusPage::_DoHandleThreadMessage
  91. Depending on the message received, does the work for the given message...
  92. *****************************************************************************/
  93. VOID CStatusPage::_DoHandleThreadMessage( LPMSG pMSG )
  94. {
  95. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_STATUS, TEXT("CStatusPage::_DoHandleThreadMessage()")));
  96. if (!pMSG)
  97. {
  98. WIA_ERROR((TEXT("pMSG is NULL, returning early!")));
  99. return;
  100. }
  101. switch (pMSG->message)
  102. {
  103. case PP_STATUS_PRINT:
  104. WIA_TRACE((TEXT("Got PP_STATUS_PRINT message")));
  105. if (_pWizInfo)
  106. {
  107. BOOL bDeleteDC = FALSE;
  108. //
  109. // Create an hDC for the printer...
  110. //
  111. HDC hDC = _pWizInfo->GetCachedPrinterDC();
  112. if (!hDC)
  113. {
  114. hDC = CreateDC( TEXT("WINSPOOL"), _pWizInfo->GetPrinterToUse(), NULL, _pWizInfo->GetDevModeToUse() );
  115. bDeleteDC = TRUE;
  116. }
  117. if (hDC)
  118. {
  119. DOCINFO di = {0};
  120. BOOL bCancel = FALSE;
  121. HWND hwndProgress = GetDlgItem( _hDlg, IDC_PRINT_PROGRESS );
  122. //
  123. // Set the progress meter to 0
  124. //
  125. if (hwndProgress)
  126. {
  127. PostMessage( hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0,100) );
  128. PostMessage( hwndProgress, PBM_SETPOS, 0, 0 );
  129. }
  130. //
  131. // turn on ICM for this hDC
  132. //
  133. SetICMMode( hDC, ICM_ON );
  134. di.cbSize = sizeof(DOCINFO);
  135. //
  136. // Lets use the template name for the document name...
  137. //
  138. CSimpleString strTitle;
  139. CTemplateInfo * pTemplateInfo = NULL;
  140. if (SUCCEEDED(_pWizInfo->GetTemplateByIndex( _pWizInfo->GetCurrentTemplateIndex() ,&pTemplateInfo)) && pTemplateInfo)
  141. {
  142. pTemplateInfo->GetTitle( &strTitle );
  143. }
  144. //
  145. // Let's remove the ':' at the end if there is one
  146. //
  147. INT iLen = strTitle.Length();
  148. if (iLen && (strTitle[(INT)iLen-1] == TEXT(':')))
  149. {
  150. strTitle.Truncate(iLen);
  151. }
  152. di.lpszDocName = strTitle;
  153. if (!_pWizInfo->IsWizardShuttingDown())
  154. {
  155. if (StartDoc( hDC, &di ) > 0)
  156. {
  157. HRESULT hr;
  158. INT iPageCount = 0;
  159. float fPercent = 0.0;
  160. MSG msg;
  161. g_bCancelPrintJob = FALSE;
  162. //
  163. // Set the abort proc...
  164. //
  165. if (SP_ERROR == SetAbortProc( hDC, PhotoPrintAbortProc ))
  166. {
  167. WIA_ERROR((TEXT("Got SP_ERROR trying to set AbortProc!")));
  168. }
  169. //
  170. // Loop through until we've printed all the photos...
  171. //
  172. if (SUCCEEDED(hr = _pWizInfo->GetCountOfPrintedPages( _pWizInfo->GetCurrentTemplateIndex(), &iPageCount )))
  173. {
  174. float fPageCount = (float)iPageCount;
  175. for (INT iPage = 0; !g_bCancelPrintJob && (iPage < iPageCount); iPage++)
  176. {
  177. //
  178. // Set which page we are on...
  179. //
  180. PostMessage( _hDlg, SP_MSG_UPDATE_PROGRESS_TEXT, (WPARAM)(iPage+1), (LPARAM)iPageCount );
  181. //
  182. // Print the page...
  183. //
  184. if (StartPage( hDC ) > 0)
  185. {
  186. //
  187. // Ensure that ICM mode stays on. Per MSDN docs
  188. // ICM mode gets reset after each StartPage call.
  189. //
  190. SetICMMode( hDC, ICM_ON );
  191. hr = _pWizInfo->RenderPrintedPage( _pWizInfo->GetCurrentTemplateIndex(), iPage, hDC, hwndProgress, (float)((float)100.0 / fPageCount), &fPercent );
  192. if ((hr != S_OK) && (hr != S_FALSE))
  193. {
  194. g_bCancelPrintJob = TRUE;
  195. }
  196. EndPage( hDC );
  197. }
  198. else
  199. {
  200. _pWizInfo->ShowError( _hDlg, HRESULT_FROM_WIN32(GetLastError()), IDS_ERROR_WHILE_PRINTING );
  201. WIA_ERROR((TEXT("PrintThread: StartPage failed w/GLE=%d"),GetLastError()));
  202. g_bCancelPrintJob = TRUE;
  203. }
  204. if (_pWizInfo->IsWizardShuttingDown())
  205. {
  206. g_bCancelPrintJob = TRUE;
  207. }
  208. }
  209. }
  210. }
  211. else
  212. {
  213. _pWizInfo->ShowError( _hDlg, HRESULT_FROM_WIN32(GetLastError()), IDS_ERROR_WHILE_PRINTING );
  214. WIA_ERROR((TEXT("PrintThread: StartDoc failed w/GLE = %d"),GetLastError()));
  215. g_bCancelPrintJob = TRUE;
  216. }
  217. }
  218. INT iOffset = -1;
  219. if (g_bCancelPrintJob)
  220. {
  221. //
  222. // If there was an error, or the job was cancelled, then abort it...
  223. //
  224. AbortDoc( hDC );
  225. }
  226. else
  227. {
  228. //
  229. // If printing succeeded, then end the job so it can be printed...
  230. //
  231. EndDoc( hDC );
  232. //
  233. // Set progress to 100 percent
  234. //
  235. if (hwndProgress)
  236. {
  237. PostMessage( hwndProgress, PBM_SETPOS, 100, 0 );
  238. Sleep(250);
  239. }
  240. //
  241. // Jump to next page...
  242. //
  243. iOffset = 1;
  244. }
  245. if (bDeleteDC)
  246. {
  247. DeleteDC( hDC );
  248. }
  249. WIA_TRACE((TEXT("iOffset from current page %d"),iOffset));
  250. PostMessage( _hDlg, SP_MSG_JUMP_TO_PAGE, 0, iOffset );
  251. }
  252. else
  253. {
  254. _pWizInfo->ShowError( _hDlg, (HRESULT)GetLastError(), IDS_ERROR_CREATEDC_FAILED );
  255. //
  256. // Jump back to printer selection page... (back 2 pages, thus -2)
  257. //
  258. PostMessage( _hDlg, SP_MSG_JUMP_TO_PAGE, 0, -2 );
  259. }
  260. }
  261. break;
  262. }
  263. }
  264. /*****************************************************************************
  265. CStatusPage::_OnInitDialog
  266. Handle initializing the wizard page...
  267. *****************************************************************************/
  268. LRESULT CStatusPage::_OnInitDialog()
  269. {
  270. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_STATUS, TEXT("CStatusPage::_OnInitDialog()")));
  271. if (!_pWizInfo)
  272. {
  273. WIA_ERROR((TEXT("FATAL: _pWizInfo is NULL, exiting early")));
  274. return FALSE;
  275. }
  276. _pWizInfo->SetStatusWnd( _hDlg );
  277. _pWizInfo->SetStatusPageClass( this );
  278. return TRUE;
  279. }
  280. /*****************************************************************************
  281. CStatusPage::CancelPrinting
  282. Called to stop the print job...
  283. *****************************************************************************/
  284. VOID CStatusPage::_CancelPrinting()
  285. {
  286. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_STATUS, TEXT("CStatusPage:_CancelPrinting()")));
  287. //
  288. // Pause the worker thread while we ask about cancelling printing...
  289. //
  290. if (_hWorkerThread)
  291. {
  292. SuspendThread( _hWorkerThread );
  293. }
  294. //
  295. // Check to see if the user wants to cancel printing...
  296. //
  297. INT iRes;
  298. CSimpleString strMessage(IDS_CANCEL_PRINT_MESSAGE, g_hInst);
  299. CSimpleString strCaption(IDS_CANCEL_PRINT_CAPTION, g_hInst);
  300. iRes = MessageBox( _hDlg,
  301. strMessage,
  302. strCaption,
  303. MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2 | MB_APPLMODAL | MB_SETFOREGROUND
  304. );
  305. g_bCancelPrintJob = (iRes == IDYES);
  306. //
  307. // Resume the thread now that the user has responded...
  308. //
  309. if (_hWorkerThread)
  310. {
  311. ResumeThread( _hWorkerThread );
  312. }
  313. }
  314. /*****************************************************************************
  315. CStatusPage::_OnDestroy
  316. Handles WM_DESTROY for printing status page...
  317. *****************************************************************************/
  318. LRESULT CStatusPage::_OnDestroy()
  319. {
  320. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_STATUS, TEXT("CStatusPage::_OnDestroy()")));
  321. if (_hWorkerThread && _dwWorkerThreadId)
  322. {
  323. WIA_TRACE((TEXT("Sending WM_QUIT to worker thread proc")));
  324. PostThreadMessage( _dwWorkerThreadId, WM_QUIT, 0, 0 );
  325. WiaUiUtil::MsgWaitForSingleObject( _hWorkerThread, INFINITE );
  326. WIA_TRACE((TEXT("_hWorkerThread handle signal'd, closing handle...")));
  327. CloseHandle( _hWorkerThread );
  328. _hWorkerThread = NULL;
  329. _dwWorkerThreadId = 0;
  330. }
  331. return FALSE;
  332. }
  333. /*****************************************************************************
  334. CStatusPage::_OnNotify
  335. Handle WM_NOTIFY
  336. *****************************************************************************/
  337. LRESULT CStatusPage::_OnNotify( WPARAM wParam, LPARAM lParam )
  338. {
  339. WIA_PUSH_FUNCTION_MASK((TRACE_DLGPROC, TEXT("CStatusPage::_OnNotify()")));
  340. LONG_PTR lpRes = 0;
  341. LPNMHDR pnmh = (LPNMHDR)lParam;
  342. switch (pnmh->code)
  343. {
  344. case PSN_SETACTIVE:
  345. {
  346. WIA_TRACE((TEXT("CStatusPage: got PSN_SETACTIVE")));
  347. PropSheet_SetWizButtons( GetParent(_hDlg), 0 );
  348. //
  349. // Reset items
  350. //
  351. SendDlgItemMessage( _hDlg, IDC_PRINT_PROGRESS, PBM_SETPOS, 0, 0 );
  352. CSimpleString str( IDS_READY_TO_PRINT, g_hInst );
  353. SetDlgItemText( _hDlg, IDC_PRINT_PROGRESS_TEXT, str.String() );
  354. //
  355. // Start printing...
  356. //
  357. if (_hWorkerThread && _dwWorkerThreadId)
  358. {
  359. //
  360. // Start printing...
  361. //
  362. WIA_TRACE((TEXT("CStatusPage: posting PP_STATUS_PRINT message")));
  363. PostThreadMessage( _dwWorkerThreadId, PP_STATUS_PRINT, 0, 0 );
  364. }
  365. lpRes = 0;
  366. }
  367. break;
  368. case PSN_WIZBACK:
  369. case PSN_WIZNEXT:
  370. WIA_TRACE((TEXT("CStatusPage: got PSN_WIZBACK or PSN_WIZNEXT")));
  371. lpRes = -1;
  372. break;
  373. case PSN_QUERYCANCEL:
  374. {
  375. WIA_TRACE((TEXT("CStatusPage: got PSN_QUERYCANCEL")));
  376. _CancelPrinting();
  377. if (pnmh->code == PSN_QUERYCANCEL)
  378. {
  379. lpRes = (!g_bCancelPrintJob);
  380. if (!lpRes)
  381. {
  382. //
  383. // We're cancelling the dialog, so do cleanup...
  384. //
  385. if (_pWizInfo)
  386. {
  387. _pWizInfo->ShutDownWizard();
  388. }
  389. }
  390. }
  391. else
  392. {
  393. lpRes = -1;
  394. }
  395. }
  396. break;
  397. }
  398. SetWindowLongPtr( _hDlg, DWLP_MSGRESULT, lpRes );
  399. return TRUE;
  400. }
  401. /*****************************************************************************
  402. CStatusPage::DoHandleMessage
  403. Hanlder for messages sent to this page...
  404. *****************************************************************************/
  405. INT_PTR CStatusPage::DoHandleMessage( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  406. {
  407. WIA_PUSH_FUNCTION_MASK((TRACE_DLGPROC, TEXT("CStatusPage::DoHandleMessage( uMsg = 0x%x, wParam = 0x%x, lParam = 0x%x )"),uMsg,wParam,lParam));
  408. static CSimpleString strFormat(IDS_PRINTING_PROGRESS,g_hInst);
  409. static CSimpleString strProgress;
  410. switch ( uMsg )
  411. {
  412. case WM_INITDIALOG:
  413. _hDlg = hDlg;
  414. return _OnInitDialog();
  415. case WM_COMMAND:
  416. if (LOWORD(wParam)==IDC_CANCEL_PRINTING)
  417. {
  418. if (HIWORD(wParam)==BN_CLICKED)
  419. {
  420. _CancelPrinting();
  421. }
  422. }
  423. break;
  424. case WM_DESTROY:
  425. return _OnDestroy();
  426. case WM_NOTIFY:
  427. return _OnNotify(wParam,lParam);
  428. case SP_MSG_UPDATE_PROGRESS_TEXT:
  429. strProgress.Format( strFormat, wParam, lParam );
  430. strProgress.SetWindowText( GetDlgItem( _hDlg, IDC_PRINT_PROGRESS_TEXT ) );
  431. break;
  432. case SP_MSG_JUMP_TO_PAGE:
  433. {
  434. HWND hwndCurrent = PropSheet_GetCurrentPageHwnd( GetParent(_hDlg) );
  435. INT iIndex = PropSheet_HwndToIndex( GetParent(_hDlg), hwndCurrent );
  436. PropSheet_SetCurSel( GetParent(_hDlg), NULL, iIndex + (INT)lParam );
  437. }
  438. break;
  439. }
  440. return FALSE;
  441. }