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 _DEBUG
- #undef THIS_FILE
- static char BASED_CODE THIS_FILE[] = __FILE__;
- #endif
-
- #define new DEBUG_NEW
-
- /////////////////////////////////////////////////////////////////////////////
- // COleDocObjectItem
-
- IMPLEMENT_DYNAMIC(COleDocObjectItem, COleClientItem)
-
- BEGIN_INTERFACE_MAP(COleDocObjectItem, COleClientItem)
- INTERFACE_PART(COleDocObjectItem, IID_IOleDocumentSite, OleDocumentSite)
- END_INTERFACE_MAP()
-
-
- COleDocObjectItem::COleDocObjectItem(COleDocument* pContainerDoc)
- : COleClientItem(pContainerDoc)
- {
- m_pHelpPopupMenu = NULL;
- m_pActiveView = NULL;
- m_pIPrint = NULL;
- m_bInHelpMenu = FALSE;
- }
-
- COleDocObjectItem::~COleDocObjectItem()
- {
- if (m_pHelpPopupMenu != NULL)
- m_pHelpPopupMenu->RemoveMenu(0, MF_BYPOSITION);
- delete m_pHelpPopupMenu;
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- // IOleDocumentSite interface
-
- STDMETHODIMP_(ULONG) COleDocObjectItem::XOleDocumentSite::AddRef()
- {
- METHOD_PROLOGUE_EX(COleDocObjectItem, OleDocumentSite)
- return pThis->ExternalAddRef();
- }
-
- STDMETHODIMP_(ULONG) COleDocObjectItem::XOleDocumentSite::Release()
- {
- METHOD_PROLOGUE_EX(COleDocObjectItem, OleDocumentSite)
- return pThis->ExternalRelease();
- }
-
- STDMETHODIMP COleDocObjectItem::XOleDocumentSite::QueryInterface(
- REFIID iid, LPVOID* ppvObj)
- {
- METHOD_PROLOGUE_EX(COleDocObjectItem, OleDocumentSite)
- return pThis->ExternalQueryInterface(&iid, ppvObj);
- }
-
- STDMETHODIMP COleDocObjectItem::XOleDocumentSite::ActivateMe(
- LPOLEDOCUMENTVIEW pViewToActivate)
- {
- METHOD_PROLOGUE_EX(COleDocObjectItem, OleDocumentSite)
-
- LPOLEDOCUMENT lpDocument;
- LPOLECLIENTSITE lpClientSite = pThis->GetClientSite();
- LPOLEINPLACESITE lpInPlaceSite =
- (LPOLEINPLACESITE) pThis->GetInterface(&IID_IOleInPlaceSite);
-
- if (lpClientSite == NULL || lpInPlaceSite == NULL)
- return E_FAIL;
-
- // if we've gotten a NULL view, we're to create one ourselves
-
- if (pViewToActivate == NULL)
- {
- // if we already have a view, we can simply activate it
-
- if (pThis->m_pActiveView != NULL && pThis->m_pView != NULL)
- {
- pThis->ActivateAndShow();
- return NOERROR;
- }
-
- ASSERT(pThis->m_lpObject != NULL);
- if (pThis->m_lpObject == NULL)
- return E_FAIL;
-
- lpDocument = QUERYINTERFACE(pThis->m_lpObject, IOleDocument);
- if (lpDocument == NULL)
- return E_FAIL;
-
- if (FAILED(
- lpDocument->CreateView(lpInPlaceSite, NULL, 0, &pViewToActivate)))
- {
- lpDocument->Release();
- return E_OUTOFMEMORY;
- }
-
- // we're done with the document pointer
- lpDocument->Release();
- }
- else if (pThis->m_pActiveView != NULL && pThis->m_pActiveView == pViewToActivate)
- {
- // we already own this view, so no need to addref
- // simply make it visible and resize it
-
- pThis->ActivateAndShow();
- return NOERROR;
- }
- else
- {
- // set the in-place site
- pViewToActivate->SetInPlaceSite(lpInPlaceSite);
- pViewToActivate->AddRef();
- }
-
- // it must've created
- ASSERT(pThis->m_pView != NULL);
-
- // if we had an old one, release it
- if (pThis->m_pActiveView != NULL)
- {
- pThis->m_pActiveView->Show(FALSE);
- pThis->m_pActiveView->UIActivate(FALSE);
- pThis->m_pActiveView->Release();
-
- if (pThis->m_pIPrint != (IPrint*) -1 && pThis->m_pIPrint != NULL)
- pThis->m_pIPrint->Release();
- pThis->m_pIPrint = NULL;
- }
-
- // remember it for later
- pThis->m_pActiveView = pViewToActivate;
-
- // activate and position it
- pThis->ActivateAndShow();
-
- return NOERROR;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // IOleDocumentSite implementation helper
-
- void COleDocObjectItem::ActivateAndShow()
- {
- // set up toolbars and menus for the object
- m_pActiveView->UIActivate(TRUE);
-
- // set the window size, avoiding new toolbars
- RECT rc;
- m_pView->GetClientRect(&rc);
- m_pActiveView->SetRect(&rc);
-
- // make everything visible
- m_pActiveView->Show(TRUE);
-
- return;
- }
-
- void COleDocObjectItem::OnGetItemPosition(CRect& rPosition)
- {
- ASSERT_VALID(this);
- ASSERT(AfxIsValidAddress(&rPosition, sizeof(RECT)));
-
- // doc objects [almost] always in the exact rect of the view
- ASSERT_VALID(m_pView);
- m_pView->GetClientRect(&rPosition);
- }
-
- LPOLEDOCUMENTVIEW COleDocObjectItem::GetActiveView() const
- {
- return m_pActiveView;
- }
-
- void COleDocObjectItem::Release(OLECLOSE dwCloseOption)
- {
- RELEASE(m_pActiveView);
- if (m_pIPrint != (IPrint*) -1)
- RELEASE(m_pIPrint);
- COleClientItem::Release(dwCloseOption);
- }
-
- HRESULT COleDocObjectItem::ExecCommand(DWORD nCmdID,
- DWORD nCmdExecOpt /* = OLECMDEXECOPT_DONTPROMPTUSER */,
- const GUID* pguidCmdGroup /* = NULL */)
- {
- LPOLECOMMANDTARGET lpCt = QUERYINTERFACE(m_lpObject, IOleCommandTarget);
- HRESULT hr = E_NOTIMPL;
-
- if (lpCt != NULL)
- hr = lpCt->Exec(pguidCmdGroup, nCmdID, nCmdExecOpt, NULL, NULL);
-
- RELEASE(lpCt);
- return hr;
- }
-
- BOOL COleDocObjectItem::SupportsIPrint()
- {
- // did someone already ask? -1 means we know it doesn't,
- // non-NULL means we know it does (and we point at it)
- // NULL means we don't know
-
- if (m_pIPrint == NULL)
- {
- // QI for it
- m_pIPrint = QUERYINTERFACE(m_lpObject, IPrint);
-
- if (m_pIPrint == NULL)
- {
- // if the server isn't running, we'll need to
- // start it in order to print
-
- if (FAILED(::OleRun(m_lpObject)))
- m_pIPrint = (IPrint*) -1;
- else
- m_pIPrint = QUERYINTERFACE(m_lpObject, IPrint);
- }
- }
-
- return (m_pIPrint != NULL && m_pIPrint != (IPrint*) -1);
- }
-
- BOOL COleDocObjectItem::GetPageCount(LPLONG pnFirstPage, LPLONG pcPages)
- {
- if (!SupportsIPrint())
- return FALSE;
-
- //WINBUG: The proxy in DOCOBJ.DLL is broken; it doesn't allow
- // NULL parameters to IPrint::GetPageInfo(), even though the spec
- // says it should.
-
- LONG lPages;
- LONG lFirstPage;
-
- HRESULT hr = m_pIPrint->GetPageInfo(&lFirstPage, &lPages);
-
- if (pnFirstPage != NULL)
- *pnFirstPage = lFirstPage;
- if (pcPages != NULL)
- *pcPages = lPages;
-
- if (SUCCEEDED(hr))
- return TRUE;
- else
- return FALSE;
- }
-
-
- CMenu* COleDocObjectItem::GetHelpMenu(UINT& nPosition)
- {
- CFrameWnd* pFrame = m_pView->GetTopLevelFrame();
- CMenu* pMenuFrame = CMenu::FromHandle(pFrame->m_hMenuDefault);
-
- if (pMenuFrame != NULL)
- nPosition = pMenuFrame->GetMenuItemCount() -1;
-
- return pMenuFrame;
- }
-
- void COleDocObjectItem::OnInsertMenus(CMenu* pMenuShared,
- LPOLEMENUGROUPWIDTHS lpMenuWidths)
- {
- ASSERT_VALID(this);
- ASSERT_VALID(pMenuShared);
- ASSERT(AfxIsValidAddress(lpMenuWidths, sizeof(OLEMENUGROUPWIDTHS)));
-
- // initialize the group widths array
- lpMenuWidths->width[0] = 1;
- lpMenuWidths->width[2] = 0;
- lpMenuWidths->width[4] = 0;
-
- // get menu from document template
- CDocTemplate* pTemplate = GetDocument()->GetDocTemplate();
- HMENU hMenuOLE = pTemplate->m_hMenuInPlace;
-
- // only copy the popups if there is a menu loaded
- if (hMenuOLE == NULL)
- return;
-
- UINT nItem;
- CMenu* pMenuFrame = GetHelpMenu(nItem);
-
- if (pMenuFrame != NULL)
- {
- CString strHelpMenuName;
- int nSeparator = pMenuFrame->GetMenuString(nItem,
- strHelpMenuName, MF_BYPOSITION);
- if (nSeparator == 0)
- {
- TRACE0("Error: COleDocObjectItem::OnInsertMenus() found no help menu!\n");
- return;
- }
-
- CString strTearOffName;
- strTearOffName.Format(_T("%s %s"), AfxGetAppName(), strHelpMenuName);
- strTearOffName.Remove('&');
-
- // get the normal frame menu
- int nCount = pMenuFrame->GetMenuItemCount();
- HMENU hMenu = GetSubMenu(pMenuFrame->m_hMenu, nCount-1);
-
- // clean up old menu and allocate a new one
- if (m_pHelpPopupMenu == NULL)
- {
- m_pHelpPopupMenu = new CMenu;
-
- // create new sub-popup menu and add container's Help tearoff
- // then add help menu from main window
- m_pHelpPopupMenu->CreateMenu();
- m_pHelpPopupMenu->InsertMenu((UINT) -1, MF_BYPOSITION | MF_POPUP,
- (UINT) hMenu, strTearOffName);
- }
-
- pMenuShared->InsertMenu(1, MF_BYPOSITION | MF_POPUP,
- (UINT) m_pHelpPopupMenu->m_hMenu, strHelpMenuName);
-
- // tell the object we added our Help menu
- lpMenuWidths->width[5] = 1;
- }
-
- // insert our menu items and adjust group widths array
- AfxMergeMenus(pMenuShared->GetSafeHmenu(), hMenuOLE,
- &lpMenuWidths->width[0], 0);
- }
-
- void COleDocObjectItem::OnRemoveMenus(CMenu *pMenuShared)
- {
- int cItemsShared = pMenuShared->GetMenuItemCount();
- if (cItemsShared != 0)
- {
- CMenu *pMenuHelp = pMenuShared->GetSubMenu(cItemsShared - 1);
-
- int cItemsHelp = pMenuHelp->GetMenuItemCount();
- int nItem;
- for (nItem = cItemsHelp-1; nItem > 0; nItem--)
- pMenuHelp->DeleteMenu(nItem, MF_BYPOSITION);
-
- pMenuShared->RemoveMenu(cItemsShared - 1, MF_BYPOSITION);
- }
-
- COleClientItem::OnRemoveMenus(pMenuShared);
- }
-
- BOOL COleDocObjectItem::OnPreparePrinting(CView* pCaller,
- CPrintInfo* pInfo, BOOL bPrintAll)
- {
- LONG lDocObjectPages = 0;
-
- CDocument* pDoc = pCaller->GetDocument();
- COleDocument* pOleDoc = DYNAMIC_DOWNCAST(COleDocument, pDoc);
- if (pOleDoc == NULL)
- return FALSE;
-
- POSITION pos = pOleDoc->GetStartPosition();
- while (pos != NULL)
- {
- COleClientItem* pItem = pOleDoc->GetNextClientItem(pos);
- COleDocObjectItem* pDocItem =
- DYNAMIC_DOWNCAST(COleDocObjectItem, pItem);
- if (pDocItem == NULL)
- continue;
-
- // if this isn't the view, continue
- if (!bPrintAll)
- {
- if (pItem->m_pView == NULL ||
- pItem->m_pView->m_hWnd != pCaller->m_hWnd)
- continue;
- }
-
- if (pDocItem->SupportsIPrint())
- {
- LONG lThisObjectPages;
- if (pDocItem->GetPageCount(NULL, &lThisObjectPages))
- lDocObjectPages += lThisObjectPages;
- pInfo->m_bDocObject = TRUE;
- }
- else
- lDocObjectPages++;
-
- if (!bPrintAll)
- break;
- }
-
- if (lDocObjectPages > 0)
- {
- UINT nMaxPage = pInfo->GetMaxPage();
-
- // set the page count; increment it if previously set
- if (nMaxPage == 0xFFFF)
- pInfo->SetMaxPage(lDocObjectPages);
- else
- pInfo->SetMaxPage(nMaxPage + lDocObjectPages);
- pInfo->m_bDocObject = TRUE;
- }
-
- if (pInfo->m_bDocObject)
- {
- // we can't show the "selection" button for DocObjects
- pInfo->m_pPD->m_pd.Flags |= PD_NOSELECTION;
-
- // if it's a doc object, and we're printing all, then we
- // shouldn't show the selection
- if (bPrintAll)
- pInfo->m_pPD->m_pd.Flags |= PD_NOPAGENUMS;
- }
-
- return TRUE;
- }
-
- void COleDocObjectItem::OnPrint(CView* pCaller, CPrintInfo* pInfo,
- BOOL bPrintAll)
- {
- // Note that this function ignores pInfo->m_nCurPage, and will always
- // print the whole range of pages in the CPrintInfo object. That's
- // because DocObjects don't support any mechanism to _continue_
- // printing to an existing print job.
-
- CDocument* pDoc = pCaller->GetDocument();
- COleDocument* pOleDoc = DYNAMIC_DOWNCAST(COleDocument, pDoc);
- if (pOleDoc == NULL)
- return;
-
- POSITION pos = pOleDoc->GetStartPosition();
- while (pos != NULL)
- {
- COleClientItem* pItem = pOleDoc->GetNextClientItem(pos);
- COleDocObjectItem* pDocItem = DYNAMIC_DOWNCAST(COleDocObjectItem, pItem);
- if (pDocItem == NULL)
- continue;
-
- // if this isn't the view, continue
- if (!bPrintAll)
- {
- if (pItem->m_pView == NULL || pItem->m_pView->m_hWnd != pCaller->m_hWnd)
- continue;
- }
-
- HRESULT hrThisPage = E_UNEXPECTED;
-
- if (pDocItem->SupportsIPrint())
- {
- DVTARGETDEVICE* pTargetDevice = NULL;
- LPDEVNAMES lpDevNames = NULL;
- LPDEVMODE lpDevMode = NULL;
-
- lpDevNames = (LPDEVNAMES) GlobalLock(pInfo->m_pPD->m_pd.hDevNames);
- if (lpDevNames != NULL)
- {
- lpDevMode = (LPDEVMODE) GlobalLock(pInfo->m_pPD->m_pd.hDevMode);
- if (lpDevMode != NULL)
- {
- pTargetDevice = _AfxOleCreateTargetDevice(lpDevNames, lpDevMode);
- if (pTargetDevice != NULL)
- {
- PAGESET* pps = (PAGESET*) CoTaskMemAlloc(sizeof(PAGESET));
- if (pps != NULL)
- {
- pps->cbStruct = sizeof(PAGESET);
- ASSERT((pps->cbStruct % 4) == 0);
- pps->fOddPages = TRUE;
- pps->fEvenPages = TRUE;
- pps->cPageRange = 1;
- pps->rgPages[0].nFromPage = pInfo->GetFromPage();
- pps->rgPages[0].nToPage = pInfo->GetToPage();
-
- LONG lLastPage = pps->rgPages[0].nFromPage;
- LONG lPagesPrinted;
-
- DWORD dwFlags = PRINTFLAG_RECOMPOSETODEVICE;
-
- if (pInfo->m_pPD->m_pd.Flags & PD_PRINTTOFILE)
- dwFlags |= PRINTFLAG_PRINTTOFILE;
-
- hrThisPage = pDocItem->m_pIPrint->Print(dwFlags,
- &pTargetDevice, &pps, NULL, NULL,
- pInfo->m_nCurPage, &lPagesPrinted,
- &lLastPage);
-
- if (!SUCCEEDED(hrThisPage))
- TRACE1("IPrint::Print() returned %8.8X\n", hrThisPage);
- CoTaskMemFree(pps);
- }
- CoTaskMemFree(pTargetDevice);
- }
- GlobalUnlock(pInfo->m_pPD->m_pd.hDevMode);
- }
- GlobalUnlock(pInfo->m_pPD->m_pd.hDevNames);
- }
- }
- else
- {
- // try through IOleCommandTarget
-
- hrThisPage = pDocItem->ExecCommand(OLECMDID_PRINT);
- if (!SUCCEEDED(hrThisPage))
- TRACE1("IOleCommandTarget::Exec() returned %8.8X\n", hrThisPage);
- }
- }
-
- return;
- }
-