home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / olecli2.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-16  |  40.1 KB  |  1,577 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 AFX_OLE2_SEG
  14. #pragma code_seg(AFX_OLE2_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // COleFrameHook Construction & Destruction
  26.  
  27. COleFrameHook::COleFrameHook(CFrameWnd* pFrameWnd, COleClientItem* pItem)
  28. {
  29.     ASSERT_VALID(pItem);
  30.     ASSERT_VALID(pFrameWnd);
  31.  
  32.     m_lpActiveObject = NULL;
  33.     m_pActiveItem = pItem;
  34.     m_pFrameWnd = pFrameWnd;
  35.     m_hWnd = pFrameWnd->m_hWnd;
  36.     m_bToolBarHidden = FALSE;
  37.     m_hAccelTable = NULL;
  38.     m_bInModalState = FALSE;
  39.     m_nModelessCount = 0;
  40.     pFrameWnd->m_pNotifyHook = this;    // assume start out hooked
  41.  
  42.     ASSERT_VALID(this);
  43. }
  44.  
  45. COleFrameHook::~COleFrameHook()
  46. {
  47.     if (m_pFrameWnd != NULL)
  48.     {
  49.         ASSERT_VALID(m_pFrameWnd);
  50.         if (m_pFrameWnd->m_pNotifyHook == this)
  51.             m_pFrameWnd->m_pNotifyHook = NULL;
  52.     }
  53.  
  54.     ASSERT_VALID(this);
  55. }
  56.  
  57. /////////////////////////////////////////////////////////////////////////////
  58. // COleFrameHook overrides
  59.  
  60. void COleFrameHook::OnRecalcLayout()
  61. {
  62.     ASSERT_VALID(this);
  63.  
  64.     if (m_lpActiveObject == NULL)
  65.         return;
  66.  
  67.     // get current border size (without current server control bars)
  68.     RECT rectBorder;
  69.     m_pFrameWnd->NegotiateBorderSpace(CFrameWnd::borderGet, &rectBorder);
  70.  
  71.     // allow server to resize/move its control bars
  72.     m_lpActiveObject->ResizeBorder(&rectBorder, &m_xOleInPlaceFrame,
  73.         m_pActiveItem->m_pInPlaceFrame == this);
  74. }
  75.  
  76. BOOL COleFrameHook::OnDocActivate(BOOL bActive)
  77. {
  78.     ASSERT_VALID(this);
  79.  
  80.     if (m_lpActiveObject == NULL)
  81.         return TRUE;
  82.  
  83.     // allow server to do document activation related actions
  84.     m_lpActiveObject->OnDocWindowActivate(bActive);
  85.  
  86.     // make sure window caption gets updated later
  87.     COleFrameHook* pNotifyHook = m_pActiveItem->m_pInPlaceFrame;
  88.     pNotifyHook->m_pFrameWnd->DelayUpdateFrameTitle();
  89.  
  90.     if (!bActive)
  91.     {
  92.         // clear border space
  93.         pNotifyHook->m_xOleInPlaceFrame.SetBorderSpace(NULL);
  94.         if (m_pActiveItem->m_pInPlaceDoc != NULL)
  95.             m_pActiveItem->m_pInPlaceDoc->m_xOleInPlaceFrame.SetBorderSpace(NULL);
  96.  
  97.         // remove the menu hook when the doc is not active
  98.         pNotifyHook->m_xOleInPlaceFrame.SetMenu(NULL, NULL, NULL);
  99.  
  100.         // unhook top-level frame if not needed
  101.         if (pNotifyHook != this)
  102.         {
  103.             // shouldn't be removing some other hook
  104.             ASSERT(pNotifyHook->m_pFrameWnd->m_pNotifyHook == pNotifyHook);
  105.             pNotifyHook->m_pFrameWnd->m_pNotifyHook = NULL;
  106.         }
  107.     }
  108.     else
  109.     {
  110.         // rehook top-level frame if necessary (no effect if top-level == doc-level)
  111.         pNotifyHook->m_pFrameWnd->m_pNotifyHook = pNotifyHook;
  112.     }
  113.  
  114.     // don't do default if activating
  115.     return bActive;
  116. }
  117.  
  118. BOOL COleFrameHook::OnContextHelp(BOOL bEnter)
  119. {
  120.     ASSERT_VALID(this);
  121.     if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
  122.         return TRUE;
  123.  
  124.     // allow all servers to enter/exit context sensitive help mode
  125.     return NotifyAllInPlace(bEnter, &COleFrameHook::DoContextSensitiveHelp);
  126. }
  127.  
  128. /////////////////////////////////////////////////////////////////////////////
  129. // COleFrameHook callbacks for the top-level frame
  130.  
  131. BOOL COleFrameHook::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
  132. {
  133.     UNUSED_ALWAYS(nFlags);
  134.     UNUSED_ALWAYS(nItemID);
  135.  
  136.     // if we're over a docobject item, we need to reflect messages
  137.  
  138.     COleDocObjectItem* pActiveDocObjectItem = DYNAMIC_DOWNCAST(COleDocObjectItem, m_pActiveItem);
  139.     if (pActiveDocObjectItem != NULL)
  140.     {
  141.         CWnd* pWnd = pActiveDocObjectItem->GetInPlaceWindow();
  142.  
  143.         // if we're popping up a menu, figure out what menu is
  144.         // apparing; if it's in the help menu and it's not the
  145.         // first element, it's the object's menu.
  146.  
  147.         if (nFlags & MF_POPUP)
  148.         {
  149.             if (pActiveDocObjectItem->m_pHelpPopupMenu->GetSafeHmenu() ==
  150.                     hSysMenu)
  151.             {
  152.                 pActiveDocObjectItem->m_bInHelpMenu = (nItemID != 0);
  153.  
  154.                 if (pActiveDocObjectItem->m_bInHelpMenu && pWnd != NULL)
  155.                 {
  156.                     pWnd->SendMessage(WM_MENUSELECT,
  157.                         MAKEWPARAM(nItemID, nFlags), (LPARAM) hSysMenu);
  158.                     return TRUE;
  159.                 }
  160.             }
  161.         }
  162.         else
  163.         {
  164.             if (pActiveDocObjectItem->m_bInHelpMenu && pWnd != NULL)
  165.             {
  166.                 pWnd->SendMessage(WM_MENUSELECT,
  167.                     MAKEWPARAM(nItemID, nFlags), (LPARAM) hSysMenu);
  168.                 return TRUE;
  169.             }
  170.         }
  171.     }
  172.  
  173.     return FALSE;
  174. }
  175.  
  176. void COleFrameHook::OnInitMenu(CMenu* pMenu)
  177. {
  178.     UNUSED_ALWAYS(pMenu);
  179.  
  180.     // reset the help menu flag when a new menu is opening
  181.  
  182.     COleDocObjectItem* pActiveDocObjectItem = DYNAMIC_DOWNCAST(COleDocObjectItem, m_pActiveItem);
  183.     if (pActiveDocObjectItem != NULL)
  184.         pActiveDocObjectItem->m_bInHelpMenu = FALSE;
  185.  
  186.     return;
  187. }
  188.  
  189. BOOL COleFrameHook::OnInitMenuPopup(CMenu* pMenu, int nIndex, BOOL bSysMenu)
  190. {
  191.     UNUSED_ALWAYS(nIndex);
  192.  
  193.     if (bSysMenu)
  194.         return FALSE;
  195.  
  196.     COleDocObjectItem* pActiveDocObjectItem = DYNAMIC_DOWNCAST(COleDocObjectItem, m_pActiveItem);
  197.     if (pActiveDocObjectItem == NULL)
  198.         return FALSE;
  199.  
  200.     // if we're popping up a new menu, for the object,
  201.     // reflect the message and don't let MFC handle it
  202.     // with ON_COMMAND_UI stuff
  203.  
  204.     if (pActiveDocObjectItem->m_bInHelpMenu)
  205.     {
  206.         CWnd* pWnd = pActiveDocObjectItem->GetInPlaceWindow();
  207.         if (pWnd != NULL)
  208.         {
  209.             pWnd->SendMessage(WM_INITMENUPOPUP, (WPARAM) pMenu->m_hMenu,
  210.                 MAKELPARAM(nIndex, bSysMenu));
  211.             return TRUE;
  212.         }
  213.     }
  214.  
  215.     return FALSE;
  216. }
  217.  
  218. BOOL COleFrameHook::OnPreTranslateMessage(MSG* pMsg)
  219. {
  220.     ASSERT_VALID(this);
  221.  
  222.     if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
  223.         return FALSE;
  224.  
  225.     // allow server to translate accelerators
  226.     if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
  227.         return m_lpActiveObject->TranslateAccelerator(pMsg) == S_OK;
  228.  
  229.     // if we've finally gotten a WM_COMMAND message, make sure
  230.     // that it is appropriately reflected to the docobject
  231.  
  232.     if (pMsg->message == WM_COMMAND)
  233.     {
  234.         COleDocObjectItem* pActiveDocObjectItem = DYNAMIC_DOWNCAST(COleDocObjectItem, m_pActiveItem);
  235.         if (pActiveDocObjectItem != NULL)
  236.         {
  237.             LRESULT lResult = 0;
  238.             if (pActiveDocObjectItem->m_bInHelpMenu)
  239.             {
  240.                 CWnd* pWnd = pActiveDocObjectItem->GetInPlaceWindow();
  241.                 if (pWnd != NULL)
  242.                     lResult = pWnd->SendMessage(WM_COMMAND, pMsg->wParam, pMsg->lParam);
  243.             }
  244.             return lResult;
  245.         }
  246.     }
  247.  
  248.     return FALSE;
  249. }
  250.  
  251. void COleFrameHook::OnActivate(BOOL bActive)
  252. {
  253.     ASSERT_VALID(this);
  254.  
  255.     if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
  256.         return;
  257.  
  258.     if (m_pFrameWnd->IsWindowEnabled())
  259.     {
  260.         // allow active server to do frame level activation
  261.         m_lpActiveObject->OnFrameWindowActivate(bActive);
  262.     }
  263. }
  264.  
  265. void COleFrameHook::OnEnableModeless(BOOL bEnable)
  266. {
  267.     ASSERT_VALID(this);
  268.  
  269.     if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
  270.         return;
  271.  
  272.     // allow server to disable/enable modeless dialogs
  273.     NotifyAllInPlace(bEnable, &COleFrameHook::DoEnableModeless);
  274. }
  275.  
  276. BOOL COleFrameHook::OnUpdateFrameTitle()
  277. {
  278.     ASSERT_VALID(this);
  279.     ASSERT_VALID(m_pActiveItem);
  280.  
  281.     if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
  282.         return FALSE;
  283.  
  284.     return m_pActiveItem->OnUpdateFrameTitle();
  285. }
  286.  
  287. void COleFrameHook::OnPaletteChanged(CWnd* pFocusWnd)
  288. {
  289.     CWnd* pWnd = m_pActiveItem->GetInPlaceWindow();
  290.     if (pWnd != NULL)
  291.         pWnd->SendMessage(WM_PALETTECHANGED, (WPARAM)pFocusWnd->GetSafeHwnd());
  292. }
  293.  
  294. BOOL COleFrameHook::OnQueryNewPalette()
  295. {
  296.     CWnd* pWnd = m_pActiveItem->GetInPlaceWindow();
  297.     if (pWnd != NULL)
  298.         return pWnd->SendMessage(WM_QUERYNEWPALETTE);
  299.     return FALSE;
  300. }
  301.  
  302. /////////////////////////////////////////////////////////////////////////////
  303. // Helpers for notifications that have to affect all in-place windows
  304.  
  305. BOOL COleFrameHook::NotifyAllInPlace(
  306.     BOOL bParam, BOOL (COleFrameHook::*pNotifyFunc)(BOOL bParam))
  307. {
  308.     ASSERT_VALID(this);
  309.     HWND hWndFrame = m_hWnd;
  310.     CWinApp* pApp = AfxGetApp();
  311.  
  312.     // no doc manager - no templates
  313.     if (pApp->m_pDocManager == NULL)
  314.         return TRUE;
  315.  
  316.     // walk all templates in the application
  317.     CDocTemplate* pTemplate;
  318.     POSITION pos = pApp->m_pDocManager->GetFirstDocTemplatePosition();
  319.     while (pos != NULL)
  320.     {
  321.         pTemplate = pApp->m_pDocManager->GetNextDocTemplate(pos);
  322.         ASSERT_VALID(pTemplate);
  323.         ASSERT_KINDOF(CDocTemplate, pTemplate);
  324.  
  325.         // walk all documents in the template
  326.         POSITION pos2 = pTemplate->GetFirstDocPosition();
  327.         while (pos2)
  328.         {
  329.             COleDocument* pDoc = (COleDocument*)pTemplate->GetNextDoc(pos2);
  330.             ASSERT_VALID(pDoc);
  331.             if (pDoc->IsKindOf(RUNTIME_CLASS(COleDocument)))
  332.             {
  333.                 // walk all COleClientItem objects in the document
  334.                 COleClientItem* pItem;
  335.                 POSITION pos3 = pDoc->GetStartPosition();
  336.                 while ((pItem = pDoc->GetNextClientItem(pos3)) != NULL)
  337.                 {
  338.                     if (pItem->m_pInPlaceFrame != NULL &&
  339.                         pItem->m_pInPlaceFrame->m_lpActiveObject != NULL &&
  340.                         pItem->m_pView != NULL &&
  341.                         AfxIsDescendant(hWndFrame, pItem->m_pView->m_hWnd))
  342.                     {
  343.                         // Whew!  Found an in-place active item that is
  344.                         //  part of this frame window hierarchy.
  345.                         COleFrameHook* pNotifyHook = pItem->m_pInPlaceFrame;
  346.                         if (!(pNotifyHook->*pNotifyFunc)(bParam))
  347.                             return FALSE;
  348.                     }
  349.                 }
  350.             }
  351.         }
  352.     }
  353.     return TRUE;
  354. }
  355.  
  356. BOOL COleFrameHook::DoContextSensitiveHelp(BOOL bEnter)
  357. {
  358.     ASSERT_VALID(this);
  359.     ASSERT(m_lpActiveObject != NULL);
  360.  
  361.     return !FAILED(m_lpActiveObject->ContextSensitiveHelp(bEnter));
  362. }
  363.  
  364. BOOL COleFrameHook::DoEnableModeless(BOOL bEnable)
  365. {
  366.     ASSERT_VALID(this);
  367.     ASSERT(m_lpActiveObject != NULL);
  368.  
  369.     // allow server to enable/disable any modeless windows
  370.     if (!bEnable)
  371.     {
  372.         if (m_nModelessCount++ == 0)
  373.             m_lpActiveObject->EnableModeless(FALSE);
  374.     }
  375.     else
  376.     {
  377.         if (m_nModelessCount != 0 && --m_nModelessCount == 0)
  378.             m_lpActiveObject->EnableModeless(TRUE);
  379.     }
  380.     return TRUE;
  381. }
  382.  
  383. /////////////////////////////////////////////////////////////////////////////
  384. // COleClientItem - default in-place activation implementation
  385.  
  386. BOOL COleClientItem::CanActivate()
  387. {
  388.     // don't allow in-place activations with iconic aspect items
  389.     if (m_nDrawAspect == DVASPECT_ICON)
  390.         return FALSE;
  391.  
  392.     // if no view has been set, attempt to find suitable one.
  393.     //  (necessary to get links to embeddings to work correctly)
  394.     if (m_pView == NULL)
  395.     {
  396.         // only use pActivateView if this item is in same document
  397.         _AFX_OLE_STATE* pOleState = _afxOleState;
  398.         if (pOleState->m_pActivateView != NULL &&
  399.             pOleState->m_pActivateView->GetDocument() != GetDocument())
  400.         {
  401.             pOleState->m_pActivateView = NULL;   // not in same document
  402.         }
  403.  
  404.         CView* pView = pOleState->m_pActivateView;
  405.         if (pView == NULL)
  406.         {
  407.             // no routing view available - try to use the one with focus
  408.             CWnd* pWnd = CWnd::GetFocus();
  409.             while (pWnd != NULL && !pWnd->IsKindOf(RUNTIME_CLASS(CView)))
  410.                 pWnd = pWnd->GetParent();
  411.             pView = STATIC_DOWNCAST(CView, pWnd);
  412.  
  413.             if (pView == NULL)
  414.             {
  415.                 // still no routing view available - just use first one
  416.                 COleDocument* pDoc = GetDocument();
  417.                 POSITION pos = pDoc->GetFirstViewPosition();
  418.                 pView = pDoc->GetNextView(pos);
  419.             }
  420.         }
  421.         m_pView = pView;
  422.     }
  423.  
  424.     return m_pView->GetSafeHwnd() != NULL;
  425. }
  426.  
  427. void COleClientItem::OnActivate()
  428. {
  429.     ASSERT_VALID(this);
  430.  
  431.     // it is necessary to lock the object when it is in-place
  432.     //  (without this, a link to an embedding may disconnect unexpectedly)
  433.     if (!m_bLocked)
  434.     {
  435.         OleLockRunning(m_lpObject, TRUE, FALSE);
  436.         m_bLocked = TRUE;
  437.     }
  438.  
  439.     // notify the item of the state change
  440.     if (m_nItemState != activeState)
  441.     {
  442.         OnChange(OLE_CHANGED_STATE, (DWORD)activeState);
  443.         m_nItemState = activeState;
  444.     }
  445. }
  446.  
  447. void COleClientItem::OnActivateUI()
  448. {
  449.     ASSERT_VALID(this);
  450.  
  451.     // notify the item of the state change
  452.     if (m_nItemState != activeUIState)
  453.     {
  454.         OnChange(OLE_CHANGED_STATE, (DWORD)activeUIState);
  455.         m_nItemState = activeUIState;
  456.     }
  457.  
  458.     // the container window must have WS_CLIPCHILDREN set
  459.     ASSERT_VALID(m_pView);
  460.     m_dwContainerStyle = m_pView->GetStyle();
  461.     m_pView->ModifyStyle(0, WS_CLIPCHILDREN);
  462.  
  463.     // cache the server's HWND for later
  464.     LPOLEINPLACEOBJECT lpInPlaceObject =
  465.         QUERYINTERFACE(m_lpObject, IOleInPlaceObject);
  466.     ASSERT(lpInPlaceObject != NULL);
  467.  
  468.     // get the HWND for the in-place active object
  469.     HWND hWnd;
  470.     if (lpInPlaceObject->GetWindow(&hWnd) != S_OK)
  471.         hWnd = NULL;
  472.     lpInPlaceObject->Release();
  473.     m_hWndServer = hWnd;
  474.  
  475.     // make sure top-level frame is hooked
  476.     if (m_pInPlaceFrame != NULL)
  477.     {
  478.         ASSERT_VALID(m_pInPlaceFrame->m_pFrameWnd);
  479.         m_pInPlaceFrame->m_pFrameWnd->m_pNotifyHook = m_pInPlaceFrame;
  480.     }
  481.     // make sure doc-level frame is hooked
  482.     if (m_pInPlaceDoc != NULL)
  483.     {
  484.         ASSERT_VALID(m_pInPlaceDoc->m_pFrameWnd);
  485.         m_pInPlaceDoc->m_pFrameWnd->m_pNotifyHook = m_pInPlaceDoc;
  486.     }
  487. }
  488.  
  489. BOOL COleClientItem::OnShowControlBars(CFrameWnd* pFrameWnd, BOOL bShow)
  490. {
  491.     ASSERT_VALID(pFrameWnd);
  492.     ASSERT_VALID(this);
  493.  
  494.     // show/hide all bars marked with CBRS_HIDE_INPLACE style
  495.     BOOL bResult = FALSE;
  496.     if (bShow)
  497.     {
  498.         POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
  499.         while (pos)
  500.         {
  501.             CControlBar* pBar =
  502.                 (CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);
  503.             ASSERT_VALID(pBar);
  504.             if ((pBar->GetBarStyle() & CBRS_HIDE_INPLACE) &&
  505.                 (pBar->m_nStateFlags & CControlBar::tempHide))
  506.             {
  507.                 pBar->m_nStateFlags &= ~CControlBar::tempHide;
  508.                 pFrameWnd->ShowControlBar(pBar, TRUE, TRUE);
  509.                 bResult = TRUE;
  510.             }
  511.         }
  512.     }
  513.     else
  514.     {
  515.         POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
  516.         while (pos)
  517.         {
  518.             CControlBar* pBar =
  519.                 (CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);
  520.             ASSERT_VALID(pBar);
  521.             if (pBar->IsVisible() && (pBar->GetBarStyle() & CBRS_HIDE_INPLACE))
  522.             {
  523.                 pBar->m_nStateFlags |= CControlBar::tempHide;
  524.                 pFrameWnd->ShowControlBar(pBar, FALSE, TRUE);
  525.                 bResult = TRUE;
  526.             }
  527.         }
  528.     }
  529.     return bResult;
  530. }
  531.  
  532. BOOL COleClientItem::OnGetWindowContext(
  533.     CFrameWnd** ppMainFrame, CFrameWnd** ppDocFrame,
  534.     LPOLEINPLACEFRAMEINFO pFrameInfo)
  535. {
  536.     ASSERT(AfxIsValidAddress(ppMainFrame, sizeof(CFrameWnd*)));
  537.     ASSERT(AfxIsValidAddress(ppDocFrame, sizeof(CFrameWnd*)));
  538.     ASSERT(pFrameInfo == NULL ||
  539.         AfxIsValidAddress(pFrameInfo, sizeof(OLEINPLACEFRAMEINFO)));
  540.     ASSERT_VALID(this);
  541.     ASSERT_VALID(m_pView);
  542.  
  543.     // get main window of application
  544.     *ppMainFrame = m_pView->GetTopLevelFrame();
  545.     ASSERT_VALID(*ppMainFrame);
  546.     ASSERT_KINDOF(CFrameWnd, *ppMainFrame);
  547.  
  548.     // get document window (if there is one)
  549.     CFrameWnd* pDocFrame = m_pView->GetParentFrame();
  550.     if (pDocFrame != *ppMainFrame)
  551.     {
  552.         *ppDocFrame = pDocFrame;
  553.         ASSERT_VALID(*ppDocFrame);
  554.         ASSERT_KINDOF(CFrameWnd, *ppDocFrame);
  555.     }
  556.  
  557.     if (pFrameInfo != NULL)
  558.     {
  559.         // get accelerator table
  560.         CDocTemplate* pTemplate = GetDocument()->GetDocTemplate();
  561.         HACCEL hAccel = pTemplate != NULL ? pTemplate->m_hAccelInPlace : NULL;
  562.         pFrameInfo->cAccelEntries =
  563.             hAccel != NULL ? CopyAcceleratorTable(hAccel, NULL, 0) : 0;
  564.         pFrameInfo->haccel = pFrameInfo->cAccelEntries != 0 ? hAccel : NULL;
  565.         pFrameInfo->hwndFrame = (*ppMainFrame)->m_hWnd;
  566.         pFrameInfo->fMDIApp = *ppDocFrame != NULL;
  567.     }
  568.     return TRUE;
  569. }
  570.  
  571. BOOL COleClientItem::OnScrollBy(CSize sizeExtent)
  572. {
  573.     ASSERT_VALID(this);
  574.     ASSERT_VALID(m_pView);
  575.  
  576.     // scroll through splitter or view
  577.     CSplitterWnd* pSplitter = CView::GetParentSplitter(m_pView, FALSE);
  578.     BOOL bResult;
  579.     if (pSplitter != NULL)
  580.         bResult = pSplitter->DoScrollBy(m_pView, sizeExtent);
  581.     else
  582.         bResult = m_pView->OnScrollBy(sizeExtent);
  583.  
  584.     return bResult;
  585. }
  586.  
  587. void COleClientItem::OnDeactivateUI(BOOL /*bUndoable*/)
  588. {
  589.     ASSERT_VALID(this);
  590.  
  591.     // notify the item of the state change
  592.     if (m_nItemState != activeState)
  593.     {
  594.         OnChange(OLE_CHANGED_STATE, (DWORD)activeState);
  595.         m_nItemState = activeState;
  596.     }
  597.  
  598.     if (m_pView != NULL && m_pDocument->GetFirstViewPosition())
  599.     {
  600.         // restore container window's WS_CLIPCHILDREN bit...
  601.         ASSERT_VALID(m_pView);
  602.         m_pView->ModifyStyle(WS_CLIPCHILDREN, m_dwContainerStyle & WS_CLIPCHILDREN);
  603.     }
  604.  
  605.     // restore original user interface on the frame window
  606.     CFrameWnd* pMainFrame;
  607.     CFrameWnd* pDocFrame = NULL;
  608.     if (OnGetWindowContext(&pMainFrame, &pDocFrame, NULL))
  609.     {
  610.         ASSERT_VALID(pMainFrame);
  611.         pMainFrame->DelayUpdateFrameTitle();
  612.         if (pMainFrame->NegotiateBorderSpace(CFrameWnd::borderSet, NULL))
  613.             pMainFrame->DelayRecalcLayout();
  614.  
  615.         // restore original user interface on the document window
  616.         if (pDocFrame != NULL)
  617.         {
  618.             pDocFrame->DelayUpdateFrameTitle();
  619.             if (pDocFrame->NegotiateBorderSpace(CFrameWnd::borderSet, NULL))
  620.                 pDocFrame->DelayRecalcLayout();
  621.         }
  622.     }
  623.  
  624.     // cleanup frame interfaces allocated in GetWindowContext
  625.     if (m_pInPlaceFrame != NULL)
  626.     {
  627.         OnShowControlBars(m_pInPlaceFrame->m_pFrameWnd, TRUE);
  628.  
  629.         // release OLE frame window hooks and allow menu update
  630.         ::OleSetMenuDescriptor(NULL, m_pInPlaceFrame->m_pFrameWnd->m_hWnd,
  631.             NULL, NULL, NULL);
  632.         if (m_pInPlaceDoc != NULL)
  633.         {
  634.             ::OleSetMenuDescriptor(NULL, m_pInPlaceDoc->m_pFrameWnd->m_hWnd,
  635.                 NULL, NULL, NULL);
  636.         }
  637.         m_pInPlaceFrame->m_pFrameWnd->DelayUpdateFrameMenu(NULL);
  638.  
  639.         // unhook from frame window
  640.         if (m_pInPlaceFrame->m_pFrameWnd->m_pNotifyHook == m_pInPlaceFrame)
  641.             m_pInPlaceFrame->m_pFrameWnd->m_pNotifyHook = NULL;
  642.  
  643.         // cleanup document interfaces allocated in GetWindowContext
  644.         if (m_pInPlaceDoc != NULL)
  645.         {
  646.             OnShowControlBars(m_pInPlaceDoc->m_pFrameWnd, TRUE);
  647.  
  648.             // unhook from frame window
  649.             if (m_pInPlaceDoc->m_pFrameWnd->m_pNotifyHook == m_pInPlaceDoc)
  650.                 m_pInPlaceDoc->m_pFrameWnd->m_pNotifyHook = NULL;
  651.         }
  652.     }
  653.  
  654.     // reset server HWND -- no longer necessary
  655.     m_hWndServer = NULL;
  656.  
  657.     CWnd* pWnd = AfxGetMainWnd();
  658.     if (pWnd != NULL)
  659.     {
  660.         // set focus back to the container
  661.         pWnd = pWnd->GetTopLevelParent();
  662.         ASSERT_VALID(pWnd);
  663.         if (::GetActiveWindow() == pWnd->m_hWnd)
  664.             pWnd->SetFocus();
  665.     }
  666. }
  667.  
  668. void COleClientItem::OnDeactivate()
  669. {
  670.     ASSERT_VALID(this);
  671.  
  672.     // notify the item of the state change
  673.     if (m_nItemState != loadedState)
  674.     {
  675.         OnChange(OLE_CHANGED_STATE, (DWORD)loadedState);
  676.         m_nItemState = loadedState;
  677.     }
  678.  
  679.     // cleanup frame interfaces allocated in GetWindowContext
  680.     if (m_pInPlaceFrame != NULL)
  681.     {
  682.         // release in place frame
  683.         if (m_pInPlaceFrame->m_pFrameWnd->m_pNotifyHook == m_pInPlaceFrame)
  684.             m_pInPlaceFrame->m_pFrameWnd->m_pNotifyHook =  NULL;
  685.         m_pInPlaceFrame->InternalRelease();
  686.         m_pInPlaceFrame = NULL;
  687.  
  688.         // cleanup document interfaces allocated in GetWindowContext
  689.         if (m_pInPlaceDoc != NULL)
  690.         {
  691.             // release in place document
  692.             if (m_pInPlaceDoc->m_pFrameWnd->m_pNotifyHook == m_pInPlaceDoc)
  693.                 m_pInPlaceDoc->m_pFrameWnd->m_pNotifyHook = NULL;
  694.             m_pInPlaceDoc->InternalRelease();
  695.             m_pInPlaceDoc = NULL;
  696.         }
  697.     }
  698.  
  699.     // both frame-level and doc-level interfaces should be cleaned up
  700.     ASSERT(m_pInPlaceFrame == NULL);
  701.     ASSERT(m_pInPlaceDoc == NULL);
  702.  
  703.     // no longer need the container window
  704.     m_pView = NULL;
  705. }
  706.  
  707. void COleClientItem::OnDiscardUndoState()
  708. {
  709.     ASSERT_VALID(this);
  710.  
  711.     // default does nothing
  712. }
  713.  
  714. void COleClientItem::OnDeactivateAndUndo()
  715. {
  716.     ASSERT_VALID(this);
  717.  
  718.     DeactivateUI(); // default is to UI deactivate
  719. }
  720.  
  721. BOOL COleClientItem::OnChangeItemPosition(const CRect& rectPos)
  722. {
  723.     if (!IsInPlaceActive())
  724.         return FALSE;
  725.  
  726.     ASSERT_VALID(this);
  727.     ASSERT(AfxIsValidAddress(&rectPos, sizeof(CRect), FALSE));
  728.     ASSERT_VALID(m_pView);
  729.  
  730.     // determine the visible rect based on intersection between client rect
  731.     CRect clipRect;
  732.     OnGetClipRect(clipRect);
  733.     CRect visRect;
  734.     visRect.IntersectRect(clipRect, rectPos);
  735.  
  736.     // advise the server of the new visible rectangle
  737.     if (!visRect.IsRectEmpty())
  738.         return SetItemRects(&rectPos, &clipRect);
  739.  
  740.     return FALSE;
  741. }
  742.  
  743. /////////////////////////////////////////////////////////////////////////////
  744. // IOleInPlaceFrame notifications (default implementation)
  745.  
  746. void COleClientItem::OnInsertMenus(CMenu* pMenuShared,
  747.     LPOLEMENUGROUPWIDTHS lpMenuWidths)
  748. {
  749.     ASSERT_VALID(this);
  750.     ASSERT_VALID(pMenuShared);
  751.     ASSERT(AfxIsValidAddress(lpMenuWidths, sizeof(OLEMENUGROUPWIDTHS)));
  752.  
  753.     // initialize the group widths array
  754.     lpMenuWidths->width[0] = 0;
  755.     lpMenuWidths->width[2] = 0;
  756.     lpMenuWidths->width[4] = 0;
  757.  
  758.     // get menu from document template
  759.     CDocTemplate* pTemplate = GetDocument()->GetDocTemplate();
  760.     HMENU hMenuOLE = pTemplate->m_hMenuInPlace;
  761.  
  762.     // only copy the popups if there is a menu loaded
  763.     if (hMenuOLE == NULL)
  764.         return;
  765.  
  766.     // insert our menu items and adjust group widths array
  767.     AfxMergeMenus(pMenuShared->GetSafeHmenu(), hMenuOLE, &lpMenuWidths->width[0], 0);
  768. }
  769.  
  770. void COleClientItem::OnSetMenu(CMenu* pMenuShared, HOLEMENU holemenu,
  771.     HWND hwndActiveObject)
  772. {
  773.     ASSERT_VALID(this);
  774.     ASSERT(m_pInPlaceFrame != NULL);
  775.     ASSERT(m_pInPlaceFrame->m_pFrameWnd != NULL);
  776.  
  777.     // don't set the doc is active
  778.     CFrameWnd* pFrameWnd = m_pInPlaceFrame->m_pFrameWnd;
  779.     ASSERT_VALID(pFrameWnd);
  780.     if (m_pInPlaceDoc != NULL &&
  781.         m_pInPlaceDoc->m_pFrameWnd != pFrameWnd->GetActiveFrame())
  782.     {
  783.         return;
  784.     }
  785.  
  786.     // update the menu
  787.     pFrameWnd->DelayUpdateFrameMenu(pMenuShared->GetSafeHmenu());
  788.  
  789.     // enable/disable the OLE command routing hook
  790.     ::OleSetMenuDescriptor(holemenu, pFrameWnd->m_hWnd,
  791.         hwndActiveObject, NULL, NULL);
  792.     if (m_pInPlaceDoc != NULL)
  793.     {
  794.         pFrameWnd = m_pInPlaceDoc->m_pFrameWnd;
  795.         ASSERT_VALID(pFrameWnd);
  796.         ::OleSetMenuDescriptor(holemenu, pFrameWnd->m_hWnd,
  797.             hwndActiveObject, NULL, NULL);
  798.     }
  799. }
  800.  
  801. void COleClientItem::OnRemoveMenus(CMenu* pMenuShared)
  802. {
  803.     ASSERT_VALID(this);
  804.     ASSERT_VALID(pMenuShared);
  805.  
  806.     // get menu from document template
  807.     CDocTemplate* pTemplate = GetDocument()->GetDocTemplate();
  808.     HMENU hMenuOLE = pTemplate->m_hMenuInPlace;
  809.     if (hMenuOLE == NULL)
  810.         return;
  811.  
  812.     // remove any menu popups originally added in OnInsertMenus
  813.     AfxUnmergeMenus(pMenuShared->GetSafeHmenu(), hMenuOLE);
  814. }
  815.  
  816. BOOL COleClientItem::OnUpdateFrameTitle()
  817. {
  818.     ASSERT_VALID(this);
  819.     return FALSE;
  820. }
  821.  
  822. /////////////////////////////////////////////////////////////////////////////
  823. // In-place Activation operations
  824.  
  825. void COleClientItem::Deactivate()
  826. {
  827.     ASSERT_VALID(this);
  828.     ASSERT(m_lpObject != NULL);
  829.     ASSERT(IsInPlaceActive());
  830.  
  831.     // get IOleInPlaceObject interface
  832.     LPOLEINPLACEOBJECT lpInPlaceObject =
  833.         QUERYINTERFACE(m_lpObject, IOleInPlaceObject);
  834.     if (lpInPlaceObject == NULL)
  835.     {
  836.         Close();    // handle rare failure cases by calling Close
  837.         return;
  838.     }
  839.  
  840.     // call IOleInPlaceObject::InPlaceDeactivate
  841.     m_scLast = lpInPlaceObject->InPlaceDeactivate();
  842.     lpInPlaceObject->Release();
  843.     if (FAILED(m_scLast))
  844.     {
  845.         Close();    // handle rare failure cases by calling Close
  846.         return;
  847.     }
  848.     m_nItemState = loadedState; // just in case server has crashed
  849. }
  850.  
  851. void COleClientItem::DeactivateUI()
  852. {
  853.     ASSERT_VALID(this);
  854.     ASSERT(m_lpObject != NULL);
  855.     ASSERT(GetItemState() == activeUIState);
  856.  
  857.     // get IOleInPlaceObject interface
  858.     LPOLEINPLACEOBJECT lpInPlaceObject =
  859.         QUERYINTERFACE(m_lpObject, IOleInPlaceObject);
  860.     if (lpInPlaceObject == NULL)
  861.     {
  862.         Close();    // handle rare failure cases by calling Close
  863.         return;
  864.     }
  865.  
  866.     // call IOleInPlaceObject::UIDeactivate
  867.     m_scLast = lpInPlaceObject->UIDeactivate();
  868.     lpInPlaceObject->Release();
  869.     if (FAILED(m_scLast))
  870.     {
  871.         Close();    // handle rare failure cases by calling Close
  872.         return;
  873.     }
  874.     if (m_nItemState == activeUIState)
  875.         m_nItemState = activeState; // just in case server has crashed
  876. }
  877.  
  878. BOOL COleClientItem::SetItemRects(LPCRECT lpPosRect, LPCRECT lpClipRect)
  879. {
  880.     ASSERT_VALID(this);
  881.     ASSERT(m_lpObject != NULL);
  882.     ASSERT(IsInPlaceActive());
  883.     ASSERT(lpPosRect == NULL ||
  884.         AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
  885.     ASSERT(lpClipRect == NULL ||
  886.         AfxIsValidAddress(lpClipRect, sizeof(RECT), FALSE));
  887.  
  888.     // get IOleInPlaceObject interface
  889.     LPOLEINPLACEOBJECT lpInPlaceObject =
  890.         QUERYINTERFACE(m_lpObject, IOleInPlaceObject);
  891.     if (lpInPlaceObject == NULL)
  892.         return FALSE;   // perhaps server crashed?
  893.  
  894.     // use OnGetPosRect if rectangle not specified
  895.     CRect rectPos;
  896.     if (lpPosRect == NULL)
  897.     {
  898.         ASSERT(lpClipRect == NULL);
  899.         OnGetItemPosition(rectPos);
  900.         lpPosRect = &rectPos;
  901.     }
  902.  
  903.     // use OnGetClipRect if clipping rectangle not specified
  904.     CRect rectClip;
  905.     if (lpClipRect == NULL)
  906.     {
  907.         OnGetClipRect(rectClip);
  908.         lpClipRect = &rectClip;
  909.     }
  910.     ASSERT(lpPosRect != NULL);
  911.     ASSERT(lpClipRect != NULL);
  912.  
  913.     // notify the server of the new item rectangles
  914.     m_scLast = lpInPlaceObject->SetObjectRects(lpPosRect, lpClipRect);
  915.     lpInPlaceObject->Release();
  916.  
  917.     // remember position rectangle as cached position
  918.     return !FAILED(m_scLast);
  919. }
  920.  
  921. BOOL COleClientItem::ReactivateAndUndo()
  922. {
  923.     ASSERT_VALID(this);
  924.     ASSERT(m_lpObject != NULL);
  925.     ASSERT(IsInPlaceActive());
  926.  
  927.     // get IOleInPlaceObject interface
  928.     LPOLEINPLACEOBJECT lpInPlaceObject =
  929.         QUERYINTERFACE(m_lpObject, IOleInPlaceObject);
  930.     if (lpInPlaceObject == NULL)
  931.     {
  932.         Close();    // handle rare failure cases by calling Close
  933.         return FALSE;
  934.     }
  935.  
  936.     // call IOleInPlaceObject::ReactivateAndUndo
  937.     m_scLast = lpInPlaceObject->ReactivateAndUndo();
  938.     lpInPlaceObject->Release();
  939.     if (FAILED(m_scLast))
  940.     {
  941.         Close();    // handle rare failure cases by calling Close
  942.         return FALSE;
  943.     }
  944.     return TRUE;
  945. }
  946.  
  947. CWnd* COleClientItem::GetInPlaceWindow()
  948. {
  949.     ASSERT_VALID(this);
  950.     ASSERT(m_lpObject != NULL);
  951.  
  952.     // only inplace active items should be asking for the window handle
  953.     if (GetItemState() != activeUIState)
  954.         return NULL;
  955.  
  956.     // handle case of server that just disappears
  957.     if (m_hWndServer != NULL && !::IsWindow(m_hWndServer))
  958.     {
  959.         Close();
  960.         return NULL;
  961.     }
  962.  
  963.     ASSERT(m_hWndServer == NULL || ::IsWindow(m_hWndServer));
  964.     return CWnd::FromHandle(m_hWndServer);
  965. }
  966.  
  967. /////////////////////////////////////////////////////////////////////////////
  968. // COleFrameHook OLE interface implementation
  969.  
  970. BEGIN_INTERFACE_MAP(COleFrameHook, CCmdTarget)
  971.     INTERFACE_PART(COleFrameHook, IID_IOleWindow, OleInPlaceFrame)
  972.     INTERFACE_PART(COleFrameHook, IID_IOleInPlaceUIWindow, OleInPlaceFrame)
  973.     INTERFACE_PART(COleFrameHook, IID_IOleInPlaceFrame, OleInPlaceFrame)
  974. #ifndef _AFXDLL
  975.     INTERFACE_PART(COleFrameHook, IID_IOleCommandTarget, OleCommandTarget)
  976. #endif
  977. END_INTERFACE_MAP()
  978.  
  979. /////////////////////////////////////////////////////////////////////////////
  980. // COleFrameHook::XOleCommandTarget implementation
  981.  
  982. #ifdef _AFXDLL
  983. LPUNKNOWN COleFrameHook::GetInterfaceHook(const void* pIID)
  984. {
  985.     ASSERT(m_pModuleState != NULL);
  986.     if (m_pModuleState->m_dwVersion >= 0x423 &&
  987.         *(IID*)pIID == IID_IOleCommandTarget)
  988.     {
  989.         return &m_xOleCommandTarget;
  990.     }
  991.     return NULL;
  992. }
  993. #endif
  994.  
  995. STDMETHODIMP_(ULONG) COleFrameHook::XOleCommandTarget::AddRef()
  996. {
  997.     METHOD_PROLOGUE_EX_(COleFrameHook, OleCommandTarget)
  998.     return pThis->ExternalAddRef();
  999. }
  1000.  
  1001. STDMETHODIMP_(ULONG) COleFrameHook::XOleCommandTarget::Release()
  1002. {
  1003.     METHOD_PROLOGUE_EX_(COleFrameHook, OleCommandTarget)
  1004.     return pThis->ExternalRelease();
  1005. }
  1006.  
  1007. STDMETHODIMP COleFrameHook::XOleCommandTarget::QueryInterface(
  1008.     REFIID iid, LPVOID* ppvObj)
  1009. {
  1010.     METHOD_PROLOGUE_EX_(COleFrameHook, OleCommandTarget)
  1011.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  1012. }
  1013.  
  1014. STDMETHODIMP COleFrameHook::XOleCommandTarget::Exec(
  1015.    const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt,
  1016.    VARIANTARG* pvarargIn, VARIANTARG* pvarargOut)
  1017. {
  1018.     HRESULT hResult = OLECMDERR_E_UNKNOWNGROUP;
  1019.     METHOD_PROLOGUE_EX_(COleFrameHook, OleCommandTarget)
  1020.  
  1021.     COleDocObjectItem* pActiveDocObjectItem =
  1022.         DYNAMIC_DOWNCAST(COleDocObjectItem, pThis->m_pActiveItem);
  1023.     if (pActiveDocObjectItem != NULL)
  1024.     {
  1025.         hResult = _AfxExecOleCommandHelper(pActiveDocObjectItem,
  1026.             pguidCmdGroup, nCmdID, nCmdExecOpt, pvarargIn, pvarargOut);
  1027.     }
  1028.  
  1029.     return hResult;
  1030. }
  1031.  
  1032. STDMETHODIMP COleFrameHook::XOleCommandTarget::QueryStatus(
  1033.    const GUID* pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[],
  1034.    OLECMDTEXT* pcmdtext)
  1035. {
  1036.     HRESULT hResult = OLECMDERR_E_UNKNOWNGROUP;
  1037.     METHOD_PROLOGUE_EX_(COleFrameHook, OleCommandTarget)
  1038.  
  1039.     COleDocObjectItem* pActiveDocObjectItem =
  1040.         DYNAMIC_DOWNCAST(COleDocObjectItem, pThis->m_pActiveItem);
  1041.     if (pActiveDocObjectItem != NULL)
  1042.     {
  1043.         hResult = _AfxQueryStatusOleCommandHelper(pActiveDocObjectItem,
  1044.            pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  1045.     }
  1046.  
  1047.     return hResult;
  1048. }
  1049.  
  1050. /////////////////////////////////////////////////////////////////////////////
  1051. // COleFrameHook::XOleInPlaceFrame implementation
  1052.  
  1053. STDMETHODIMP_(ULONG) COleFrameHook::XOleInPlaceFrame::AddRef()
  1054. {
  1055.     METHOD_PROLOGUE_EX_(COleFrameHook, OleInPlaceFrame)
  1056.     return pThis->ExternalAddRef();
  1057. }
  1058.  
  1059. STDMETHODIMP_(ULONG) COleFrameHook::XOleInPlaceFrame::Release()
  1060. {
  1061.     METHOD_PROLOGUE_EX_(COleFrameHook, OleInPlaceFrame)
  1062.     return pThis->ExternalRelease();
  1063. }
  1064.  
  1065. STDMETHODIMP COleFrameHook::XOleInPlaceFrame::QueryInterface(
  1066.     REFIID iid, LPVOID* ppvObj)
  1067. {
  1068.     METHOD_PROLOGUE_EX_(COleFrameHook, OleInPlaceFrame)
  1069.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  1070. }
  1071.  
  1072. STDMETHODIMP COleFrameHook::XOleInPlaceFrame::GetWindow(
  1073.     HWND* lphwnd)
  1074. {
  1075.     METHOD_PROLOGUE_EX_(COleFrameHook, OleInPlaceFrame)
  1076.  
  1077.     *lphwnd = pThis->m_hWnd;
  1078.     return *lphwnd != NULL ? S_OK : E_FAIL;
  1079. }
  1080.  
  1081. STDMETHODIMP COleFrameHook::XOleInPlaceFrame::ContextSensitiveHelp(
  1082.     BOOL fEnterMode)
  1083. {
  1084.     METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
  1085.     ASSERT_VALID(pThis);
  1086.  
  1087.     // document frame windows should not be put in help mode, so we get the
  1088.     //  top-level frame window and check it first
  1089.     CFrameWnd* pFrameWnd = pThis->m_pFrameWnd->GetTopLevelFrame();
  1090.     ASSERT_VALID(pFrameWnd);
  1091.  
  1092.     if (fEnterMode)
  1093.     {
  1094.         if (!pFrameWnd->m_bHelpMode)
  1095.         {
  1096.             // check if help mode probable
  1097.             if (!pFrameWnd->CanEnterHelpMode())
  1098.                 return E_UNEXPECTED;
  1099.  
  1100.             // attempt to enter context help
  1101.             if (!pThis->OnContextHelp(TRUE) ||
  1102.                 !pFrameWnd->PostMessage(WM_COMMAND, ID_CONTEXT_HELP))
  1103.             {
  1104.                 return E_UNEXPECTED;
  1105.             }
  1106.         }
  1107.     }
  1108.     else
  1109.     {
  1110.         // just exit help mode
  1111.         pFrameWnd->ExitHelpMode();
  1112.     }
  1113.  
  1114.     return S_OK;
  1115. }
  1116.  
  1117. STDMETHODIMP COleFrameHook::XOleInPlaceFrame::GetBorder(LPRECT lpRectBorder)
  1118. {
  1119.     METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
  1120.     ASSERT_VALID(pThis);
  1121.  
  1122.     COleClientItem* pItem = pThis->m_pActiveItem;
  1123.     ASSERT_VALID(pItem);
  1124.     CFrameWnd* pFrameWnd = pThis->m_pFrameWnd;
  1125.     ASSERT_VALID(pFrameWnd);
  1126.  
  1127.     // hide the control bars temporarily
  1128.     BOOL bHidden = pItem->OnShowControlBars(pFrameWnd, FALSE);
  1129.  
  1130.     // determine border space assuming that we'll remove our control bars
  1131.     CRect rectSave = pFrameWnd->m_rectBorder;
  1132.     pFrameWnd->NegotiateBorderSpace(CFrameWnd::borderSet, NULL);
  1133.     pFrameWnd->NegotiateBorderSpace(CFrameWnd::borderGet, lpRectBorder);
  1134.     pFrameWnd->NegotiateBorderSpace(CFrameWnd::borderSet, &rectSave);
  1135.  
  1136.     // restore control bars
  1137.     if (bHidden)
  1138.         pItem->OnShowControlBars(pFrameWnd, TRUE);
  1139.  
  1140.     return S_OK;
  1141. }
  1142.  
  1143. STDMETHODIMP COleFrameHook::XOleInPlaceFrame::RequestBorderSpace(
  1144.     LPCRECT lpRectWidths)
  1145. {
  1146.     METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
  1147.     ASSERT_VALID(pThis);
  1148.  
  1149.     CFrameWnd* pFrameWnd = pThis->m_pFrameWnd;
  1150.     ASSERT_VALID(pFrameWnd);
  1151.  
  1152.     if (!pFrameWnd->NegotiateBorderSpace(
  1153.         CFrameWnd::borderRequest, (LPRECT)lpRectWidths))
  1154.     {
  1155.         return INPLACE_E_NOTOOLSPACE;
  1156.     }
  1157.  
  1158.     return S_OK;
  1159. }
  1160.  
  1161. STDMETHODIMP COleFrameHook::XOleInPlaceFrame::SetBorderSpace(
  1162.     LPCRECT lpRectWidths)
  1163. {
  1164.     METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
  1165.     ASSERT_VALID(pThis);
  1166.  
  1167.     CFrameWnd* pFrameWnd = pThis->m_pFrameWnd;
  1168.  
  1169.     if (pFrameWnd->NegotiateBorderSpace(
  1170.         CFrameWnd::borderSet, (LPRECT)lpRectWidths))
  1171.     {
  1172.         pFrameWnd->DelayRecalcLayout(FALSE);
  1173.         pFrameWnd->PostMessage(WM_KICKIDLE);
  1174.     }
  1175.     pThis->m_pActiveItem->OnShowControlBars(pFrameWnd, lpRectWidths == NULL);
  1176.  
  1177.     return S_OK;
  1178. }
  1179.  
  1180. STDMETHODIMP COleFrameHook::XOleInPlaceFrame::SetActiveObject(
  1181.     LPOLEINPLACEACTIVEOBJECT lpActiveObject, LPCOLESTR lpszObjName)
  1182. {
  1183.     METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
  1184.     ASSERT_VALID(pThis);
  1185.  
  1186.     SCODE sc = E_UNEXPECTED;
  1187.     TRY
  1188.     {
  1189.         // release the old active object
  1190.         RELEASE(pThis->m_lpActiveObject);
  1191.  
  1192.         // set the new active object
  1193.         pThis->m_lpActiveObject = lpActiveObject;
  1194.         if (lpActiveObject != NULL)
  1195.             lpActiveObject->AddRef();
  1196.  
  1197.         // update caption if necessary
  1198.         pThis->m_strObjName.Empty();
  1199.         if (lpszObjName != NULL && lpActiveObject != NULL)
  1200.         {
  1201.             pThis->m_strObjName = lpszObjName;
  1202.             pThis->m_pActiveItem->OnUpdateFrameTitle();
  1203.         }
  1204.         sc = S_OK;
  1205.     }
  1206.     END_TRY
  1207.  
  1208.     return sc;
  1209. }
  1210.  
  1211. STDMETHODIMP COleFrameHook::XOleInPlaceFrame::InsertMenus(
  1212.     HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
  1213. {
  1214.     METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
  1215.     ASSERT_VALID(pThis);
  1216.  
  1217.     // get the associated COleClientItem object
  1218.     COleClientItem* pItem = pThis->m_pActiveItem;
  1219.     ASSERT_VALID(pItem);
  1220.  
  1221.     SCODE sc = E_UNEXPECTED;
  1222.     TRY
  1223.     {
  1224.         pItem->OnInsertMenus(CMenu::FromHandle(hmenuShared), lpMenuWidths);
  1225.         sc = S_OK;
  1226.     }
  1227.     END_TRY
  1228.  
  1229.     return sc;
  1230. }
  1231.  
  1232. STDMETHODIMP COleFrameHook::XOleInPlaceFrame::SetMenu(
  1233.     HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
  1234. {
  1235.     METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
  1236.     ASSERT_VALID(pThis);
  1237.  
  1238.     // get the associated COleClientItem object
  1239.     COleClientItem* pItem = pThis->m_pActiveItem;
  1240.     ASSERT_VALID(pItem);
  1241.  
  1242.     SCODE sc = E_UNEXPECTED;
  1243.     TRY
  1244.     {
  1245.         pItem->OnSetMenu(CMenu::FromHandle(hmenuShared), holemenu,
  1246.             hwndActiveObject);
  1247.         sc = S_OK;
  1248.     }
  1249.     END_TRY
  1250.  
  1251.     return sc;
  1252. }
  1253.  
  1254. STDMETHODIMP COleFrameHook::XOleInPlaceFrame::RemoveMenus(
  1255.     HMENU hmenuShared)
  1256. {
  1257.     METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
  1258.     ASSERT_VALID(pThis);
  1259.  
  1260.     // get the associated COleClientItem object
  1261.     COleClientItem* pItem = pThis->m_pActiveItem;
  1262.     ASSERT_VALID(pItem);
  1263.  
  1264.     SCODE sc = E_UNEXPECTED;
  1265.     TRY
  1266.     {
  1267.         pItem->OnRemoveMenus(CMenu::FromHandle(hmenuShared));
  1268.         sc = S_OK;
  1269.     }
  1270.     END_TRY
  1271.  
  1272.     return sc;
  1273. }
  1274.  
  1275. STDMETHODIMP COleFrameHook::XOleInPlaceFrame::SetStatusText(
  1276.     LPCOLESTR lpszStatusText)
  1277. {
  1278.     METHOD_PROLOGUE_EX_(COleFrameHook, OleInPlaceFrame)
  1279.     USES_CONVERSION;
  1280.  
  1281.     pThis->m_pFrameWnd->SendMessage(WM_SETMESSAGESTRING, 0,
  1282.         (LPARAM)OLE2CT(lpszStatusText));
  1283.  
  1284.     return S_OK;
  1285. }
  1286.  
  1287. STDMETHODIMP COleFrameHook::XOleInPlaceFrame::EnableModeless(BOOL fEnable)
  1288. {
  1289.     METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
  1290.     ASSERT_VALID(pThis);
  1291.     ASSERT_VALID(pThis->m_pFrameWnd);
  1292.  
  1293.     SCODE sc = E_UNEXPECTED;
  1294.     TRY
  1295.     {
  1296.         if (!fEnable)
  1297.             pThis->m_pFrameWnd->BeginModalState();
  1298.         else
  1299.             pThis->m_pFrameWnd->EndModalState();
  1300.         sc = S_OK;
  1301.     }
  1302.     END_TRY
  1303.  
  1304.     return sc;
  1305. }
  1306.  
  1307. STDMETHODIMP COleFrameHook::XOleInPlaceFrame::TranslateAccelerator(
  1308.     LPMSG lpmsg, WORD /*wID*/)
  1309. {
  1310.     METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
  1311.     ASSERT_VALID(pThis);
  1312.  
  1313.     SCODE sc = E_UNEXPECTED;
  1314.     TRY
  1315.     {
  1316.         // swap accel tables and call PreTranslateMessage
  1317.         CFrameWnd* pFrameWnd = pThis->m_pFrameWnd;
  1318.         HACCEL hAccelSave = pFrameWnd->m_hAccelTable;
  1319.         pFrameWnd->m_hAccelTable = pThis->m_hAccelTable;
  1320.         ASSERT(lpmsg != NULL);
  1321.         MSG msg = *lpmsg;
  1322.         sc = pFrameWnd->PreTranslateMessage(&msg) ? S_OK : S_FALSE;
  1323.         *lpmsg = msg;
  1324.         pFrameWnd->m_hAccelTable = hAccelSave;
  1325.     }
  1326.     END_TRY
  1327.  
  1328.     return sc;
  1329. }
  1330.  
  1331. /////////////////////////////////////////////////////////////////////////////
  1332. // COleClientItem::XOleIPSite implementation
  1333.  
  1334. STDMETHODIMP_(ULONG) COleClientItem::XOleIPSite::AddRef()
  1335. {
  1336.     METHOD_PROLOGUE_EX_(COleClientItem, OleIPSite)
  1337.     return pThis->ExternalAddRef();
  1338. }
  1339.  
  1340. STDMETHODIMP_(ULONG) COleClientItem::XOleIPSite::Release()
  1341. {
  1342.     METHOD_PROLOGUE_EX_(COleClientItem, OleIPSite)
  1343.     return pThis->ExternalRelease();
  1344. }
  1345.  
  1346. STDMETHODIMP COleClientItem::XOleIPSite::QueryInterface(
  1347.     REFIID iid, LPVOID* ppvObj)
  1348. {
  1349.     METHOD_PROLOGUE_EX_(COleClientItem, OleIPSite)
  1350.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  1351. }
  1352.  
  1353. STDMETHODIMP COleClientItem::XOleIPSite::GetWindow(HWND* lphwnd)
  1354. {
  1355.     METHOD_PROLOGUE_EX_(COleClientItem, OleIPSite)
  1356.  
  1357.     *lphwnd = pThis->m_pView->GetSafeHwnd();
  1358.     return *lphwnd != NULL ? S_OK : E_FAIL;
  1359. }
  1360.  
  1361. STDMETHODIMP COleClientItem::XOleIPSite::ContextSensitiveHelp(
  1362.     BOOL fEnterMode)
  1363. {
  1364.     METHOD_PROLOGUE_EX_(COleClientItem, OleIPSite)
  1365.  
  1366.     if (pThis->m_pInPlaceFrame == NULL)
  1367.         return E_UNEXPECTED;
  1368.  
  1369.     // simply delegate to frame window implementation
  1370.     return pThis->m_pInPlaceFrame->
  1371.         m_xOleInPlaceFrame.ContextSensitiveHelp(fEnterMode);
  1372. }
  1373.  
  1374. STDMETHODIMP COleClientItem::XOleIPSite::CanInPlaceActivate()
  1375. {
  1376.     METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
  1377.  
  1378.     return pThis->CanActivate() ? S_OK : S_FALSE;
  1379. }
  1380.  
  1381. STDMETHODIMP COleClientItem::XOleIPSite::OnInPlaceActivate()
  1382. {
  1383.     METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
  1384.     ASSERT_VALID(pThis);
  1385.  
  1386.     SCODE sc = E_UNEXPECTED;
  1387.     TRY
  1388.     {
  1389.         pThis->OnActivate();
  1390.         sc = S_OK;
  1391.     }
  1392.     END_TRY
  1393.  
  1394.     return sc;
  1395. }
  1396.  
  1397. STDMETHODIMP COleClientItem::XOleIPSite::OnUIActivate()
  1398. {
  1399.     METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
  1400.     ASSERT_VALID(pThis);
  1401.  
  1402.     SCODE sc = E_UNEXPECTED;
  1403.     TRY
  1404.     {
  1405.         pThis->OnActivateUI();
  1406.         sc = S_OK;
  1407.     }
  1408.     END_TRY
  1409.  
  1410.     return sc;
  1411. }
  1412.  
  1413. STDMETHODIMP COleClientItem::XOleIPSite::GetWindowContext(
  1414.     LPOLEINPLACEFRAME* lplpFrame,
  1415.     LPOLEINPLACEUIWINDOW* lplpDoc,
  1416.     LPRECT lpPosRect, LPRECT lpClipRect,
  1417.     LPOLEINPLACEFRAMEINFO lpFrameInfo)
  1418. {
  1419.     METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
  1420.     ASSERT_VALID(pThis);
  1421.  
  1422.     *lplpFrame = NULL;  // init these in-case of mem-alloc failure
  1423.     *lplpDoc = NULL;
  1424.  
  1425.     CFrameWnd* pMainFrame = NULL;
  1426.     CFrameWnd* pDocFrame = NULL;
  1427.  
  1428.     SCODE sc = E_UNEXPECTED;
  1429.     TRY
  1430.     {
  1431.         // get position of the item relative to activation view
  1432.         CRect rect;
  1433.         pThis->OnGetItemPosition(rect);
  1434.         ::CopyRect(lpPosRect, &rect);
  1435.         pThis->OnGetClipRect(rect);
  1436.         ::CopyRect(lpClipRect, &rect);
  1437.  
  1438.         // get the window context information
  1439.         if (pThis->OnGetWindowContext(&pMainFrame, &pDocFrame, lpFrameInfo))
  1440.         {
  1441.             // hook IOleInPlaceFrame interface to pMainFrame
  1442.             if (pThis->m_pInPlaceFrame == NULL)
  1443.                 pThis->m_pInPlaceFrame = new COleFrameHook(pMainFrame, pThis);
  1444.             pThis->m_pInPlaceFrame->InternalAddRef();
  1445.             *lplpFrame = (LPOLEINPLACEFRAME)pThis->m_pInPlaceFrame->
  1446.                 GetInterface(&IID_IOleInPlaceFrame);
  1447.  
  1448.             // save accel table for IOleInPlaceFrame::TranslateAccelerators
  1449.             pThis->m_pInPlaceFrame->m_hAccelTable = lpFrameInfo->haccel;
  1450.  
  1451.             // hook IOleInPlaceUIWindow to pDocFrame
  1452.             if (pDocFrame != NULL)
  1453.             {
  1454.                 if (pThis->m_pInPlaceDoc == NULL)
  1455.                     pThis->m_pInPlaceDoc = new COleFrameHook(pDocFrame, pThis);
  1456.                 pThis->m_pInPlaceDoc->InternalAddRef();
  1457.                 *lplpDoc = (LPOLEINPLACEUIWINDOW)pThis->m_pInPlaceDoc->
  1458.                     GetInterface(&IID_IOleInPlaceUIWindow);
  1459.             }
  1460.             sc = S_OK;
  1461.         }
  1462.     }
  1463.     CATCH_ALL(e)
  1464.     {
  1465.         // cleanup memory that may be partially allocated
  1466.         delete *lplpFrame;
  1467.         ASSERT(*lplpDoc == NULL);
  1468.         DELETE_EXCEPTION(e);
  1469.     }
  1470.     END_CATCH_ALL
  1471.  
  1472.     return sc;
  1473. }
  1474.  
  1475. STDMETHODIMP COleClientItem::XOleIPSite::Scroll(SIZE scrollExtent)
  1476. {
  1477.     METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
  1478.     ASSERT_VALID(pThis);
  1479.  
  1480.     SCODE sc = E_UNEXPECTED;
  1481.     TRY
  1482.     {
  1483.         if (!pThis->OnScrollBy(CSize(scrollExtent)))
  1484.             sc = S_FALSE;
  1485.         else
  1486.             sc = S_OK;
  1487.     }
  1488.     END_TRY
  1489.  
  1490.     return sc;
  1491. }
  1492.  
  1493. STDMETHODIMP COleClientItem::XOleIPSite::OnUIDeactivate(BOOL fUndoable)
  1494. {
  1495.     METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
  1496.     ASSERT_VALID(pThis);
  1497.  
  1498.     SCODE sc = E_UNEXPECTED;
  1499.     TRY
  1500.     {
  1501.         pThis->OnDeactivateUI(fUndoable);
  1502.         sc = S_OK;
  1503.     }
  1504.     END_TRY
  1505.  
  1506.     return sc;
  1507. }
  1508.  
  1509. STDMETHODIMP COleClientItem::XOleIPSite::OnInPlaceDeactivate()
  1510. {
  1511.     METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
  1512.     ASSERT_VALID(pThis);
  1513.  
  1514.     SCODE sc = E_UNEXPECTED;
  1515.     TRY
  1516.     {
  1517.         pThis->OnDeactivate();
  1518.         sc = S_OK;
  1519.     }
  1520.     END_TRY
  1521.  
  1522.     return sc;
  1523. }
  1524.  
  1525. STDMETHODIMP COleClientItem::XOleIPSite::DiscardUndoState()
  1526. {
  1527.     METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
  1528.     ASSERT_VALID(pThis);
  1529.  
  1530.     SCODE sc = E_UNEXPECTED;
  1531.     TRY
  1532.     {
  1533.         pThis->OnDiscardUndoState();
  1534.         sc = S_OK;
  1535.     }
  1536.     END_TRY
  1537.  
  1538.     return sc;
  1539. }
  1540.  
  1541. STDMETHODIMP COleClientItem::XOleIPSite::DeactivateAndUndo()
  1542. {
  1543.     METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
  1544.     ASSERT_VALID(pThis);
  1545.  
  1546.     SCODE sc = E_UNEXPECTED;
  1547.     TRY
  1548.     {
  1549.         pThis->OnDeactivateAndUndo();
  1550.         sc = S_OK;
  1551.     }
  1552.     END_TRY
  1553.  
  1554.     return sc;
  1555. }
  1556.  
  1557. STDMETHODIMP COleClientItem::XOleIPSite::OnPosRectChange(
  1558.     LPCRECT lpPosRect)
  1559. {
  1560.     METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
  1561.     ASSERT_VALID(pThis);
  1562.  
  1563.     SCODE sc = E_UNEXPECTED;
  1564.     TRY
  1565.     {
  1566.         CRect rect;
  1567.         rect.CopyRect(lpPosRect);
  1568.         pThis->OnChangeItemPosition(rect);
  1569.         sc = S_OK;
  1570.     }
  1571.     END_TRY
  1572.  
  1573.     return sc;
  1574. }
  1575.  
  1576. /////////////////////////////////////////////////////////////////////////////
  1577.