Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

448 lines
12 KiB

// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1995 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 _MAC
#include <macname1.h>
#include <Events.h>
#include <macname2.h>
#endif
#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)
{
#ifdef _MAC
// Note! set m_pView *before* CDialog::Create so that
// CPrintingDialog::OnInitDialog can use it.
m_pView = pParent;
#endif
Create(CPrintingDialog::IDD, pParent); // modeless !
_afxWinState->m_bUserAbort = FALSE;
}
virtual ~CPrintingDialog() { }
virtual BOOL OnInitDialog();
virtual void OnCancel();
protected:
#ifdef _MAC
CWnd* m_pView; // the view being printed
afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message);
#endif
#ifdef _MAC
//{{AFX_MSG(CPrintingDialog)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
#endif
};
#ifdef _MAC
BEGIN_MESSAGE_MAP(CPrintingDialog, CDialog)
//{{AFX_MSG_MAP(CPrintingDialog)
ON_WM_MOUSEACTIVATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif
BOOL CALLBACK _AfxAbortProc(HDC, int)
{
_AFX_WIN_STATE* pWinState = _afxWinState;
#ifdef _MAC
EventRecord er;
BOOL fNewMessages;
// Look for an event, and if we find one, see if WLM cares about it.
// If so, remove it from the queue (and then ignore it, since we've
// already told WLM about it by calling QueueEvent). We also remove
// the event from the queue if it's an activateEvt for a non-WLM
// window, since this will probably be an activate for the printer
// driver's status window, which we want to flush from the queue so
// that it doesn't block events for WLM windows.
while (EventAvail(everyEvent, &er) &&
(QueueEvent(&er, &fNewMessages) || er.what == activateEvt))
{
GetNextEvent(everyEvent, &er);
}
// It's harder for us to depend on a cmd-. or escape keypress getting
// picked up by the EventAvail, since the user could easily click in
// the printer status window, producing a non-WLM event that would hide
// the keypress. Therefore we also explicitly check for the keypress.
if (GetAsyncKeyState(VK_CANCEL))
{
TRACE0("saw an async VK_CANCEL\n");
pWinState->m_bUserAbort = TRUE;
}
#endif
MSG msg;
while (!pWinState->m_bUserAbort &&
#ifndef _MAC
::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE))
#else
// don't grab any new messages from the Mac event queue
::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE | PM_NOEVENTS))
#endif
{
if (!AfxGetThread()->PumpMessage())
return FALSE; // terminate if WM_QUIT received
}
return !pWinState->m_bUserAbort;
}
BOOL CPrintingDialog::OnInitDialog()
{
#ifdef _MAC
// prime the state of the VK_CANCEL key
GetAsyncKeyState(VK_CANCEL);
#endif
SetWindowText(AfxGetAppName());
#ifndef _MAC
CenterWindow();
#else
CenterWindow(m_pView->GetParentFrame());
#endif
return CDialog::OnInitDialog();
}
void CPrintingDialog::OnCancel()
{
_afxWinState->m_bUserAbort = TRUE; // flag that user aborted print
CDialog::OnCancel();
}
#ifdef _MAC
int CPrintingDialog::OnMouseActivate(CWnd* pDesktopWnd, UINT, UINT)
{
UNUSED(pDesktopWnd); // not used in release build
ASSERT(pDesktopWnd == this);
// if the printer driver has opened its own status window, we don't
// want to activate our printing status window when it's clicked
return MA_NOACTIVATE;
}
#endif
/////////////////////////////////////////////////////////////////////////////
// CView printing commands
BOOL CView::DoPreparePrinting(CPrintInfo* pInfo)
{
ASSERT(pInfo != NULL);
ASSERT(pInfo->m_pPD != NULL);
CWinApp* pApp = AfxGetApp();
if (pInfo->m_bPreview || pInfo->m_bDirect)
{
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 (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);
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 (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)
{
// 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;
dcPrint.Attach(printInfo.m_pPD->m_pd.hDC); // attach printer dc
dcPrint.m_bPrinting = TRUE;
OnBeginPrinting(&dcPrint, &printInfo);
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);
#ifndef _MAC
dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PRINTERNAME,
printInfo.m_pPD->GetDeviceName());
AfxFormatString1(strTemp, nFormatID, strPortName);
dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PORTNAME, strTemp);
#endif
dlgPrintStatus.ShowWindow(SW_SHOW);
dlgPrintStatus.UpdateWindow();
// start document printing process
if (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));
// begin page printing loop
BOOL bError = FALSE;
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 (!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
#ifdef _MAC
// It's common for the user to click on the printing status dialog
// and not have the click be registered because the abort proc
// wasn't called often enough. For this reason we call _FlushEvents
// after printing is done so that those events don't get sent
// through to the document window and cause unintended changes to
// the document.
FlushEvents(everyEvent, 0);
#endif
}
}
/////////////////////////////////////////////////////////////////////////////
// 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_bContinuePrinting = TRUE; // Assume it is OK to print
}
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;
}
/////////////////////////////////////////////////////////////////////////////