home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
-
- #ifdef AFX_PRINT_SEG
- #pragma code_seg(AFX_PRINT_SEG)
- #endif
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // Printing Dialog
-
- class CPrintingDialog : public CDialog
- {
- public:
- //{{AFX_DATA(CPrintingDialog)
- enum { IDD = AFX_IDD_PRINTDLG };
- //}}AFX_DATA
- CPrintingDialog::CPrintingDialog(CWnd* pParent)
- {
- Create(CPrintingDialog::IDD, pParent); // modeless !
- _afxWinState->m_bUserAbort = FALSE;
- }
- virtual ~CPrintingDialog() { }
-
- virtual BOOL OnInitDialog();
- virtual void OnCancel();
- };
-
- BOOL CALLBACK _AfxAbortProc(HDC, int)
- {
- _AFX_WIN_STATE* pWinState = _afxWinState;
- MSG msg;
- while (!pWinState->m_bUserAbort &&
- ::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE))
- {
- if (!AfxGetThread()->PumpMessage())
- return FALSE; // terminate if WM_QUIT received
- }
- return !pWinState->m_bUserAbort;
- }
-
- BOOL CPrintingDialog::OnInitDialog()
- {
- SetWindowText(AfxGetAppName());
- CenterWindow();
- return CDialog::OnInitDialog();
- }
-
- void CPrintingDialog::OnCancel()
- {
- _afxWinState->m_bUserAbort = TRUE; // flag that user aborted print
- CDialog::OnCancel();
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CView printing commands
-
- BOOL CView::DoPreparePrinting(CPrintInfo* pInfo)
- {
- ASSERT(pInfo != NULL);
- ASSERT(pInfo->m_pPD != NULL);
-
- if (pInfo->m_pPD->m_pd.nMinPage > pInfo->m_pPD->m_pd.nMaxPage)
- pInfo->m_pPD->m_pd.nMaxPage = pInfo->m_pPD->m_pd.nMinPage;
-
- // don't prompt the user if we're doing print preview, printing directly,
- // or printing via IPrint and have been instructed not to ask
-
- CWinApp* pApp = AfxGetApp();
- if (pInfo->m_bPreview || pInfo->m_bDirect ||
- (pInfo->m_bDocObject && !(pInfo->m_dwFlags & PRINTFLAG_PROMPTUSER)))
- {
- if (pInfo->m_pPD->m_pd.hDC == NULL)
- {
- // if no printer set then, get default printer DC and create DC without calling
- // print dialog.
- if (!pApp->GetPrinterDeviceDefaults(&pInfo->m_pPD->m_pd))
- {
- // bring up dialog to alert the user they need to install a printer.
- if (!pInfo->m_bDocObject || (pInfo->m_dwFlags & PRINTFLAG_MAYBOTHERUSER))
- if (pApp->DoPrintDialog(pInfo->m_pPD) != IDOK)
- return FALSE;
- }
-
- if (pInfo->m_pPD->m_pd.hDC == NULL)
- {
- // call CreatePrinterDC if DC was not created by above
- if (pInfo->m_pPD->CreatePrinterDC() == NULL)
- return FALSE;
- }
- }
-
- // set up From and To page range from Min and Max
- pInfo->m_pPD->m_pd.nFromPage = (WORD)pInfo->GetMinPage();
- pInfo->m_pPD->m_pd.nToPage = (WORD)pInfo->GetMaxPage();
- }
- else
- {
- // otherwise, bring up the print dialog and allow user to change things
- // preset From-To range same as Min-Max range
- pInfo->m_pPD->m_pd.nFromPage = (WORD)pInfo->GetMinPage();
- pInfo->m_pPD->m_pd.nToPage = (WORD)pInfo->GetMaxPage();
-
- if (pApp->DoPrintDialog(pInfo->m_pPD) != IDOK)
- return FALSE; // do not print
- }
-
- ASSERT(pInfo->m_pPD != NULL);
- ASSERT(pInfo->m_pPD->m_pd.hDC != NULL);
- if (pInfo->m_pPD->m_pd.hDC == NULL)
- return FALSE;
-
- pInfo->m_nNumPreviewPages = pApp->m_nNumPreviewPages;
- VERIFY(pInfo->m_strPageDesc.LoadString(AFX_IDS_PREVIEWPAGEDESC));
- return TRUE;
- }
-
- void CView::OnFilePrint()
- {
- // get default print info
- CPrintInfo printInfo;
- ASSERT(printInfo.m_pPD != NULL); // must be set
-
- if (LOWORD(GetCurrentMessage()->wParam) == ID_FILE_PRINT_DIRECT)
- {
- CCommandLineInfo* pCmdInfo = AfxGetApp()->m_pCmdInfo;
-
- if (pCmdInfo != NULL)
- {
- if (pCmdInfo->m_nShellCommand == CCommandLineInfo::FilePrintTo)
- {
- printInfo.m_pPD->m_pd.hDC = ::CreateDC(pCmdInfo->m_strDriverName,
- pCmdInfo->m_strPrinterName, pCmdInfo->m_strPortName, NULL);
- if (printInfo.m_pPD->m_pd.hDC == NULL)
- {
- AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
- return;
- }
- }
- }
-
- printInfo.m_bDirect = TRUE;
- }
-
- if (OnPreparePrinting(&printInfo))
- {
- // hDC must be set (did you remember to call DoPreparePrinting?)
- ASSERT(printInfo.m_pPD->m_pd.hDC != NULL);
-
- // gather file to print to if print-to-file selected
- CString strOutput;
- if (printInfo.m_pPD->m_pd.Flags & PD_PRINTTOFILE && !printInfo.m_bDocObject)
- {
- // construct CFileDialog for browsing
- CString strDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULTEXT));
- CString strPrintDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULT));
- CString strFilter(MAKEINTRESOURCE(AFX_IDS_PRINTFILTER));
- CString strCaption(MAKEINTRESOURCE(AFX_IDS_PRINTCAPTION));
- CFileDialog dlg(FALSE, strDef, strPrintDef,
- OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, strFilter);
- dlg.m_ofn.lpstrTitle = strCaption;
-
- if (dlg.DoModal() != IDOK)
- return;
-
- // set output device to resulting path name
- strOutput = dlg.GetPathName();
- }
-
- // set up document info and start the document printing process
- CString strTitle;
- CDocument* pDoc = GetDocument();
- if (pDoc != NULL)
- strTitle = pDoc->GetTitle();
- else
- GetParentFrame()->GetWindowText(strTitle);
- if (strTitle.GetLength() > 31)
- strTitle.ReleaseBuffer(31);
- DOCINFO docInfo;
- memset(&docInfo, 0, sizeof(DOCINFO));
- docInfo.cbSize = sizeof(DOCINFO);
- docInfo.lpszDocName = strTitle;
- CString strPortName;
- int nFormatID;
- if (strOutput.IsEmpty())
- {
- docInfo.lpszOutput = NULL;
- strPortName = printInfo.m_pPD->GetPortName();
- nFormatID = AFX_IDS_PRINTONPORT;
- }
- else
- {
- docInfo.lpszOutput = strOutput;
- AfxGetFileTitle(strOutput,
- strPortName.GetBuffer(_MAX_PATH), _MAX_PATH);
- nFormatID = AFX_IDS_PRINTTOFILE;
- }
-
- // setup the printing DC
- CDC dcPrint;
- if (!printInfo.m_bDocObject)
- {
- dcPrint.Attach(printInfo.m_pPD->m_pd.hDC); // attach printer dc
- dcPrint.m_bPrinting = TRUE;
- }
- OnBeginPrinting(&dcPrint, &printInfo);
-
- if (!printInfo.m_bDocObject)
- dcPrint.SetAbortProc(_AfxAbortProc);
-
- // disable main window while printing & init printing status dialog
- AfxGetMainWnd()->EnableWindow(FALSE);
- CPrintingDialog dlgPrintStatus(this);
-
- CString strTemp;
- dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_DOCNAME, strTitle);
- dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PRINTERNAME,
- printInfo.m_pPD->GetDeviceName());
- AfxFormatString1(strTemp, nFormatID, strPortName);
- dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PORTNAME, strTemp);
- dlgPrintStatus.ShowWindow(SW_SHOW);
- dlgPrintStatus.UpdateWindow();
-
- // start document printing process
- if (!printInfo.m_bDocObject && dcPrint.StartDoc(&docInfo) == SP_ERROR)
- {
- // enable main window before proceeding
- AfxGetMainWnd()->EnableWindow(TRUE);
-
- // cleanup and show error message
- OnEndPrinting(&dcPrint, &printInfo);
- dlgPrintStatus.DestroyWindow();
- dcPrint.Detach(); // will be cleaned up by CPrintInfo destructor
- AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
- return;
- }
-
- // Guarantee values are in the valid range
- UINT nEndPage = printInfo.GetToPage();
- UINT nStartPage = printInfo.GetFromPage();
-
- if (nEndPage < printInfo.GetMinPage())
- nEndPage = printInfo.GetMinPage();
- if (nEndPage > printInfo.GetMaxPage())
- nEndPage = printInfo.GetMaxPage();
-
- if (nStartPage < printInfo.GetMinPage())
- nStartPage = printInfo.GetMinPage();
- if (nStartPage > printInfo.GetMaxPage())
- nStartPage = printInfo.GetMaxPage();
-
- int nStep = (nEndPage >= nStartPage) ? 1 : -1;
- nEndPage = (nEndPage == 0xffff) ? 0xffff : nEndPage + nStep;
-
- VERIFY(strTemp.LoadString(AFX_IDS_PRINTPAGENUM));
-
- // If it's a doc object, we don't loop page-by-page
- // because doc objects don't support that kind of levity.
-
- BOOL bError = FALSE;
- if (printInfo.m_bDocObject)
- {
- OnPrepareDC(&dcPrint, &printInfo);
- OnPrint(&dcPrint, &printInfo);
- }
- else
- {
- // begin page printing loop
- for (printInfo.m_nCurPage = nStartPage;
- printInfo.m_nCurPage != nEndPage; printInfo.m_nCurPage += nStep)
- {
- OnPrepareDC(&dcPrint, &printInfo);
-
- // check for end of print
- if (!printInfo.m_bContinuePrinting)
- break;
-
- // write current page
- TCHAR szBuf[80];
- wsprintf(szBuf, strTemp, printInfo.m_nCurPage);
- dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PAGENUM, szBuf);
-
- // set up drawing rect to entire page (in logical coordinates)
- printInfo.m_rectDraw.SetRect(0, 0,
- dcPrint.GetDeviceCaps(HORZRES),
- dcPrint.GetDeviceCaps(VERTRES));
- dcPrint.DPtoLP(&printInfo.m_rectDraw);
-
- // attempt to start the current page
- if (dcPrint.StartPage() < 0)
- {
- bError = TRUE;
- break;
- }
-
- // must call OnPrepareDC on newer versions of Windows because
- // StartPage now resets the device attributes.
- if (afxData.bMarked4)
- OnPrepareDC(&dcPrint, &printInfo);
-
- ASSERT(printInfo.m_bContinuePrinting);
-
- // page successfully started, so now render the page
- OnPrint(&dcPrint, &printInfo);
- if (dcPrint.EndPage() < 0 || !_AfxAbortProc(dcPrint.m_hDC, 0))
- {
- bError = TRUE;
- break;
- }
- }
- }
-
- // cleanup document printing process
- if (!printInfo.m_bDocObject)
- {
- if (!bError)
- dcPrint.EndDoc();
- else
- dcPrint.AbortDoc();
- }
-
- AfxGetMainWnd()->EnableWindow(); // enable main window
-
- OnEndPrinting(&dcPrint, &printInfo); // clean up after printing
- dlgPrintStatus.DestroyWindow();
-
- dcPrint.Detach(); // will be cleaned up by CPrintInfo destructor
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CPrintInfo helper structure
-
- CPrintInfo::CPrintInfo()
- {
- m_pPD = new CPrintDialog(FALSE, PD_ALLPAGES | PD_USEDEVMODECOPIES |
- PD_NOSELECTION);
-
- ASSERT(m_pPD->m_pd.hDC == NULL);
-
- SetMinPage(1); // one based page numbers
- SetMaxPage(0xffff); // unknown how many pages
-
- m_nCurPage = 1;
-
- m_lpUserData = NULL; // Initialize to no user data
- m_bPreview = FALSE; // initialize to not preview
- m_bDirect = FALSE; // initialize to not direct
- m_bDocObject = FALSE; // initialize to not IPrint
- m_bContinuePrinting = TRUE; // Assume it is OK to print
-
- m_dwFlags = 0;
- m_nOffsetPage = 0;
- }
-
- CPrintInfo::~CPrintInfo()
- {
- if (m_pPD != NULL && m_pPD->m_pd.hDC != NULL)
- {
- ::DeleteDC(m_pPD->m_pd.hDC);
- m_pPD->m_pd.hDC = NULL;
- }
- delete m_pPD;
- }
-
- /////////////////////////////////////////////////////////////////////////////
-