viewprnt.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #ifdef AFX_PRINT_SEG
  12. #pragma code_seg(AFX_PRINT_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. /////////////////////////////////////////////////////////////////////////////
  19. // Printing Dialog
  20. class CPrintingDialog : public CDialog
  21. {
  22. public:
  23. //{{AFX_DATA(CPrintingDialog)
  24. enum { IDD = AFX_IDD_PRINTDLG };
  25. //}}AFX_DATA
  26. CPrintingDialog::CPrintingDialog(CWnd* pParent)
  27. {
  28. Create(CPrintingDialog::IDD, pParent); // modeless !
  29. _afxWinState->m_bUserAbort = FALSE;
  30. }
  31. virtual ~CPrintingDialog() { }
  32. virtual BOOL OnInitDialog();
  33. virtual void OnCancel();
  34. };
  35. BOOL CALLBACK _AfxAbortProc(HDC, int)
  36. {
  37. _AFX_WIN_STATE* pWinState = _afxWinState;
  38. MSG msg;
  39. while (!pWinState->m_bUserAbort &&
  40. ::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE))
  41. {
  42. if (!AfxGetThread()->PumpMessage())
  43. return FALSE; // terminate if WM_QUIT received
  44. }
  45. return !pWinState->m_bUserAbort;
  46. }
  47. BOOL CPrintingDialog::OnInitDialog()
  48. {
  49. SetWindowText(AfxGetAppName());
  50. CenterWindow();
  51. return CDialog::OnInitDialog();
  52. }
  53. void CPrintingDialog::OnCancel()
  54. {
  55. _afxWinState->m_bUserAbort = TRUE; // flag that user aborted print
  56. CDialog::OnCancel();
  57. }
  58. /////////////////////////////////////////////////////////////////////////////
  59. // CView printing commands
  60. BOOL CView::DoPreparePrinting(CPrintInfo* pInfo)
  61. {
  62. ASSERT(pInfo != NULL);
  63. ASSERT(pInfo->m_pPD != NULL);
  64. if (pInfo->m_pPD->m_pd.nMinPage > pInfo->m_pPD->m_pd.nMaxPage)
  65. pInfo->m_pPD->m_pd.nMaxPage = pInfo->m_pPD->m_pd.nMinPage;
  66. // don't prompt the user if we're doing print preview, printing directly,
  67. // or printing via IPrint and have been instructed not to ask
  68. CWinApp* pApp = AfxGetApp();
  69. if (pInfo->m_bPreview || pInfo->m_bDirect ||
  70. (pInfo->m_bDocObject && !(pInfo->m_dwFlags & PRINTFLAG_PROMPTUSER)))
  71. {
  72. if (pInfo->m_pPD->m_pd.hDC == NULL)
  73. {
  74. // if no printer set then, get default printer DC and create DC without calling
  75. // print dialog.
  76. if (!pApp->GetPrinterDeviceDefaults(&pInfo->m_pPD->m_pd))
  77. {
  78. // bring up dialog to alert the user they need to install a printer.
  79. if (!pInfo->m_bDocObject || (pInfo->m_dwFlags & PRINTFLAG_MAYBOTHERUSER))
  80. if (pApp->DoPrintDialog(pInfo->m_pPD) != IDOK)
  81. return FALSE;
  82. }
  83. if (pInfo->m_pPD->m_pd.hDC == NULL)
  84. {
  85. // call CreatePrinterDC if DC was not created by above
  86. if (pInfo->m_pPD->CreatePrinterDC() == NULL)
  87. return FALSE;
  88. }
  89. }
  90. // set up From and To page range from Min and Max
  91. pInfo->m_pPD->m_pd.nFromPage = (WORD)pInfo->GetMinPage();
  92. pInfo->m_pPD->m_pd.nToPage = (WORD)pInfo->GetMaxPage();
  93. }
  94. else
  95. {
  96. // otherwise, bring up the print dialog and allow user to change things
  97. // preset From-To range same as Min-Max range
  98. pInfo->m_pPD->m_pd.nFromPage = (WORD)pInfo->GetMinPage();
  99. pInfo->m_pPD->m_pd.nToPage = (WORD)pInfo->GetMaxPage();
  100. if (pApp->DoPrintDialog(pInfo->m_pPD) != IDOK)
  101. return FALSE; // do not print
  102. }
  103. ASSERT(pInfo->m_pPD != NULL);
  104. ASSERT(pInfo->m_pPD->m_pd.hDC != NULL);
  105. if (pInfo->m_pPD->m_pd.hDC == NULL)
  106. return FALSE;
  107. pInfo->m_nNumPreviewPages = pApp->m_nNumPreviewPages;
  108. VERIFY(pInfo->m_strPageDesc.LoadString(AFX_IDS_PREVIEWPAGEDESC));
  109. return TRUE;
  110. }
  111. void CView::OnFilePrint()
  112. {
  113. // get default print info
  114. CPrintInfo printInfo;
  115. ASSERT(printInfo.m_pPD != NULL); // must be set
  116. if (LOWORD(GetCurrentMessage()->wParam) == ID_FILE_PRINT_DIRECT)
  117. {
  118. CCommandLineInfo* pCmdInfo = AfxGetApp()->m_pCmdInfo;
  119. if (pCmdInfo != NULL)
  120. {
  121. if (pCmdInfo->m_nShellCommand == CCommandLineInfo::FilePrintTo)
  122. {
  123. printInfo.m_pPD->m_pd.hDC = ::CreateDC(pCmdInfo->m_strDriverName,
  124. pCmdInfo->m_strPrinterName, pCmdInfo->m_strPortName, NULL);
  125. if (printInfo.m_pPD->m_pd.hDC == NULL)
  126. {
  127. AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
  128. return;
  129. }
  130. }
  131. }
  132. printInfo.m_bDirect = TRUE;
  133. }
  134. if (OnPreparePrinting(&printInfo))
  135. {
  136. // hDC must be set (did you remember to call DoPreparePrinting?)
  137. ASSERT(printInfo.m_pPD->m_pd.hDC != NULL);
  138. // gather file to print to if print-to-file selected
  139. CString strOutput;
  140. if (printInfo.m_pPD->m_pd.Flags & PD_PRINTTOFILE && !printInfo.m_bDocObject)
  141. {
  142. // construct CFileDialog for browsing
  143. CString strDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULTEXT));
  144. CString strPrintDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULT));
  145. CString strFilter(MAKEINTRESOURCE(AFX_IDS_PRINTFILTER));
  146. CString strCaption(MAKEINTRESOURCE(AFX_IDS_PRINTCAPTION));
  147. CFileDialog dlg(FALSE, strDef, strPrintDef,
  148. OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, strFilter);
  149. dlg.m_ofn.lpstrTitle = strCaption;
  150. if (dlg.DoModal() != IDOK)
  151. return;
  152. // set output device to resulting path name
  153. strOutput = dlg.GetPathName();
  154. }
  155. // set up document info and start the document printing process
  156. CString strTitle;
  157. CDocument* pDoc = GetDocument();
  158. if (pDoc != NULL)
  159. strTitle = pDoc->GetTitle();
  160. else
  161. GetParentFrame()->GetWindowText(strTitle);
  162. if (strTitle.GetLength() > 31)
  163. strTitle.ReleaseBuffer(31);
  164. DOCINFO docInfo;
  165. memset(&docInfo, 0, sizeof(DOCINFO));
  166. docInfo.cbSize = sizeof(DOCINFO);
  167. docInfo.lpszDocName = strTitle;
  168. CString strPortName;
  169. int nFormatID;
  170. if (strOutput.IsEmpty())
  171. {
  172. docInfo.lpszOutput = NULL;
  173. strPortName = printInfo.m_pPD->GetPortName();
  174. nFormatID = AFX_IDS_PRINTONPORT;
  175. }
  176. else
  177. {
  178. docInfo.lpszOutput = strOutput;
  179. AfxGetFileTitle(strOutput,
  180. strPortName.GetBuffer(_MAX_PATH), _MAX_PATH);
  181. nFormatID = AFX_IDS_PRINTTOFILE;
  182. }
  183. // setup the printing DC
  184. CDC dcPrint;
  185. if (!printInfo.m_bDocObject)
  186. {
  187. dcPrint.Attach(printInfo.m_pPD->m_pd.hDC); // attach printer dc
  188. dcPrint.m_bPrinting = TRUE;
  189. }
  190. OnBeginPrinting(&dcPrint, &printInfo);
  191. if (!printInfo.m_bDocObject)
  192. dcPrint.SetAbortProc(_AfxAbortProc);
  193. // disable main window while printing & init printing status dialog
  194. AfxGetMainWnd()->EnableWindow(FALSE);
  195. CPrintingDialog dlgPrintStatus(this);
  196. CString strTemp;
  197. dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_DOCNAME, strTitle);
  198. dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PRINTERNAME,
  199. printInfo.m_pPD->GetDeviceName());
  200. AfxFormatString1(strTemp, nFormatID, strPortName);
  201. dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PORTNAME, strTemp);
  202. dlgPrintStatus.ShowWindow(SW_SHOW);
  203. dlgPrintStatus.UpdateWindow();
  204. // start document printing process
  205. if (!printInfo.m_bDocObject && dcPrint.StartDoc(&docInfo) == SP_ERROR)
  206. {
  207. // enable main window before proceeding
  208. AfxGetMainWnd()->EnableWindow(TRUE);
  209. // cleanup and show error message
  210. OnEndPrinting(&dcPrint, &printInfo);
  211. dlgPrintStatus.DestroyWindow();
  212. dcPrint.Detach(); // will be cleaned up by CPrintInfo destructor
  213. AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
  214. return;
  215. }
  216. // Guarantee values are in the valid range
  217. UINT nEndPage = printInfo.GetToPage();
  218. UINT nStartPage = printInfo.GetFromPage();
  219. if (nEndPage < printInfo.GetMinPage())
  220. nEndPage = printInfo.GetMinPage();
  221. if (nEndPage > printInfo.GetMaxPage())
  222. nEndPage = printInfo.GetMaxPage();
  223. if (nStartPage < printInfo.GetMinPage())
  224. nStartPage = printInfo.GetMinPage();
  225. if (nStartPage > printInfo.GetMaxPage())
  226. nStartPage = printInfo.GetMaxPage();
  227. int nStep = (nEndPage >= nStartPage) ? 1 : -1;
  228. nEndPage = (nEndPage == 0xffff) ? 0xffff : nEndPage + nStep;
  229. VERIFY(strTemp.LoadString(AFX_IDS_PRINTPAGENUM));
  230. // If it's a doc object, we don't loop page-by-page
  231. // because doc objects don't support that kind of levity.
  232. BOOL bError = FALSE;
  233. if (printInfo.m_bDocObject)
  234. {
  235. OnPrepareDC(&dcPrint, &printInfo);
  236. OnPrint(&dcPrint, &printInfo);
  237. }
  238. else
  239. {
  240. // begin page printing loop
  241. for (printInfo.m_nCurPage = nStartPage;
  242. printInfo.m_nCurPage != nEndPage; printInfo.m_nCurPage += nStep)
  243. {
  244. OnPrepareDC(&dcPrint, &printInfo);
  245. // check for end of print
  246. if (!printInfo.m_bContinuePrinting)
  247. break;
  248. // write current page
  249. TCHAR szBuf[80];
  250. wsprintf(szBuf, strTemp, printInfo.m_nCurPage);
  251. dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PAGENUM, szBuf);
  252. // set up drawing rect to entire page (in logical coordinates)
  253. printInfo.m_rectDraw.SetRect(0, 0,
  254. dcPrint.GetDeviceCaps(HORZRES),
  255. dcPrint.GetDeviceCaps(VERTRES));
  256. dcPrint.DPtoLP(&printInfo.m_rectDraw);
  257. // attempt to start the current page
  258. if (dcPrint.StartPage() < 0)
  259. {
  260. bError = TRUE;
  261. break;
  262. }
  263. // must call OnPrepareDC on newer versions of Windows because
  264. // StartPage now resets the device attributes.
  265. if (afxData.bMarked4)
  266. OnPrepareDC(&dcPrint, &printInfo);
  267. ASSERT(printInfo.m_bContinuePrinting);
  268. // page successfully started, so now render the page
  269. OnPrint(&dcPrint, &printInfo);
  270. if (dcPrint.EndPage() < 0 || !_AfxAbortProc(dcPrint.m_hDC, 0))
  271. {
  272. bError = TRUE;
  273. break;
  274. }
  275. }
  276. }
  277. // cleanup document printing process
  278. if (!printInfo.m_bDocObject)
  279. {
  280. if (!bError)
  281. dcPrint.EndDoc();
  282. else
  283. dcPrint.AbortDoc();
  284. }
  285. AfxGetMainWnd()->EnableWindow(); // enable main window
  286. OnEndPrinting(&dcPrint, &printInfo); // clean up after printing
  287. dlgPrintStatus.DestroyWindow();
  288. dcPrint.Detach(); // will be cleaned up by CPrintInfo destructor
  289. }
  290. }
  291. /////////////////////////////////////////////////////////////////////////////
  292. // CPrintInfo helper structure
  293. CPrintInfo::CPrintInfo()
  294. {
  295. m_pPD = new CPrintDialog(FALSE, PD_ALLPAGES | PD_USEDEVMODECOPIES |
  296. PD_NOSELECTION);
  297. ASSERT(m_pPD->m_pd.hDC == NULL);
  298. SetMinPage(1); // one based page numbers
  299. SetMaxPage(0xffff); // unknown how many pages
  300. m_nCurPage = 1;
  301. m_lpUserData = NULL; // Initialize to no user data
  302. m_bPreview = FALSE; // initialize to not preview
  303. m_bDirect = FALSE; // initialize to not direct
  304. m_bDocObject = FALSE; // initialize to not IPrint
  305. m_bContinuePrinting = TRUE; // Assume it is OK to print
  306. m_dwFlags = 0;
  307. m_nOffsetPage = 0;
  308. }
  309. CPrintInfo::~CPrintInfo()
  310. {
  311. if (m_pPD != NULL && m_pPD->m_pd.hDC != NULL)
  312. {
  313. ::DeleteDC(m_pPD->m_pd.hDC);
  314. m_pPD->m_pd.hDC = NULL;
  315. }
  316. delete m_pPD;
  317. }
  318. /////////////////////////////////////////////////////////////////////////////