| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- // 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;
- }
- /////////////////////////////////////////////////////////////////////////////
|