home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / oledoccl.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  14KB  |  513 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef _DEBUG
  14. #undef THIS_FILE
  15. static char BASED_CODE THIS_FILE[] = __FILE__;
  16. #endif
  17.  
  18. #define new DEBUG_NEW
  19.  
  20. /////////////////////////////////////////////////////////////////////////////
  21. // COleDocObjectItem
  22.  
  23. IMPLEMENT_DYNAMIC(COleDocObjectItem, COleClientItem)
  24.  
  25. BEGIN_INTERFACE_MAP(COleDocObjectItem, COleClientItem)
  26.     INTERFACE_PART(COleDocObjectItem, IID_IOleDocumentSite, OleDocumentSite)
  27. END_INTERFACE_MAP()
  28.  
  29.  
  30. COleDocObjectItem::COleDocObjectItem(COleDocument* pContainerDoc)
  31.     : COleClientItem(pContainerDoc)
  32. {
  33.     m_pHelpPopupMenu = NULL;
  34.     m_pActiveView = NULL;
  35.     m_pIPrint = NULL;
  36.     m_bInHelpMenu = FALSE;
  37. }
  38.  
  39. COleDocObjectItem::~COleDocObjectItem()
  40. {
  41.     if (m_pHelpPopupMenu != NULL)
  42.         m_pHelpPopupMenu->RemoveMenu(0, MF_BYPOSITION);
  43.     delete m_pHelpPopupMenu;
  44. }
  45.  
  46.  
  47. /////////////////////////////////////////////////////////////////////////////
  48. // IOleDocumentSite interface
  49.  
  50. STDMETHODIMP_(ULONG) COleDocObjectItem::XOleDocumentSite::AddRef()
  51. {
  52.     METHOD_PROLOGUE_EX(COleDocObjectItem, OleDocumentSite)
  53.     return pThis->ExternalAddRef();
  54. }
  55.  
  56. STDMETHODIMP_(ULONG) COleDocObjectItem::XOleDocumentSite::Release()
  57. {
  58.     METHOD_PROLOGUE_EX(COleDocObjectItem, OleDocumentSite)
  59.     return pThis->ExternalRelease();
  60. }
  61.  
  62. STDMETHODIMP COleDocObjectItem::XOleDocumentSite::QueryInterface(
  63.     REFIID iid, LPVOID* ppvObj)
  64. {
  65.     METHOD_PROLOGUE_EX(COleDocObjectItem, OleDocumentSite)
  66.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  67. }
  68.  
  69. STDMETHODIMP COleDocObjectItem::XOleDocumentSite::ActivateMe(
  70.     LPOLEDOCUMENTVIEW pViewToActivate)
  71. {
  72.     METHOD_PROLOGUE_EX(COleDocObjectItem, OleDocumentSite)
  73.  
  74.     LPOLEDOCUMENT lpDocument;
  75.     LPOLECLIENTSITE lpClientSite = pThis->GetClientSite();
  76.     LPOLEINPLACESITE lpInPlaceSite =
  77.         (LPOLEINPLACESITE) pThis->GetInterface(&IID_IOleInPlaceSite);
  78.  
  79.     if (lpClientSite == NULL || lpInPlaceSite == NULL)
  80.         return E_FAIL;
  81.  
  82.     // if we've gotten a NULL view, we're to create one ourselves
  83.  
  84.     if (pViewToActivate == NULL)
  85.     {
  86.         // if we already have a view, we can simply activate it
  87.  
  88.         if (pThis->m_pActiveView != NULL && pThis->m_pView != NULL)
  89.         {
  90.             pThis->ActivateAndShow();
  91.             return NOERROR;
  92.         }
  93.  
  94.         ASSERT(pThis->m_lpObject != NULL);
  95.         if (pThis->m_lpObject == NULL)
  96.             return E_FAIL;
  97.  
  98.         lpDocument = QUERYINTERFACE(pThis->m_lpObject, IOleDocument);
  99.         if (lpDocument == NULL)
  100.             return E_FAIL;
  101.  
  102.         if (FAILED(
  103.             lpDocument->CreateView(lpInPlaceSite, NULL, 0, &pViewToActivate)))
  104.         {
  105.             lpDocument->Release();
  106.         return E_OUTOFMEMORY;
  107.         }
  108.  
  109.         // we're done with the document pointer
  110.         lpDocument->Release();
  111.     }
  112.     else if (pThis->m_pActiveView != NULL && pThis->m_pActiveView == pViewToActivate)
  113.     {
  114.         // we already own this view, so no need to addref
  115.         // simply make it visible and resize it
  116.  
  117.         pThis->ActivateAndShow();
  118.         return NOERROR;
  119.     }
  120.     else
  121.     {
  122.         // set the in-place site
  123.         pViewToActivate->SetInPlaceSite(lpInPlaceSite);
  124.         pViewToActivate->AddRef();
  125.     }
  126.  
  127.     // it must've created
  128.     ASSERT(pThis->m_pView != NULL);
  129.  
  130.     // if we had an old one, release it
  131.     if (pThis->m_pActiveView != NULL)
  132.     {
  133.         pThis->m_pActiveView->Show(FALSE);
  134.         pThis->m_pActiveView->UIActivate(FALSE);
  135.         pThis->m_pActiveView->Release();
  136.  
  137.         if (pThis->m_pIPrint != (IPrint*) -1 && pThis->m_pIPrint != NULL)
  138.             pThis->m_pIPrint->Release();
  139.         pThis->m_pIPrint = NULL;
  140.     }
  141.  
  142.     // remember it for later
  143.     pThis->m_pActiveView = pViewToActivate;
  144.  
  145.     // activate and position it
  146.     pThis->ActivateAndShow();
  147.  
  148.     return NOERROR;
  149. }
  150.  
  151. /////////////////////////////////////////////////////////////////////////////
  152. // IOleDocumentSite implementation helper
  153.  
  154. void COleDocObjectItem::ActivateAndShow()
  155. {
  156.     // set up toolbars and menus for the object
  157.     m_pActiveView->UIActivate(TRUE);
  158.  
  159.     // set the window size, avoiding new toolbars
  160.     RECT rc;
  161.     m_pView->GetClientRect(&rc);
  162.     m_pActiveView->SetRect(&rc);
  163.  
  164.     // make everything visible
  165.     m_pActiveView->Show(TRUE);
  166.  
  167.     return;
  168. }
  169.  
  170. void COleDocObjectItem::OnGetItemPosition(CRect& rPosition)
  171. {
  172.     ASSERT_VALID(this);
  173.     ASSERT(AfxIsValidAddress(&rPosition, sizeof(RECT)));
  174.  
  175.     // doc objects [almost] always in the exact rect of the view
  176.     ASSERT_VALID(m_pView);
  177.     m_pView->GetClientRect(&rPosition);
  178. }
  179.  
  180. LPOLEDOCUMENTVIEW COleDocObjectItem::GetActiveView() const
  181. {
  182.     return m_pActiveView;
  183. }
  184.  
  185. void COleDocObjectItem::Release(OLECLOSE dwCloseOption)
  186. {
  187.     RELEASE(m_pActiveView);
  188.     if (m_pIPrint != (IPrint*) -1)
  189.         RELEASE(m_pIPrint);
  190.     COleClientItem::Release(dwCloseOption);
  191. }
  192.  
  193. HRESULT COleDocObjectItem::ExecCommand(DWORD nCmdID,
  194.     DWORD nCmdExecOpt /* = OLECMDEXECOPT_DONTPROMPTUSER */,
  195.     const GUID* pguidCmdGroup /* = NULL */)
  196. {
  197.     LPOLECOMMANDTARGET lpCt = QUERYINTERFACE(m_lpObject, IOleCommandTarget);
  198.     HRESULT hr = E_NOTIMPL;
  199.  
  200.     if (lpCt != NULL)
  201.         hr = lpCt->Exec(pguidCmdGroup, nCmdID, nCmdExecOpt, NULL, NULL);
  202.  
  203.     RELEASE(lpCt);
  204.     return hr;
  205. }
  206.  
  207. BOOL COleDocObjectItem::SupportsIPrint()
  208. {
  209.     // did someone already ask? -1 means we know it doesn't,
  210.     // non-NULL means we know it does (and we point at it)
  211.     // NULL means we don't know
  212.  
  213.     if (m_pIPrint == NULL)
  214.     {
  215.         // QI for it
  216.         m_pIPrint = QUERYINTERFACE(m_lpObject, IPrint);
  217.  
  218.         if (m_pIPrint == NULL)
  219.         {
  220.             // if the server isn't running, we'll need to
  221.             // start it in order to print
  222.  
  223.             if (FAILED(::OleRun(m_lpObject)))
  224.                 m_pIPrint = (IPrint*) -1;
  225.             else
  226.                 m_pIPrint = QUERYINTERFACE(m_lpObject, IPrint);
  227.         }
  228.     }
  229.  
  230.     return (m_pIPrint != NULL && m_pIPrint != (IPrint*) -1);
  231. }
  232.  
  233. BOOL COleDocObjectItem::GetPageCount(LPLONG pnFirstPage, LPLONG pcPages)
  234. {
  235.     if (!SupportsIPrint())
  236.         return FALSE;
  237.  
  238.     //WINBUG: The proxy in DOCOBJ.DLL is broken; it doesn't allow
  239.     // NULL parameters to IPrint::GetPageInfo(), even though the spec
  240.     // says it should.
  241.  
  242.     LONG lPages;
  243.     LONG lFirstPage;
  244.  
  245.     HRESULT hr = m_pIPrint->GetPageInfo(&lFirstPage, &lPages);
  246.  
  247.     if (pnFirstPage != NULL)
  248.         *pnFirstPage = lFirstPage;
  249.     if (pcPages != NULL)
  250.         *pcPages = lPages;
  251.  
  252.     if (SUCCEEDED(hr))
  253.         return TRUE;
  254.     else
  255.         return FALSE;
  256. }
  257.  
  258.  
  259. CMenu* COleDocObjectItem::GetHelpMenu(UINT& nPosition)
  260. {
  261.     CFrameWnd* pFrame = m_pView->GetTopLevelFrame();
  262.     CMenu* pMenuFrame = CMenu::FromHandle(pFrame->m_hMenuDefault);
  263.  
  264.     if (pMenuFrame != NULL)
  265.         nPosition = pMenuFrame->GetMenuItemCount() -1;
  266.  
  267.     return pMenuFrame;
  268. }
  269.  
  270. void COleDocObjectItem::OnInsertMenus(CMenu* pMenuShared,
  271.     LPOLEMENUGROUPWIDTHS lpMenuWidths)
  272. {
  273.     ASSERT_VALID(this);
  274.     ASSERT_VALID(pMenuShared);
  275.     ASSERT(AfxIsValidAddress(lpMenuWidths, sizeof(OLEMENUGROUPWIDTHS)));
  276.  
  277.     // initialize the group widths array
  278.     lpMenuWidths->width[0] = 1;
  279.     lpMenuWidths->width[2] = 0;
  280.     lpMenuWidths->width[4] = 0;
  281.  
  282.     // get menu from document template
  283.     CDocTemplate* pTemplate = GetDocument()->GetDocTemplate();
  284.     HMENU hMenuOLE = pTemplate->m_hMenuInPlace;
  285.  
  286.     // only copy the popups if there is a menu loaded
  287.     if (hMenuOLE == NULL)
  288.         return;
  289.  
  290.     UINT nItem;
  291.     CMenu* pMenuFrame = GetHelpMenu(nItem);
  292.  
  293.     if (pMenuFrame != NULL)
  294.     {
  295.         CString strHelpMenuName;
  296.         int nSeparator = pMenuFrame->GetMenuString(nItem,
  297.                 strHelpMenuName, MF_BYPOSITION);
  298.         if (nSeparator == 0)
  299.         {
  300.             TRACE0("Error: COleDocObjectItem::OnInsertMenus() found no help menu!\n");
  301.             return;
  302.         }
  303.  
  304.         CString strTearOffName;
  305.         strTearOffName.Format(_T("%s %s"), AfxGetAppName(), strHelpMenuName);
  306.         strTearOffName.Remove('&');
  307.  
  308.         // get the normal frame menu
  309.         int nCount = pMenuFrame->GetMenuItemCount();
  310.         HMENU hMenu = GetSubMenu(pMenuFrame->m_hMenu, nCount-1);
  311.  
  312.         // clean up old menu and allocate a new one
  313.         if (m_pHelpPopupMenu == NULL)
  314.         {
  315.             m_pHelpPopupMenu = new CMenu;
  316.  
  317.             // create new sub-popup menu and add container's Help tearoff
  318.             // then add help menu from main window
  319.             m_pHelpPopupMenu->CreateMenu();
  320.             m_pHelpPopupMenu->InsertMenu((UINT) -1, MF_BYPOSITION | MF_POPUP,
  321.                 (UINT) hMenu, strTearOffName);
  322.         }
  323.  
  324.         pMenuShared->InsertMenu(1, MF_BYPOSITION | MF_POPUP,
  325.             (UINT) m_pHelpPopupMenu->m_hMenu, strHelpMenuName);
  326.  
  327.         // tell the object we added our Help menu
  328.         lpMenuWidths->width[5] = 1;
  329.     }
  330.  
  331.     // insert our menu items and adjust group widths array
  332.     AfxMergeMenus(pMenuShared->GetSafeHmenu(), hMenuOLE,
  333.         &lpMenuWidths->width[0], 0);
  334. }
  335.  
  336. void COleDocObjectItem::OnRemoveMenus(CMenu *pMenuShared)
  337. {
  338.     int cItemsShared = pMenuShared->GetMenuItemCount();
  339.     if (cItemsShared != 0)
  340.     {
  341.         CMenu *pMenuHelp = pMenuShared->GetSubMenu(cItemsShared - 1);
  342.  
  343.         int cItemsHelp = pMenuHelp->GetMenuItemCount();
  344.         int nItem;
  345.         for (nItem = cItemsHelp-1; nItem > 0; nItem--)
  346.             pMenuHelp->DeleteMenu(nItem, MF_BYPOSITION);
  347.  
  348.         pMenuShared->RemoveMenu(cItemsShared - 1, MF_BYPOSITION);
  349.     }
  350.  
  351.     COleClientItem::OnRemoveMenus(pMenuShared);
  352. }
  353.  
  354. BOOL COleDocObjectItem::OnPreparePrinting(CView* pCaller,
  355.     CPrintInfo* pInfo, BOOL bPrintAll)
  356. {
  357.     LONG lDocObjectPages = 0;
  358.  
  359.     CDocument* pDoc = pCaller->GetDocument();
  360.     COleDocument* pOleDoc = DYNAMIC_DOWNCAST(COleDocument, pDoc);
  361.     if (pOleDoc == NULL)
  362.         return FALSE;
  363.  
  364.     POSITION pos = pOleDoc->GetStartPosition();
  365.     while (pos != NULL)
  366.     {
  367.         COleClientItem* pItem = pOleDoc->GetNextClientItem(pos);
  368.         COleDocObjectItem* pDocItem =
  369.             DYNAMIC_DOWNCAST(COleDocObjectItem, pItem);
  370.         if (pDocItem == NULL)
  371.             continue;
  372.  
  373.         // if this isn't the view, continue
  374.         if (!bPrintAll)
  375.         {
  376.             if (pItem->m_pView == NULL ||
  377.                  pItem->m_pView->m_hWnd != pCaller->m_hWnd)
  378.                 continue;
  379.         }
  380.  
  381.         if (pDocItem->SupportsIPrint())
  382.         {
  383.             LONG lThisObjectPages;
  384.             if (pDocItem->GetPageCount(NULL, &lThisObjectPages))
  385.                 lDocObjectPages += lThisObjectPages;
  386.             pInfo->m_bDocObject = TRUE;
  387.         }
  388.         else
  389.             lDocObjectPages++;
  390.  
  391.         if (!bPrintAll)
  392.             break;
  393.     }
  394.  
  395.     if (lDocObjectPages > 0)
  396.     {
  397.         UINT nMaxPage = pInfo->GetMaxPage();
  398.  
  399.         // set the page count; increment it if previously set
  400.         if (nMaxPage == 0xFFFF)
  401.             pInfo->SetMaxPage(lDocObjectPages);
  402.         else
  403.             pInfo->SetMaxPage(nMaxPage + lDocObjectPages);
  404.         pInfo->m_bDocObject = TRUE;
  405.     }
  406.  
  407.     if (pInfo->m_bDocObject)
  408.     {
  409.         // we can't show the "selection" button for DocObjects
  410.         pInfo->m_pPD->m_pd.Flags |= PD_NOSELECTION;
  411.  
  412.         // if it's a doc object, and we're printing all, then we
  413.         // shouldn't show the selection
  414.         if (bPrintAll)
  415.             pInfo->m_pPD->m_pd.Flags |= PD_NOPAGENUMS;
  416.     }
  417.  
  418.     return TRUE;
  419. }
  420.  
  421. void COleDocObjectItem::OnPrint(CView* pCaller, CPrintInfo* pInfo,
  422.     BOOL bPrintAll)
  423. {
  424.     // Note that this function ignores pInfo->m_nCurPage, and will always
  425.     // print the whole range of pages in the CPrintInfo object. That's
  426.     // because DocObjects don't support any mechanism to _continue_
  427.     // printing to an existing print job.
  428.  
  429.     CDocument* pDoc = pCaller->GetDocument();
  430.     COleDocument* pOleDoc = DYNAMIC_DOWNCAST(COleDocument, pDoc);
  431.     if (pOleDoc == NULL)
  432.         return;
  433.  
  434.     POSITION pos = pOleDoc->GetStartPosition();
  435.     while (pos != NULL)
  436.     {
  437.         COleClientItem* pItem = pOleDoc->GetNextClientItem(pos);
  438.         COleDocObjectItem* pDocItem = DYNAMIC_DOWNCAST(COleDocObjectItem, pItem);
  439.         if (pDocItem == NULL)
  440.             continue;
  441.  
  442.         // if this isn't the view, continue
  443.         if (!bPrintAll)
  444.         {
  445.             if (pItem->m_pView == NULL || pItem->m_pView->m_hWnd != pCaller->m_hWnd)
  446.                 continue;
  447.         }
  448.  
  449.         HRESULT hrThisPage = E_UNEXPECTED;
  450.  
  451.         if (pDocItem->SupportsIPrint())
  452.         {
  453.             DVTARGETDEVICE* pTargetDevice = NULL;
  454.             LPDEVNAMES lpDevNames = NULL;
  455.             LPDEVMODE lpDevMode = NULL;
  456.  
  457.             lpDevNames = (LPDEVNAMES) GlobalLock(pInfo->m_pPD->m_pd.hDevNames);
  458.             if (lpDevNames != NULL)
  459.             {
  460.                 lpDevMode = (LPDEVMODE) GlobalLock(pInfo->m_pPD->m_pd.hDevMode);
  461.                 if (lpDevMode != NULL)
  462.                 {
  463.                     pTargetDevice = _AfxOleCreateTargetDevice(lpDevNames, lpDevMode);
  464.                     if (pTargetDevice != NULL)
  465.                     {
  466.                         PAGESET* pps = (PAGESET*) CoTaskMemAlloc(sizeof(PAGESET));
  467.                         if (pps != NULL)
  468.                         {
  469.                             pps->cbStruct = sizeof(PAGESET);
  470.                             ASSERT((pps->cbStruct % 4) == 0);
  471.                             pps->fOddPages = TRUE;
  472.                             pps->fEvenPages = TRUE;
  473.                             pps->cPageRange = 1;
  474.                             pps->rgPages[0].nFromPage = pInfo->GetFromPage();
  475.                             pps->rgPages[0].nToPage = pInfo->GetToPage();
  476.  
  477.                             LONG lLastPage = pps->rgPages[0].nFromPage;
  478.                             LONG lPagesPrinted;
  479.  
  480.                             DWORD dwFlags = PRINTFLAG_RECOMPOSETODEVICE;
  481.  
  482.                             if (pInfo->m_pPD->m_pd.Flags & PD_PRINTTOFILE)
  483.                                 dwFlags |= PRINTFLAG_PRINTTOFILE;
  484.  
  485.                             hrThisPage = pDocItem->m_pIPrint->Print(dwFlags,
  486.                                     &pTargetDevice, &pps, NULL, NULL,
  487.                                     pInfo->m_nCurPage, &lPagesPrinted,
  488.                                     &lLastPage);
  489.  
  490.                             if (!SUCCEEDED(hrThisPage))
  491.                                 TRACE1("IPrint::Print() returned %8.8X\n", hrThisPage);
  492.                             CoTaskMemFree(pps);
  493.                         }
  494.                         CoTaskMemFree(pTargetDevice);
  495.                     }
  496.                     GlobalUnlock(pInfo->m_pPD->m_pd.hDevMode);
  497.                 }
  498.                 GlobalUnlock(pInfo->m_pPD->m_pd.hDevNames);
  499.             }
  500.         }
  501.         else
  502.         {
  503.             // try through IOleCommandTarget
  504.  
  505.             hrThisPage = pDocItem->ExecCommand(OLECMDID_PRINT);
  506.             if (!SUCCEEDED(hrThisPage))
  507.                 TRACE1("IOleCommandTarget::Exec() returned %8.8X\n", hrThisPage);
  508.         }
  509.     }
  510.  
  511.     return;
  512. }
  513.