home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / OLECLI2.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  35.8 KB  |  1,439 lines

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