PrinterJob.cpp
上传用户:ledldq
上传日期:2007-01-04
资源大小:95k
文件大小:8k
源码类别:

打印编程

开发平台:

Visual C++

  1. // PrinterJob.cpp: implementation of the CPrinterJob class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "PrintManager.h"
  6. #include "PrinterJob.h"
  7. #include "PrintStatus.h"
  8. #include <stdlib.h>
  9. #ifdef _DEBUG
  10. #undef THIS_FILE
  11. static char THIS_FILE[]=__FILE__;
  12. #define new DEBUG_NEW
  13. #endif
  14. //////////////////////////////////////////////////////////////////////
  15. // Construction/Destruction
  16. //////////////////////////////////////////////////////////////////////
  17. bool bGfxUserAbort;
  18. BOOL CALLBACK EXPORT _GfxAbortProc( HDC, int )
  19. {
  20. MSG msg;
  21. while (!bGfxUserAbort && ::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE))
  22. {
  23. if (!AfxGetThread()->PumpMessage()) return FALSE;
  24. }
  25. return !bGfxUserAbort;
  26. }
  27. CPrinterJob::CPrinterJob()
  28. {
  29. pParent = NULL;
  30. strTitle = "senza nome";
  31. bAlreadyAskedPageOpt = false;
  32. }
  33. CPrinterJob::~CPrinterJob()
  34. {
  35. }
  36. bool CPrinterJob::OnPreparePrinting(CPrintInfo * pInfo, bool bPrintPreview)
  37. {
  38. if (bPrintPreview) return true;
  39. return DoPreparePrinting(pInfo);
  40. }
  41. void CPrinterJob::OnBeginPrinting(CDC * pDC, CPrintInfo * pInfo)
  42. {
  43. }
  44. void CPrinterJob::OnEndPrinting(CDC * pDC, CPrintInfo * pInfo)
  45. {
  46. }
  47. void CPrinterJob::OnPrint(CDC * pDC, CPrintInfo * pInfo)
  48. {
  49. }
  50. bool CPrinterJob::DoPreparePrinting(CPrintInfo * pInfo)
  51. {
  52. ASSERT(pInfo != NULL);
  53. ASSERT(pInfo->m_pPD != NULL);
  54. if (pInfo->m_pPD->m_pd.nMinPage > pInfo->m_pPD->m_pd.nMaxPage)
  55. pInfo->m_pPD->m_pd.nMaxPage = pInfo->m_pPD->m_pd.nMinPage;
  56. pInfo->m_pPD->m_pd.nFromPage = (WORD)pInfo->GetMinPage();
  57. pInfo->m_pPD->m_pd.nToPage = (WORD)pInfo->GetMaxPage();
  58. if (AfxGetApp()->DoPrintDialog(pInfo->m_pPD) != IDOK) return FALSE;
  59. ASSERT(pInfo->m_pPD != NULL);
  60. ASSERT(pInfo->m_pPD->m_pd.hDC != NULL);
  61. if (pInfo->m_pPD->m_pd.hDC == NULL) return FALSE;
  62. pInfo->m_nNumPreviewPages = AfxGetApp()->m_nNumPreviewPages;
  63. VERIFY(pInfo->m_strPageDesc.LoadString(AFX_IDS_PREVIEWPAGEDESC));
  64. return TRUE;
  65. }
  66. void CPrinterJob::OnFilePrint()
  67. {
  68. CPrintInfo printInfo;
  69. ASSERT(printInfo.m_pPD != NULL);    // must be set
  70. if (OnPreparePrinting(&printInfo))
  71. {
  72. // hDC must be set (did you remember to call DoPreparePrinting?)
  73. ASSERT(printInfo.m_pPD->m_pd.hDC != NULL);
  74. // gather file to print to if print-to-file selected
  75. CString strOutput;
  76. if (printInfo.m_pPD->m_pd.Flags & PD_PRINTTOFILE)
  77. {
  78. // construct CFileDialog for browsing
  79. CString strDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULTEXT));
  80. CString strPrintDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULT));
  81. CString strFilter(MAKEINTRESOURCE(AFX_IDS_PRINTFILTER));
  82. CString strCaption(MAKEINTRESOURCE(AFX_IDS_PRINTCAPTION));
  83. CFileDialog dlg(FALSE, strDef, strPrintDef, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, strFilter);
  84. dlg.m_ofn.lpstrTitle = strCaption;
  85. if (dlg.DoModal() != IDOK) return;
  86. // set output device to resulting path name
  87. strOutput = dlg.GetPathName();
  88. }
  89. DOCINFO docInfo;
  90. memset(&docInfo, 0, sizeof(DOCINFO));
  91. docInfo.cbSize = sizeof(DOCINFO);
  92. docInfo.lpszDocName = strTitle;
  93. CString strPortName;
  94. int nFormatID;
  95. if (strOutput.IsEmpty())
  96. {
  97. docInfo.lpszOutput = NULL;
  98. strPortName = printInfo.m_pPD->GetPortName();
  99. nFormatID = AFX_IDS_PRINTONPORT;
  100. }
  101. else
  102. {
  103. docInfo.lpszOutput = strOutput;
  104. nFormatID = AFX_IDS_PRINTTOFILE;
  105. }
  106. // setup the printing DC
  107. CDC dcPrint;
  108. dcPrint.Attach(printInfo.m_pPD->m_pd.hDC);  // attach printer dc
  109. dcPrint.m_bPrinting = TRUE;
  110. printInfo.m_rectDraw.SetRect(0, 0, dcPrint.GetDeviceCaps(HORZRES), dcPrint.GetDeviceCaps(VERTRES));
  111. dcPrint.DPtoLP(&printInfo.m_rectDraw);
  112. OnBeginPrinting(&dcPrint, &printInfo);
  113. dcPrint.SetAbortProc(_GfxAbortProc);
  114. // disable main window while printing & init printing status dialog
  115. CString csFormat, cs, strTemp;
  116. AfxGetMainWnd()->EnableWindow(FALSE);
  117. CPrintStatus dlgPrintStatus(pParent);
  118. cs.Format("Stampa di %s in corso ..", strTitle);
  119. dlgPrintStatus.SetWindowText(cs);
  120. dlgPrintStatus.GetDlgItemText(IDC_TEXT1, csFormat);
  121. AfxFormatString1(strTemp, nFormatID, strPortName);
  122. cs.Format(csFormat, strTitle, printInfo.m_pPD->GetDeviceName(), strTemp);
  123. dlgPrintStatus.SetDlgItemText(IDC_TEXT1, cs);
  124. dlgPrintStatus.ShowWindow(SW_SHOW);
  125. dlgPrintStatus.UpdateWindow();
  126. // start document printing process
  127. if (dcPrint.StartDoc(&docInfo) == SP_ERROR)
  128. {
  129. // enable main window before proceeding
  130. AfxGetMainWnd()->EnableWindow(TRUE);
  131. // cleanup and show error message
  132. OnEndPrinting(&dcPrint, &printInfo);
  133. dlgPrintStatus.DestroyWindow();
  134. dcPrint.Detach();   // will be cleaned up by CPrintInfo destructor
  135. AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
  136. return;
  137. }
  138. // Guarantee values are in the valid range
  139. UINT nEndPage = printInfo.GetToPage();
  140. UINT nStartPage = printInfo.GetFromPage();
  141. if (nEndPage < printInfo.GetMinPage()) nEndPage = printInfo.GetMinPage();
  142. if (nEndPage > printInfo.GetMaxPage()) nEndPage = printInfo.GetMaxPage();
  143. if (nStartPage < printInfo.GetMinPage()) nStartPage = printInfo.GetMinPage();
  144. if (nStartPage > printInfo.GetMaxPage()) nStartPage = printInfo.GetMaxPage();
  145. int nStep = (nEndPage >= nStartPage) ? 1 : -1;
  146. nEndPage = (nEndPage == 0xffff) ? 0xffff : nEndPage + nStep;
  147. int iPageTot = abs(abs(nEndPage) - abs(nStartPage)), iPrintedPages = 0;
  148. CString csPageFormat;
  149. dlgPrintStatus.GetDlgItemText(IDC_PAGES, csPageFormat);
  150. // begin page printing loop
  151. DWORD dwStart = GetTickCount(), dTickPerPage = 0;
  152. dlgPrintStatus.wndProg.SetRange(0, iPageTot);
  153. dlgPrintStatus.wndProg.SetPos(0);
  154. bool bRectSet = false;
  155. BOOL bError = FALSE;
  156. for (printInfo.m_nCurPage = nStartPage; printInfo.m_nCurPage != nEndPage; printInfo.m_nCurPage += nStep)
  157. {
  158. TCHAR szBuf[80];
  159. iPrintedPages ++;
  160. dlgPrintStatus.wndProg.SetPos(iPrintedPages);
  161. dlgPrintStatus.wndProg.UpdateWindow();
  162. wsprintf(szBuf, "%d %%", iPrintedPages*100/iPageTot);
  163. dlgPrintStatus.SetDlgItemText(IDC_PC, szBuf);
  164. OnPrepareDC(&dcPrint, &printInfo);
  165. // check for end of print
  166. if (!printInfo.m_bContinuePrinting) break;
  167. // write current page
  168. DWORD tck = dTickPerPage * (iPageTot - iPrintedPages + 1) / 1000;
  169. if (tck > 60)
  170. {
  171. tck != 60;
  172. DWORD tckS = tck%60;
  173. tck /= 60;
  174. strTemp.Format("%d minuti, %d secondi", tck, tckS);
  175. }
  176. else
  177. {
  178. if (iPageTot > 1)
  179. {
  180. if (tck > 0) strTemp.Format("%d secondi", tck);
  181. else strTemp = "??";
  182. }
  183. }
  184. wsprintf(szBuf, csPageFormat, iPrintedPages, iPageTot, strTemp);
  185. dlgPrintStatus.SetDlgItemText(IDC_PAGES, szBuf);
  186. printInfo.m_rectDraw.SetRect(0, 0, dcPrint.GetDeviceCaps(HORZRES), dcPrint.GetDeviceCaps(VERTRES));
  187. dcPrint.DPtoLP(&printInfo.m_rectDraw);
  188. // attempt to start the current page
  189. if (dcPrint.StartPage() < 0)
  190. {
  191. bError = TRUE;
  192. break;
  193. }
  194. OnPrepareDC(&dcPrint, &printInfo);
  195. ASSERT(printInfo.m_bContinuePrinting);
  196. // page successfully started, so now render the page
  197. int is = dcPrint.SaveDC();
  198. OnPrint(&dcPrint, &printInfo);
  199. if (dcPrint.EndPage() < 0 || !_GfxAbortProc(dcPrint.m_hDC, 0))
  200. {
  201. bError = TRUE;
  202. break;
  203. }
  204. dcPrint.RestoreDC(is);
  205. dTickPerPage = (GetTickCount() - dwStart) / iPrintedPages;
  206. }
  207. // cleanup document printing process
  208. if (!bError) dcPrint.EndDoc();
  209. else dcPrint.AbortDoc();
  210. AfxGetMainWnd()->EnableWindow();    // enable main window
  211. OnEndPrinting(&dcPrint, &printInfo);    // clean up after printing
  212. dlgPrintStatus.DestroyWindow();
  213. dcPrint.Detach();   // will be cleaned up by CPrintInfo destructor
  214. }
  215. }
  216. void CPrinterJob::OnPrepareDC(CDC * pDC, CPrintInfo * pInfo)
  217. {
  218. ASSERT_VALID(pDC);
  219. UNUSED(pDC); // unused in release builds
  220. // Default to one page printing if doc length not known
  221. if (pInfo != NULL)
  222. pInfo->m_bContinuePrinting =
  223. (pInfo->GetMaxPage() != 0xffff || (pInfo->m_nCurPage == 1));
  224. }