home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / VIEWPRNT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-04  |  13.1 KB  |  462 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 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.  
  11. #include "stdafx.h"
  12. #ifdef _MAC
  13. #include <macname1.h>
  14. #include <Events.h>
  15. #include <macname2.h>
  16. #endif
  17.  
  18. #ifdef AFX_PRINT_SEG
  19. #pragma code_seg(AFX_PRINT_SEG)
  20. #endif
  21.  
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26.  
  27. /////////////////////////////////////////////////////////////////////////////
  28. // Printing Dialog
  29.  
  30. class CPrintingDialog : public CDialog
  31. {
  32. public:
  33.     //{{AFX_DATA(CPrintingDialog)
  34.     enum { IDD = AFX_IDD_PRINTDLG };
  35.     //}}AFX_DATA
  36.     CPrintingDialog::CPrintingDialog(CWnd* pParent)
  37.         {
  38. #ifdef _MAC
  39.             // Note! set m_pView *before* CDialog::Create so that
  40.             // CPrintingDialog::OnInitDialog can use it.
  41.             m_pView = pParent;
  42. #endif
  43.             Create(CPrintingDialog::IDD, pParent);      // modeless !
  44.             _afxWinState->m_bUserAbort = FALSE;
  45.         }
  46.     virtual ~CPrintingDialog() { }
  47.  
  48.     virtual BOOL OnInitDialog();
  49.     virtual void OnCancel();
  50.  
  51. protected:
  52. #ifdef _MAC
  53.     CWnd*   m_pView;        // the view being printed
  54.  
  55.     afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message);
  56. #endif
  57.  
  58. #ifdef _MAC
  59.     //{{AFX_MSG(CPrintingDialog)
  60.     //}}AFX_MSG
  61.     DECLARE_MESSAGE_MAP()
  62. #endif
  63. };
  64.  
  65. #ifdef _MAC
  66. BEGIN_MESSAGE_MAP(CPrintingDialog, CDialog)
  67.     //{{AFX_MSG_MAP(CPrintingDialog)
  68.     ON_WM_MOUSEACTIVATE()
  69.     //}}AFX_MSG_MAP
  70. END_MESSAGE_MAP()
  71. #endif
  72.  
  73. BOOL CALLBACK _AfxAbortProc(HDC, int)
  74. {
  75.     _AFX_WIN_STATE* pWinState = _afxWinState;
  76.  
  77. #ifdef _MAC
  78.     EventRecord er;
  79.     BOOL fNewMessages;
  80.  
  81.     // Look for an event, and if we find one, see if WLM cares about it.
  82.     // If so, remove it from the queue (and then ignore it, since we've
  83.     // already told WLM about it by calling QueueEvent). We also remove
  84.     // the event from the queue if it's an activateEvt for a non-WLM
  85.     // window, since this will probably be an activate for the printer
  86.     // driver's status window, which we want to flush from the queue so
  87.     // that it doesn't block events for WLM windows.
  88.  
  89.     while (EventAvail(everyEvent, &er) &&
  90.         (QueueEvent(&er, &fNewMessages) || er.what == activateEvt))
  91.     {
  92.         GetNextEvent(everyEvent, &er);
  93.     }
  94.  
  95.     // It's harder for us to depend on a cmd-. or escape keypress getting
  96.     // picked up by the EventAvail, since the user could easily click in
  97.     // the printer status window, producing a non-WLM event that would hide
  98.     // the keypress. Therefore we also explicitly check for the keypress.
  99.  
  100.     if (GetAsyncKeyState(VK_CANCEL))
  101.     {
  102.         TRACE0("saw an async VK_CANCEL\n");
  103.         pWinState->m_bUserAbort = TRUE;
  104.     }
  105. #endif
  106.  
  107.     MSG msg;
  108.     while (!pWinState->m_bUserAbort &&
  109. #ifndef _MAC
  110.         ::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE))
  111. #else
  112.         // don't grab any new messages from the Mac event queue
  113.         ::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE | PM_NOEVENTS))
  114. #endif
  115.     {
  116.         if (!AfxGetThread()->PumpMessage())
  117.             return FALSE;   // terminate if WM_QUIT received
  118.     }
  119.     return !pWinState->m_bUserAbort;
  120. }
  121.  
  122. BOOL CPrintingDialog::OnInitDialog()
  123. {
  124. #ifdef _MAC
  125.     // prime the state of the VK_CANCEL key
  126.     GetAsyncKeyState(VK_CANCEL);
  127. #endif
  128.     SetWindowText(AfxGetAppName());
  129. #ifndef _MAC
  130.     CenterWindow();
  131. #else
  132.     CenterWindow(m_pView->GetParentFrame());
  133. #endif
  134.     return CDialog::OnInitDialog();
  135. }
  136.  
  137. void CPrintingDialog::OnCancel()
  138. {
  139.     _afxWinState->m_bUserAbort = TRUE;  // flag that user aborted print
  140.     CDialog::OnCancel();
  141. }
  142.  
  143. #ifdef _MAC
  144. int CPrintingDialog::OnMouseActivate(CWnd* pDesktopWnd, UINT, UINT)
  145. {
  146.     UNUSED(pDesktopWnd); // not used in release build
  147.     ASSERT(pDesktopWnd == this);
  148.  
  149.     // if the printer driver has opened its own status window, we don't
  150.     // want to activate our printing status window when it's clicked
  151.  
  152.     return MA_NOACTIVATE;
  153. }
  154. #endif
  155.  
  156. /////////////////////////////////////////////////////////////////////////////
  157. // CView printing commands
  158.  
  159. BOOL CView::DoPreparePrinting(CPrintInfo* pInfo)
  160. {
  161.     ASSERT(pInfo != NULL);
  162.     ASSERT(pInfo->m_pPD != NULL);
  163.  
  164.     if (pInfo->m_pPD->m_pd.nMinPage > pInfo->m_pPD->m_pd.nMaxPage)
  165.         pInfo->m_pPD->m_pd.nMaxPage = pInfo->m_pPD->m_pd.nMinPage;
  166.  
  167.     // don't prompt the user if we're doing print preview, printing directly,
  168.     // or printing via IPrint and have been instructed not to ask
  169.  
  170.     CWinApp* pApp = AfxGetApp();
  171.     if (pInfo->m_bPreview || pInfo->m_bDirect ||
  172.         (pInfo->m_bDocObject && !(pInfo->m_dwFlags & PRINTFLAG_PROMPTUSER)))
  173.     {
  174.         if (pInfo->m_pPD->m_pd.hDC == NULL)
  175.         {
  176.             // if no printer set then, get default printer DC and create DC without calling
  177.             //   print dialog.
  178.             if (!pApp->GetPrinterDeviceDefaults(&pInfo->m_pPD->m_pd))
  179.             {
  180.                 // bring up dialog to alert the user they need to install a printer.
  181.                 if (!pInfo->m_bDocObject || (pInfo->m_dwFlags & PRINTFLAG_MAYBOTHERUSER))
  182.                     if (pApp->DoPrintDialog(pInfo->m_pPD) != IDOK)
  183.                         return FALSE;
  184.             }
  185.  
  186.             if (pInfo->m_pPD->m_pd.hDC == NULL)
  187.             {
  188.                 // call CreatePrinterDC if DC was not created by above
  189.                 if (pInfo->m_pPD->CreatePrinterDC() == NULL)
  190.                     return FALSE;
  191.             }
  192.         }
  193.  
  194.         // set up From and To page range from Min and Max
  195.         pInfo->m_pPD->m_pd.nFromPage = (WORD)pInfo->GetMinPage();
  196.         pInfo->m_pPD->m_pd.nToPage = (WORD)pInfo->GetMaxPage();
  197.     }
  198.     else
  199.     {
  200.         // otherwise, bring up the print dialog and allow user to change things
  201.         // preset From-To range same as Min-Max range
  202.         pInfo->m_pPD->m_pd.nFromPage = (WORD)pInfo->GetMinPage();
  203.         pInfo->m_pPD->m_pd.nToPage = (WORD)pInfo->GetMaxPage();
  204.  
  205.         if (pApp->DoPrintDialog(pInfo->m_pPD) != IDOK)
  206.             return FALSE;       // do not print
  207.     }
  208.  
  209.     ASSERT(pInfo->m_pPD != NULL);
  210.     ASSERT(pInfo->m_pPD->m_pd.hDC != NULL);
  211.     if (pInfo->m_pPD->m_pd.hDC == NULL)
  212.         return FALSE;
  213.  
  214.     pInfo->m_nNumPreviewPages = pApp->m_nNumPreviewPages;
  215.     VERIFY(pInfo->m_strPageDesc.LoadString(AFX_IDS_PREVIEWPAGEDESC));
  216.     return TRUE;
  217. }
  218.  
  219. void CView::OnFilePrint()
  220. {
  221.     // get default print info
  222.     CPrintInfo printInfo;
  223.     ASSERT(printInfo.m_pPD != NULL);    // must be set
  224.  
  225.     if (LOWORD(GetCurrentMessage()->wParam) == ID_FILE_PRINT_DIRECT)
  226.     {
  227.         CCommandLineInfo* pCmdInfo = AfxGetApp()->m_pCmdInfo;
  228.  
  229.         if (pCmdInfo != NULL)
  230.         {
  231.             if (pCmdInfo->m_nShellCommand == CCommandLineInfo::FilePrintTo)
  232.             {
  233.                 printInfo.m_pPD->m_pd.hDC = ::CreateDC(pCmdInfo->m_strDriverName,
  234.                     pCmdInfo->m_strPrinterName, pCmdInfo->m_strPortName, NULL);
  235.                 if (printInfo.m_pPD->m_pd.hDC == NULL)
  236.                 {
  237.                     AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
  238.                     return;
  239.                 }
  240.             }
  241.         }
  242.  
  243.         printInfo.m_bDirect = TRUE;
  244.     }
  245.  
  246.     if (OnPreparePrinting(&printInfo))
  247.     {
  248.         // hDC must be set (did you remember to call DoPreparePrinting?)
  249.         ASSERT(printInfo.m_pPD->m_pd.hDC != NULL);
  250.  
  251.         // gather file to print to if print-to-file selected
  252.         CString strOutput;
  253.         if (printInfo.m_pPD->m_pd.Flags & PD_PRINTTOFILE)
  254.         {
  255.             // construct CFileDialog for browsing
  256.             CString strDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULTEXT));
  257.             CString strPrintDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULT));
  258.             CString strFilter(MAKEINTRESOURCE(AFX_IDS_PRINTFILTER));
  259.             CString strCaption(MAKEINTRESOURCE(AFX_IDS_PRINTCAPTION));
  260.             CFileDialog dlg(FALSE, strDef, strPrintDef,
  261.                 OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, strFilter);
  262.             dlg.m_ofn.lpstrTitle = strCaption;
  263.  
  264.             if (dlg.DoModal() != IDOK)
  265.                 return;
  266.  
  267.             // set output device to resulting path name
  268.             strOutput = dlg.GetPathName();
  269.         }
  270.  
  271.         // set up document info and start the document printing process
  272.         CString strTitle;
  273.         CDocument* pDoc = GetDocument();
  274.         if (pDoc != NULL)
  275.             strTitle = pDoc->GetTitle();
  276.         else
  277.             GetParentFrame()->GetWindowText(strTitle);
  278.         if (strTitle.GetLength() > 31)
  279.             strTitle.ReleaseBuffer(31);
  280.         DOCINFO docInfo;
  281.         memset(&docInfo, 0, sizeof(DOCINFO));
  282.         docInfo.cbSize = sizeof(DOCINFO);
  283.         docInfo.lpszDocName = strTitle;
  284.         CString strPortName;
  285.         int nFormatID;
  286.         if (strOutput.IsEmpty())
  287.         {
  288.             docInfo.lpszOutput = NULL;
  289.             strPortName = printInfo.m_pPD->GetPortName();
  290.             nFormatID = AFX_IDS_PRINTONPORT;
  291.         }
  292.         else
  293.         {
  294.             docInfo.lpszOutput = strOutput;
  295.             AfxGetFileTitle(strOutput,
  296.                 strPortName.GetBuffer(_MAX_PATH), _MAX_PATH);
  297.             nFormatID = AFX_IDS_PRINTTOFILE;
  298.         }
  299.  
  300.         // setup the printing DC
  301.         CDC dcPrint;
  302.         dcPrint.Attach(printInfo.m_pPD->m_pd.hDC);  // attach printer dc
  303.         dcPrint.m_bPrinting = TRUE;
  304.         OnBeginPrinting(&dcPrint, &printInfo);
  305.         dcPrint.SetAbortProc(_AfxAbortProc);
  306.  
  307.         // disable main window while printing & init printing status dialog
  308.         AfxGetMainWnd()->EnableWindow(FALSE);
  309.         CPrintingDialog dlgPrintStatus(this);
  310.  
  311.         CString strTemp;
  312.         dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_DOCNAME, strTitle);
  313. #ifndef _MAC
  314.         dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PRINTERNAME,
  315.             printInfo.m_pPD->GetDeviceName());
  316.         AfxFormatString1(strTemp, nFormatID, strPortName);
  317.         dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PORTNAME, strTemp);
  318. #endif
  319.         dlgPrintStatus.ShowWindow(SW_SHOW);
  320.         dlgPrintStatus.UpdateWindow();
  321.  
  322.         // start document printing process
  323.         if (dcPrint.StartDoc(&docInfo) == SP_ERROR)
  324.         {
  325.             // enable main window before proceeding
  326.             AfxGetMainWnd()->EnableWindow(TRUE);
  327.  
  328.             // cleanup and show error message
  329.             OnEndPrinting(&dcPrint, &printInfo);
  330.             dlgPrintStatus.DestroyWindow();
  331.             dcPrint.Detach();   // will be cleaned up by CPrintInfo destructor
  332.             AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
  333.             return;
  334.         }
  335.  
  336.         // Guarantee values are in the valid range
  337.         UINT nEndPage = printInfo.GetToPage();
  338.         UINT nStartPage = printInfo.GetFromPage();
  339.  
  340.         if (nEndPage < printInfo.GetMinPage())
  341.             nEndPage = printInfo.GetMinPage();
  342.         if (nEndPage > printInfo.GetMaxPage())
  343.             nEndPage = printInfo.GetMaxPage();
  344.  
  345.         if (nStartPage < printInfo.GetMinPage())
  346.             nStartPage = printInfo.GetMinPage();
  347.         if (nStartPage > printInfo.GetMaxPage())
  348.             nStartPage = printInfo.GetMaxPage();
  349.  
  350.         int nStep = (nEndPage >= nStartPage) ? 1 : -1;
  351.         nEndPage = (nEndPage == 0xffff) ? 0xffff : nEndPage + nStep;
  352.  
  353.         VERIFY(strTemp.LoadString(AFX_IDS_PRINTPAGENUM));
  354.  
  355.         // begin page printing loop
  356.         BOOL bError = FALSE;
  357.         for (printInfo.m_nCurPage = nStartPage;
  358.             printInfo.m_nCurPage != nEndPage; printInfo.m_nCurPage += nStep)
  359.         {
  360.             OnPrepareDC(&dcPrint, &printInfo);
  361.  
  362.             // check for end of print
  363.             if (!printInfo.m_bContinuePrinting)
  364.                 break;
  365.  
  366.             // write current page
  367.             TCHAR szBuf[80];
  368.             wsprintf(szBuf, strTemp, printInfo.m_nCurPage);
  369.             dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PAGENUM, szBuf);
  370.  
  371.             // set up drawing rect to entire page (in logical coordinates)
  372.             printInfo.m_rectDraw.SetRect(0, 0,
  373.                 dcPrint.GetDeviceCaps(HORZRES),
  374.                 dcPrint.GetDeviceCaps(VERTRES));
  375.             dcPrint.DPtoLP(&printInfo.m_rectDraw);
  376.  
  377.             // attempt to start the current page
  378.             if (dcPrint.StartPage() < 0)
  379.             {
  380.                 bError = TRUE;
  381.                 break;
  382.             }
  383.  
  384.             // must call OnPrepareDC on newer versions of Windows because
  385.             // StartPage now resets the device attributes.
  386.             if (afxData.bMarked4)
  387.                 OnPrepareDC(&dcPrint, &printInfo);
  388.  
  389.             ASSERT(printInfo.m_bContinuePrinting);
  390.  
  391.             // page successfully started, so now render the page
  392.             OnPrint(&dcPrint, &printInfo);
  393.             if (dcPrint.EndPage() < 0 || !_AfxAbortProc(dcPrint.m_hDC, 0))
  394.             {
  395.                 bError = TRUE;
  396.                 break;
  397.             }
  398.         }
  399.  
  400.         // cleanup document printing process
  401.         if (!bError)
  402.             dcPrint.EndDoc();
  403.         else
  404.             dcPrint.AbortDoc();
  405.  
  406.         AfxGetMainWnd()->EnableWindow();    // enable main window
  407.  
  408.         OnEndPrinting(&dcPrint, &printInfo);    // clean up after printing
  409.         dlgPrintStatus.DestroyWindow();
  410.  
  411.         dcPrint.Detach();   // will be cleaned up by CPrintInfo destructor
  412.  
  413. #ifdef _MAC
  414.         // It's common for the user to click on the printing status dialog
  415.         // and not have the click be registered because the abort proc
  416.         // wasn't called often enough. For this reason we call _FlushEvents
  417.         // after printing is done so that those events don't get sent
  418.         // through to the document window and cause unintended changes to
  419.         // the document.
  420.  
  421.         FlushEvents(everyEvent, 0);
  422. #endif
  423.     }
  424. }
  425.  
  426. /////////////////////////////////////////////////////////////////////////////
  427. // CPrintInfo helper structure
  428.  
  429. CPrintInfo::CPrintInfo()
  430. {
  431.     m_pPD = new CPrintDialog(FALSE, PD_ALLPAGES | PD_USEDEVMODECOPIES |
  432.         PD_NOSELECTION);
  433.  
  434.     ASSERT(m_pPD->m_pd.hDC == NULL);
  435.  
  436.     SetMinPage(1);              // one based page numbers
  437.     SetMaxPage(0xffff);         // unknown how many pages
  438.  
  439.     m_nCurPage = 1;
  440.  
  441.     m_lpUserData = NULL;        // Initialize to no user data
  442.     m_bPreview = FALSE;         // initialize to not preview
  443.     m_bDirect = FALSE;          // initialize to not direct
  444.     m_bDocObject = FALSE;       // initialize to not IPrint
  445.     m_bContinuePrinting = TRUE; // Assume it is OK to print
  446.  
  447.     m_dwFlags = 0;
  448.     m_nOffsetPage = 0;
  449. }
  450.  
  451. CPrintInfo::~CPrintInfo()
  452. {
  453.     if (m_pPD != NULL && m_pPD->m_pd.hDC != NULL)
  454.     {
  455.         ::DeleteDC(m_pPD->m_pd.hDC);
  456.         m_pPD->m_pd.hDC = NULL;
  457.     }
  458.     delete m_pPD;
  459. }
  460.  
  461. /////////////////////////////////////////////////////////////////////////////
  462.