📄 oledocob.cpp
字号:
// 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 _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
// CDocObjectServer
IMPLEMENT_DYNAMIC(CDocObjectServer, CCmdTarget)
BEGIN_MESSAGE_MAP(CDocObjectServer, CCmdTarget)
//{{AFX_MSG_MAP(CDocObjectServer)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BEGIN_INTERFACE_MAP(CDocObjectServer, CCmdTarget)
INTERFACE_PART(CDocObjectServer, IID_IOleObject, OleObject)
INTERFACE_PART(CDocObjectServer, IID_IOleDocument, OleDocument)
INTERFACE_PART(CDocObjectServer, IID_IOleDocumentView, OleDocumentView)
INTERFACE_PART(CDocObjectServer, IID_IOleCommandTarget, OleCommandTarget)
INTERFACE_PART(CDocObjectServer, IID_IPrint, Print)
END_INTERFACE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDocObjectServer implementation
CDocObjectServer::CDocObjectServer(COleServerDoc* pDoc,
LPOLEDOCUMENTSITE pDocSite /* = NULL */)
{
// Initialize DocObject data
m_pDocSite = pDocSite;
m_pViewSite = NULL;
m_pOwner = pDoc;
ASSERT(m_pOwner != NULL);
m_nFirstPage = 1;
// All Binder-Compatible documents use Compound Files as their
// storage mechanism
m_pOwner->EnableCompoundFile(TRUE);
m_nFirstPage = -1;
}
CDocObjectServer::~CDocObjectServer()
{
ReleaseDocSite();
}
void CDocObjectServer::ReleaseDocSite()
{
if (m_pDocSite != NULL)
{
m_pDocSite->Release();
m_pDocSite = NULL;
}
}
void CDocObjectServer::SetDocSite(LPOLEDOCUMENTSITE pNewSite)
{
ReleaseDocSite();
m_pDocSite = pNewSite;
}
void CDocObjectServer::OnCloseDocument()
{
// Clean up pointer to document site, if any
ReleaseDocSite();
m_pOwner->OnCloseDocument();
}
void CDocObjectServer::ActivateDocObject()
{
ASSERT(m_pOwner != NULL);
if (m_pOwner->IsDocObject())
{
ASSERT(m_pDocSite != NULL);
m_pDocSite->ActivateMe(NULL);
}
}
STDMETHODIMP CDocObjectServer::OnExecOleCmd(
const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt,
VARIANTARG* pvarargIn, VARIANTARG* pvarargOut)
{
ASSERT(m_pOwner != NULL);
if (m_pOwner == NULL)
return E_NOTIMPL;
else
return m_pOwner->OnExecOleCmd(pguidCmdGroup, nCmdID,
nCmdExecOpt, pvarargIn, pvarargOut);
}
COleDocIPFrameWnd* CDocObjectServer::GetControllingFrame() const
{
COleDocIPFrameWnd* pFrame = NULL;
POSITION pos = m_pOwner->GetFirstViewPosition();
if (pos != NULL)
{
CView* pView = m_pOwner->GetNextView(pos);
if (pView != NULL)
{
CWnd* pParent = pView->GetParentFrame();
pFrame = DYNAMIC_DOWNCAST(COleDocIPFrameWnd, pParent);
}
}
#ifdef _DEBUG
// This TRACE will trip if you've not converted your application to
// use a COleDocIPFrameWnd, or if you've incorrectly hooked up
// DocObject support in your application.
if (pFrame == NULL)
TRACE0("Error: An appropriate DocObject frame could not be found.\n");
#endif
return pFrame;
}
BOOL CDocObjectServer::DoPreparePrinting(CView* pView, CPrintInfo* printInfo)
{
return pView->OnPreparePrinting(printInfo);
}
void CDocObjectServer::DoPrepareDC(CView* pView, CDC* pdcPrint,
CPrintInfo* pprintInfo)
{
pView->OnPrepareDC(pdcPrint, pprintInfo);
}
void CDocObjectServer::DoPrint(CView* pView, CDC* pdcPrint,
CPrintInfo* pprintInfo)
{
pView->OnPrint(pdcPrint, pprintInfo);
}
void CDocObjectServer::DoBeginPrinting(CView* pView,
CDC* pDC, CPrintInfo* pprintInfo)
{
pView->OnBeginPrinting(pDC, pprintInfo);
}
void CDocObjectServer::DoEndPrinting(CView* pView,
CDC* pDC, CPrintInfo* pprintInfo)
{
pView->OnEndPrinting(pDC, pprintInfo);
}
/////////////////////////////////////////////////////////////////////////////
// IPrint interface
extern BOOL CALLBACK _AfxAbortProc(HDC, int); // from VIEWPRNT.CPP
STDMETHODIMP_(ULONG) CDocObjectServer::XPrint::AddRef()
{
METHOD_PROLOGUE_EX(CDocObjectServer, Print)
return pThis->m_pOwner->ExternalAddRef();
}
STDMETHODIMP_(ULONG) CDocObjectServer::XPrint::Release()
{
METHOD_PROLOGUE_EX(CDocObjectServer, Print)
return pThis->m_pOwner->ExternalRelease();
}
STDMETHODIMP CDocObjectServer::XPrint::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
METHOD_PROLOGUE_EX(CDocObjectServer, Print)
return pThis->ExternalQueryInterface(&iid, ppvObj);
}
STDMETHODIMP CDocObjectServer::XPrint::SetInitialPageNum(
LONG nFirstPage)
{
METHOD_PROLOGUE_EX(CDocObjectServer, Print)
ASSERT_VALID(pThis);
pThis->m_nFirstPage = nFirstPage;
return S_OK;
}
STDMETHODIMP CDocObjectServer::XPrint::GetPageInfo(
LPLONG pnFirstPage, LPLONG pcPages)
{
METHOD_PROLOGUE_EX(CDocObjectServer, Print)
ASSERT_VALID(pThis);
// find the view we need to print
CView* pView = NULL;
POSITION pos = pThis->m_pOwner->GetFirstViewPosition();
if (pos != NULL)
pView = pThis->m_pOwner->GetNextView(pos);
if (pView == NULL)
return E_UNEXPECTED;
// tell the view that we're not actually printing
// and just need to measure the print job
CPrintInfo printInfo;
printInfo.m_bDocObject = TRUE;
printInfo.m_dwFlags = PRINTFLAG_DONTACTUALLYPRINT;
// ask the view about it
if (!pThis->DoPreparePrinting(pView, &printInfo))
return E_UNEXPECTED;
// pnFirstPage and pcPages are allowed to be NULL
// if NULL, don't return results to caller
if (pnFirstPage != NULL)
{
if (pThis->m_nFirstPage == -1)
*pnFirstPage = printInfo.GetMinPage();
else
*pnFirstPage = pThis->m_nFirstPage;
}
if (pcPages != NULL)
{
if (printInfo.GetToPage() == 0xFFFF)
*pcPages = 0xFFFF;
else
*pcPages = printInfo.GetToPage() - printInfo.GetFromPage() +1;
}
return S_OK;
}
STDMETHODIMP CDocObjectServer::XPrint::Print(
DWORD grfFlags, DVTARGETDEVICE** ppTD, PAGESET** ppPageSet,
LPSTGMEDIUM pstgmOptions, LPCONTINUECALLBACK pCallback, LONG nFirstPage,
LPLONG pcPagesPrinted, LPLONG pnLastPage)
{
METHOD_PROLOGUE_EX(CDocObjectServer, Print)
ASSERT_VALID(pThis);
UNUSED_ALWAYS(pstgmOptions);
UNUSED_ALWAYS(pnLastPage);
// try to get out of this without doing any work
if (pcPagesPrinted == NULL || ppTD == NULL || ppPageSet == NULL)
return E_POINTER;
if (*ppTD == NULL)
return E_INVALIDARG;
// get initialized
DVTARGETDEVICE* ptd = *ppTD;
pThis->m_nFirstPage = nFirstPage;
*pcPagesPrinted = 0;
// find the view we need to print
CView* pView = NULL;
POSITION pos = pThis->m_pOwner->GetFirstViewPosition();
if (pos != NULL)
pView = pThis->m_pOwner->GetNextView(pos);
if (pView == NULL)
return E_UNEXPECTED;
// get default print info
CPrintInfo printInfo;
ASSERT(printInfo.m_pPD != NULL); // must be set
printInfo.m_bDocObject = TRUE;
printInfo.m_dwFlags = grfFlags;
printInfo.m_nOffsetPage = nFirstPage;
printInfo.m_pPD->m_pd.hDC = _AfxOleCreateDC(*ppTD);
if (printInfo.m_pPD->m_pd.hDC == NULL)
{
if (grfFlags & PRINTFLAG_MAYBOTHERUSER)
AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
return E_UNEXPECTED;
}
if (pThis->DoPreparePrinting(pView, &printInfo))
{
// hDC must be set (did you remember to call DoPreparePrinting?)
ASSERT(printInfo.m_pPD->m_pd.hDC != NULL);
// set file to print to if print-to-file selected
CString strOutput;
if (grfFlags & PRINTFLAG_PRINTTOFILE)
strOutput = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
// if we were to prompt, we'll need to copy info from the
// user back to the client
if (grfFlags & PRINTFLAG_PROMPTUSER)
{
if (grfFlags & PRINTFLAG_USERMAYCHANGEPRINTER)
{
LPDEVNAMES lpDevNames =
(LPDEVNAMES) GlobalLock(printInfo.m_pPD->m_pd.hDevNames);
LPDEVMODE lpDevMode =
(LPDEVMODE) GlobalLock(printInfo.m_pPD->m_pd.hDevMode);
if (lpDevNames == NULL || lpDevMode == NULL)
*ppTD = NULL;
else
*ppTD = _AfxOleCreateTargetDevice(lpDevNames, lpDevMode);
GlobalUnlock(printInfo.m_pPD->m_pd.hDevNames);
GlobalUnlock(printInfo.m_pPD->m_pd.hDevMode);
}
// MFC page ranges (for now) only have one PAGERANGE
LPMALLOC pMalloc = NULL;
// if the caller didn't supply a buffer, allocate one
// else, make sure the buffer is big enough
if (*ppPageSet == NULL)
{
HRESULT hrCopying = CoGetMalloc(1, &pMalloc);
if (FAILED(hrCopying))
return hrCopying;
*ppPageSet =
(PAGESET*) pMalloc->Alloc(sizeof(PAGESET) + sizeof(PAGERANGE));
}
else
{
if ((*ppPageSet)->cPageRange < 1 ||
(*ppPageSet)->cbStruct != sizeof(PAGESET))
{
return E_INVALIDARG;
}
}
if (*ppPageSet != NULL)
{
(*ppPageSet)->cbStruct = sizeof(PAGESET);
(*ppPageSet)->fOddPages = TRUE;
(*ppPageSet)->fEvenPages = TRUE;
(*ppPageSet)->cPageRange = 1;
(*ppPageSet)->rgPages[0].nFromPage = printInfo.GetFromPage();
(*ppPageSet)->rgPages[0].nToPage = printInfo.GetToPage();
}
RELEASE(pMalloc);
if (*ppTD == NULL || *ppPageSet == NULL)
return E_UNEXPECTED;
}
// if the client didn't really want to print,
// we've collected all the information we need
if (grfFlags & PRINTFLAG_DONTACTUALLYPRINT)
return S_OK;
// set up document info and start the document printing process
CString strTitle;
CDocument* pDoc = pThis->m_pOwner;
if (pDoc != NULL)
strTitle = pDoc->GetTitle();
else
pView->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 = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
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;
pThis->DoBeginPrinting(pView, &dcPrint, &printInfo);
dcPrint.SetAbortProc(_AfxAbortProc);
// disable main window while printing & init printing status dialog
AfxGetMainWnd()->EnableWindow(FALSE);
CString strTemp;
// start document printing process
if (dcPrint.StartDoc(&docInfo) == SP_ERROR)
{
// enable main window before proceeding
AfxGetMainWnd()->EnableWindow(TRUE);
// cleanup and show error message
pThis->DoEndPrinting(pView, &dcPrint, &printInfo);
dcPrint.Detach(); // will be cleaned up by CPrintInfo destructor
AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
return E_UNEXPECTED;
}
// 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;
HRESULT hrContinue = S_OK;
for (printInfo.m_nCurPage = nStartPage;
printInfo.m_nCurPage != nEndPage; printInfo.m_nCurPage += nStep)
{
// check even/odd filter
if (printInfo.m_nCurPage % 2 == 1 && !(*ppPageSet)->fOddPages)
continue;
if (printInfo.m_nCurPage % 2 == 0 && !(*ppPageSet)->fEvenPages)
continue;
// check PAGERANGE if supplied
if (ppPageSet != NULL && (*ppPageSet)->cPageRange > 0)
{
ULONG nCheckRange;
BOOL bFound = FALSE;
for (nCheckRange = 0; (nCheckRange < (*ppPageSet)->cPageRange) && !bFound; nCheckRange++)
{
if ( ((*ppPageSet)->rgPages[nCheckRange].nFromPage <= (LONG) printInfo.m_nCurPage ) &&
((*ppPageSet)->rgPages[nCheckRange].nToPage >= (LONG) printInfo.m_nCurPage) )
{
bFound = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -