home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / oleipfrm.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  18KB  |  662 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_OLE3_SEG
  14. #pragma code_seg(AFX_OLE3_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. // COleCntrFrameWnd implementation
  26.  
  27. COleCntrFrameWnd::COleCntrFrameWnd(COleIPFrameWnd* pInPlaceFrame)
  28. {
  29.     m_pInPlaceFrame = pInPlaceFrame;
  30.     RemoveFrameWnd();
  31. }
  32.  
  33. COleCntrFrameWnd::~COleCntrFrameWnd()
  34. {
  35.     AddFrameWnd();
  36.     Detach();
  37. }
  38.  
  39. void COleCntrFrameWnd::RecalcLayout(BOOL /*bNotify*/)
  40. {
  41.     if (!m_bInRecalcLayout)
  42.     {
  43.         m_bInRecalcLayout = TRUE;
  44.         m_nIdleFlags &= ~(idleLayout|idleNotify);
  45.  
  46.         ASSERT_VALID(m_pInPlaceFrame);
  47.         COleServerDoc* pDoc = (COleServerDoc*)m_pInPlaceFrame->GetActiveDocument();
  48.         if (pDoc != NULL && AfxGetThread()->m_pActiveWnd == m_pInPlaceFrame)
  49.         {
  50.             ASSERT_VALID(pDoc);
  51.             ASSERT_KINDOF(COleServerDoc, pDoc);
  52.  
  53.             if (this == m_pInPlaceFrame->m_pMainFrame)
  54.                 pDoc->OnResizeBorder(NULL, m_pInPlaceFrame->m_lpFrame, TRUE);
  55.             if (this == m_pInPlaceFrame->m_pDocFrame)
  56.                 pDoc->OnResizeBorder(NULL, m_pInPlaceFrame->m_lpDocFrame, FALSE);
  57.         }
  58.         m_bInRecalcLayout = FALSE;
  59.     }
  60. }
  61.  
  62. void COleCntrFrameWnd::OnIdleUpdateCmdUI()
  63. {
  64.     // do frame delayed recalc
  65.     if (m_nIdleFlags & idleLayout)
  66.         RecalcLayout(m_nIdleFlags & idleNotify);
  67.  
  68.     // update control bars
  69.     POSITION pos = m_listControlBars.GetHeadPosition();
  70.     while (pos != NULL)
  71.     {
  72.         CControlBar* pBar = (CControlBar*)m_listControlBars.GetNext(pos);
  73.         ASSERT(pBar != NULL);
  74.         ASSERT_VALID(pBar);
  75.         AfxCallWndProc(pBar, pBar->m_hWnd, WM_IDLEUPDATECMDUI, TRUE, 0);
  76.     }
  77. }
  78.  
  79. BOOL COleCntrFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,
  80.     AFX_CMDHANDLERINFO* pHandlerInfo)
  81. {
  82.     ASSERT_VALID(m_pInPlaceFrame);
  83.  
  84.     // pump through inplace frame
  85.     CPushRoutingFrame push(this);
  86.     return m_pInPlaceFrame->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  87. }
  88.  
  89. void COleCntrFrameWnd::PostNcDestroy()
  90. {
  91.     // do nothing to avoid destroying window
  92. }
  93.  
  94. #ifdef _DEBUG
  95. void COleCntrFrameWnd::AssertValid() const
  96. {
  97.     // COleCntrFrameWnd bends the CWnd rules just a little bit.
  98.  
  99.     ASSERT(m_hWnd == NULL || ::IsWindow(m_hWnd));
  100. }
  101. #endif //_DEBUG
  102.  
  103. /////////////////////////////////////////////////////////////////////////////
  104. // COleIPFrameWnd implementation
  105.  
  106. BEGIN_MESSAGE_MAP(COleIPFrameWnd, CFrameWnd)
  107.     //{{AFX_MSG_MAP(COleIPFrameWnd)
  108.     ON_WM_SIZE()
  109.     ON_MESSAGE(WM_RECALCPARENT, OnRecalcParent)
  110.     ON_MESSAGE_VOID(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
  111.     ON_WM_WINDOWPOSCHANGING()
  112.     ON_WM_CREATE()
  113.     ON_WM_DESTROY()
  114.     ON_MESSAGE(WM_SIZECHILD, OnResizeChild)
  115.     ON_MESSAGE(WM_SETMESSAGESTRING, OnSetMessageString)
  116.     ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateControlBarMenu)
  117.     ON_COMMAND_EX(ID_VIEW_STATUS_BAR, OnBarCheck)
  118.     ON_UPDATE_COMMAND_UI(ID_VIEW_TOOLBAR, OnUpdateControlBarMenu)
  119.     ON_COMMAND_EX(ID_VIEW_TOOLBAR, OnBarCheck)
  120.     //}}AFX_MSG_MAP
  121. END_MESSAGE_MAP()
  122.  
  123. COleIPFrameWnd::COleIPFrameWnd()
  124. {
  125.     // initialize OLEINPLACEFRAMEINFO struct
  126.     memset(&m_frameInfo, 0, sizeof(m_frameInfo));
  127.     m_frameInfo.cb = sizeof m_frameInfo;
  128.  
  129.     // initialize in-place state
  130.     m_bUIActive = FALSE;
  131.     m_lpFrame = NULL;
  132.     m_lpDocFrame = NULL;
  133.     m_hOleMenu = NULL;
  134.     m_rectPos.SetRectEmpty();
  135.     m_rectClip.SetRectEmpty();
  136.     m_bInsideRecalc = FALSE;
  137.     m_hSharedMenu = NULL;
  138.     m_pMainFrame = NULL;
  139.     m_pDocFrame = NULL;
  140.     ASSERT_VALID(this);
  141. }
  142.  
  143. COleIPFrameWnd::~COleIPFrameWnd()
  144. {
  145.     ASSERT_VALID(this);
  146.  
  147.     // destroy wrappers of container's frames
  148.     delete m_pMainFrame;
  149.     delete m_pDocFrame;
  150.  
  151.     // destroy shared menu
  152.     if (m_hSharedMenu != NULL)
  153.         ::DestroyMenu(m_hSharedMenu);
  154.  
  155.     // interfaces to the container should already be released
  156.     RELEASE(m_lpFrame);
  157.     RELEASE(m_lpDocFrame);
  158. }
  159.  
  160. int COleIPFrameWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
  161. {
  162.     ASSERT_VALID(this);
  163.  
  164.     if (CFrameWnd::OnCreate(lpCreateStruct) < 0)
  165.         return -1;
  166.  
  167.     // remove WS_EX_CLIENTEDGE style if present
  168.     ModifyStyleEx(WS_EX_CLIENTEDGE, 0, 0);
  169.  
  170.     // need to remove the pending WM_SETMESSAGESTRING from the queue
  171.     MSG msg;
  172.     PeekMessage(&msg, m_hWnd, WM_SETMESSAGESTRING, WM_SETMESSAGESTRING,
  173.         PM_REMOVE|PM_NOYIELD);
  174.  
  175.     ASSERT_VALID(this);
  176.     return 0;
  177. }
  178.  
  179. void COleIPFrameWnd::OnDestroy()
  180. {
  181.     // notify the container that the rectangle has changed!
  182.     COleServerDoc* pDoc = (COleServerDoc*)GetActiveDocument();
  183.     if (pDoc != NULL)
  184.     {
  185.         ASSERT_KINDOF(COleServerDoc, pDoc);
  186.  
  187.         // close and abort changes to the document
  188.         pDoc->DisconnectViews();
  189.         pDoc->OnCloseDocument();
  190.     }
  191.  
  192.     // explicitly destroy all of the dock bars since this window
  193.     // is actually in the container and will not be destroyed
  194.     if (m_pMainFrame != NULL)
  195.         m_pMainFrame->DestroyDockBars();
  196.     if (m_pDocFrame != NULL)
  197.         m_pDocFrame->DestroyDockBars();
  198.  
  199.     CFrameWnd::OnDestroy();
  200. }
  201.  
  202. BOOL COleIPFrameWnd::OnCreateControlBars(CWnd* pWndFrame, CWnd* /*pWndDoc*/)
  203. {
  204.     ASSERT(pWndFrame != NULL);
  205.     UNUSED(pWndFrame);  // not used in release builds
  206.  
  207.     return TRUE;
  208. }
  209.  
  210. BOOL COleIPFrameWnd::OnCreateControlBars(CFrameWnd* pWndFrame,
  211.     CFrameWnd* pWndDoc)
  212. {
  213.     return OnCreateControlBars((CWnd*)pWndFrame, (CWnd*)pWndDoc);
  214. }
  215.  
  216. void COleIPFrameWnd::OnIdleUpdateCmdUI()
  217. {
  218.     // update toolbars which may be on the container
  219.     // and allow delayed recalc layouts to execute
  220.     if (m_pMainFrame != NULL)
  221.         m_pMainFrame->OnIdleUpdateCmdUI();
  222.     if (m_pDocFrame != NULL)
  223.         m_pDocFrame->OnIdleUpdateCmdUI();
  224. }
  225.  
  226. void COleIPFrameWnd::OnWindowPosChanging(LPWINDOWPOS lpWndPos)
  227. {
  228.     MSG msg;
  229.     if (!::PeekMessage(&msg, NULL, WM_KICKIDLE, WM_KICKIDLE, PM_NOREMOVE))
  230.         ::PostThreadMessage(GetCurrentThreadId(), WM_KICKIDLE, 0, 0);
  231.  
  232.     CFrameWnd::OnWindowPosChanging(lpWndPos);
  233. }
  234.  
  235. LRESULT COleIPFrameWnd::OnSetMessageString(WPARAM wParam, LPARAM lParam)
  236. {
  237.     USES_CONVERSION;
  238.  
  239.     if (m_lpFrame != NULL)
  240.     {
  241.         LPCTSTR lpsz = NULL;
  242.         CString strMessage;
  243.  
  244.         // set the message bar text
  245.         if (lParam != NULL)
  246.         {
  247.             ASSERT(wParam == 0);    // can't have both an ID and a string
  248.             lpsz = (LPCTSTR)lParam; // set an explicit string
  249.         }
  250.         else if (wParam != 0)
  251.         {
  252.             // get message associated with the ID indicated by wParam
  253.             GetMessageString(wParam, strMessage);
  254.             lpsz = strMessage;
  255.         }
  256.  
  257.         // notify container of new status text
  258.         if (lpsz == NULL)
  259.             lpsz = _T("");
  260.         m_lpFrame->SetStatusText(T2COLE(lpsz));
  261.     }
  262.  
  263.     UINT nIDLast = m_nIDLastMessage;
  264.     m_nIDLastMessage = (UINT)wParam;    // new ID (or 0)
  265.     m_nIDTracking = (UINT)wParam;       // so F1 on toolbar buttons work
  266.     return nIDLast;
  267. }
  268.  
  269. BOOL COleIPFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
  270.     CWnd* pParentWnd, CCreateContext* pContext)
  271. {
  272.     if (pParentWnd != NULL)
  273.         ASSERT_VALID(pParentWnd);
  274.  
  275.     // only do this once
  276.     ASSERT_VALID_IDR(nIDResource);
  277.     ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);
  278.  
  279.     m_nIDHelp = nIDResource;    // ID for help context (+HID_BASE_RESOURCE)
  280.  
  281.     // create the window (use child window style create)
  282.     CRect rect(0, 0, 0, 0);
  283.     if (!CWnd::Create(NULL, NULL, dwDefaultStyle, rect, pParentWnd,
  284.         nIDResource, pContext))
  285.     {
  286.         return FALSE;   // will self destruct on failure normally
  287.     }
  288.  
  289.     // load accelerator resource
  290.     LoadAccelTable(MAKEINTRESOURCE(nIDResource));
  291.  
  292.     return TRUE;
  293. }
  294.  
  295. void COleIPFrameWnd::OnSize(UINT /*nType*/, int /*cx*/, int /*cy*/)
  296. {
  297.     // recalc layout is not called in OnSize since COleIPFrameWnd does
  298.     //  "inside out" recalc -- which is driven by the size of the
  299.     //  inner most window changing, not the outer most!
  300. }
  301.  
  302. LRESULT COleIPFrameWnd::OnResizeChild(WPARAM, LPARAM lParam)
  303. {
  304.     // notify the container that the rectangle has changed!
  305.     COleServerDoc* pDoc = (COleServerDoc*)GetActiveDocument();
  306.     if (pDoc == NULL)
  307.         return 0;
  308.  
  309.     ASSERT_KINDOF(COleServerDoc, pDoc);
  310.  
  311.     // get new rect and parent
  312.     CRect rectNew;
  313.     rectNew.CopyRect((LPCRECT)lParam);
  314.     CWnd* pParentWnd = GetParent();
  315.     ASSERT_VALID(pParentWnd);
  316.  
  317.     // convert rectNew relative to pParentWnd
  318.     ClientToScreen(&rectNew);
  319.     pParentWnd->ScreenToClient(&rectNew);
  320.  
  321.     // adjust the new rectangle for the current control bars
  322.     CWnd* pLeftOver = GetDlgItem(AFX_IDW_PANE_FIRST);
  323.     ASSERT(pLeftOver != NULL);
  324.     CRect rectCur = m_rectPos;
  325.     pLeftOver->CalcWindowRect(&rectCur, CWnd::adjustOutside);
  326.     rectNew.left += m_rectPos.left - rectCur.left;
  327.     rectNew.top += m_rectPos.top - rectCur.top;
  328.     rectNew.right -= rectCur.right - m_rectPos.right;
  329.     rectNew.bottom -= rectCur.bottom - m_rectPos.bottom;
  330.     OnRequestPositionChange(rectNew);
  331.  
  332.     return 0;
  333. }
  334.  
  335. void COleIPFrameWnd::OnRequestPositionChange(LPCRECT lpRect)
  336. {
  337.     COleServerDoc* pDoc = (COleServerDoc*)GetActiveDocument();
  338.     ASSERT_VALID(pDoc);
  339.     ASSERT_KINDOF(COleServerDoc, pDoc);
  340.  
  341.     // DocObjects don't need to generate OnPosRectChange calls,
  342.     // so we can just return if this is a DoCobject
  343.  
  344.     if (pDoc->IsDocObject())
  345.         return;
  346.  
  347.     // The default behavior is to not affect the extent during the
  348.     //  call to RequestPositionChange.  This results in consistent
  349.     //  scaling behavior.
  350.  
  351.     pDoc->RequestPositionChange(lpRect);
  352. }
  353.  
  354. LRESULT COleIPFrameWnd::OnRecalcParent(WPARAM, LPARAM lParam)
  355. {
  356.     // simply call recalc layout
  357.     RepositionFrame(&m_rectPos, &m_rectClip);
  358.  
  359.     // fill in the new rectangle if specified
  360.     if ((LPRECT)lParam != NULL)
  361.         *(LPRECT)lParam = m_rectPos;
  362.  
  363.     return TRUE;
  364. }
  365.  
  366. void COleIPFrameWnd::RecalcLayout(BOOL /*bNotify*/)
  367. {
  368.     ASSERT_VALID(this);
  369.  
  370.     // better have a parent window (only used for inplace)
  371.     CWnd* pParentWnd = GetParent();
  372.     ASSERT_VALID(pParentWnd);
  373.  
  374.     // see if this frame is supporting a normal in-place object or
  375.     // a DocObject. DocObjects put scrollbars on the inside of the rect
  376.  
  377.     UINT nAdjustType = CWnd::adjustBorder;
  378.     COleServerDoc* pDoc = (COleServerDoc*) GetActiveDocument();
  379.     if (pDoc != NULL)
  380.     {
  381.         ASSERT_VALID(pDoc);
  382.         if (pDoc->IsDocObject())
  383.             nAdjustType = CWnd::adjustOutside;
  384.     }
  385.  
  386.     // first call reposition bars with arbitarily large rect just to
  387.     //  see how much space the bars will take up
  388.     CRect rectBig(0, 0, INT_MAX/2, INT_MAX/2);
  389.     CRect rectLeft;
  390.     RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery,
  391.         &rectLeft, &rectBig);
  392.  
  393.     // grow the rect by the size of the control bars
  394.     CRect rect = m_rectPos;
  395.     rect.left -= rectLeft.left;
  396.     rect.top -= rectLeft.top;
  397.     rect.right += INT_MAX/2 - rectLeft.right;
  398.     rect.bottom += INT_MAX/2 - rectLeft.bottom;
  399.  
  400.     // see how much extra space for non-client areas (such as scrollbars)
  401.     //  that the view needs.
  402.     CWnd* pLeftOver = GetDlgItem(AFX_IDW_PANE_FIRST);
  403.     if (pLeftOver != NULL)
  404.     {
  405.         rectBig = m_rectPos;
  406.         pLeftOver->CalcWindowRect(&rectBig, CWnd::adjustOutside);
  407.         rect.left -= m_rectPos.left - rectBig.left;
  408.         rect.top -= m_rectPos.top - rectBig.top;
  409.         rect.right += rectBig.right - m_rectPos.right;
  410.         rect.bottom += rectBig.bottom - m_rectPos.bottom;
  411.     }
  412.  
  413.     // adjust for non-client area on the frame window
  414.     CalcWindowRect(&rect, nAdjustType);
  415.  
  416.     // the frame window must be clipped to the visible part in the container
  417.     CRect rectVis;
  418.     rectVis.IntersectRect(&rect, &m_rectClip);
  419.  
  420.     // move the window
  421.     AfxRepositionWindow(NULL, m_hWnd, &rectVis);
  422.  
  423.     // now resize the control bars relative to the (now moved) frame
  424.     pParentWnd->ClientToScreen(&rect);
  425.     ScreenToClient(&rect);
  426.     RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST,
  427.         CWnd::reposDefault, NULL, &rect);
  428. }
  429.  
  430. void COleIPFrameWnd::RepositionFrame(LPCRECT lpPosRect, LPCRECT lpClipRect)
  431. {
  432.     ASSERT(AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
  433.     ASSERT(AfxIsValidAddress(lpClipRect, sizeof(RECT), FALSE));
  434.  
  435.     // gaurd against recursion
  436.     if (m_bInsideRecalc)
  437.         return;
  438.     m_bInsideRecalc = TRUE;
  439.  
  440.     // remember the client area for later
  441.     m_rectPos.CopyRect(lpPosRect);
  442.     m_rectClip.CopyRect(lpClipRect);
  443.  
  444.     // recalc layout based on new position & clipping rectangles
  445.     RecalcLayout();
  446.  
  447.     // remove recursion lockout
  448.     m_bInsideRecalc = FALSE;
  449. }
  450.  
  451. BOOL COleIPFrameWnd::PreTranslateMessage(MSG* pMsg)
  452. {
  453.     // check server's accelerators first
  454.     if (CFrameWnd::PreTranslateMessage(pMsg))
  455.         return TRUE;
  456.  
  457.     if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
  458.     {
  459.         // always check to see if they exist in the default accel table
  460.         //  (they may exist but not be translated when disabled)
  461.         HACCEL hAccel = GetDefaultAccelerator();
  462.         if (hAccel != NULL && IsAccelerator(hAccel,
  463.             CopyAcceleratorTable(hAccel, NULL, 0), pMsg, NULL))
  464.         {
  465.             return TRUE;
  466.         }
  467.  
  468.         // check container's accelerators as last chance
  469.         OLEINPLACEFRAMEINFO frameInfo = m_frameInfo;
  470.         if (::OleTranslateAccelerator(m_lpFrame, &frameInfo, pMsg) == S_OK)
  471.             return TRUE;
  472.     }
  473.  
  474.     return FALSE;   // keystroke not processed.
  475. }
  476.  
  477. void COleIPFrameWnd::OnUpdateControlBarMenu(CCmdUI* pCmdUI)
  478. {
  479.     if (GetControlBar(pCmdUI->m_nID) != NULL)
  480.         CFrameWnd::OnUpdateControlBarMenu(pCmdUI);
  481.     else if (m_pMainFrame != NULL &&
  482.         m_pMainFrame->GetControlBar(pCmdUI->m_nID) != NULL)
  483.     {
  484.         m_pMainFrame->OnUpdateControlBarMenu(pCmdUI);
  485.     }
  486.     else if (m_pDocFrame != NULL &&
  487.         m_pDocFrame->GetControlBar(pCmdUI->m_nID) != NULL)
  488.     {
  489.         m_pDocFrame->OnUpdateControlBarMenu(pCmdUI);
  490.     }
  491.     else
  492.         pCmdUI->ContinueRouting();
  493. }
  494.  
  495. BOOL COleIPFrameWnd::OnBarCheck(UINT nID)
  496. {
  497.     if (GetControlBar(nID) != NULL)
  498.         return CFrameWnd::OnBarCheck(nID);
  499.     else if (m_pMainFrame != NULL && m_pMainFrame->GetControlBar(nID) != NULL)
  500.         return m_pMainFrame->OnBarCheck(nID);
  501.     else if (m_pDocFrame != NULL && m_pDocFrame->GetControlBar(nID) != NULL)
  502.         return m_pDocFrame->OnBarCheck(nID);
  503.     return FALSE;
  504. }
  505.  
  506. /////////////////////////////////////////////////////////////////////////////
  507. // Special-case context sensitive help
  508.  
  509. void COleIPFrameWnd::OnContextHelp()
  510. {
  511.     if (m_bHelpMode == HELP_ACTIVE || !CanEnterHelpMode())
  512.         return;
  513.  
  514.     // notify container that we are entering context sensitive help
  515.     BOOL bHelpMode = m_bHelpMode;
  516.     m_bHelpMode = HELP_ACTIVE;
  517.     ASSERT(m_lpFrame != NULL);
  518.     if (m_lpFrame->ContextSensitiveHelp(TRUE) != S_OK ||
  519.         (m_lpDocFrame != NULL && m_lpDocFrame->ContextSensitiveHelp(TRUE) != S_OK))
  520.     {
  521.         m_bHelpMode = HELP_INACTIVE;
  522.         return;
  523.     }
  524.     m_bHelpMode = bHelpMode;
  525.  
  526.     // echo help mode to top-level frame
  527.     CFrameWnd* pFrameWnd = GetTopLevelFrame();
  528.     if (pFrameWnd != this)
  529.         pFrameWnd->m_bHelpMode = HELP_ACTIVE;
  530.  
  531.     // now enter context sensitive help mode ourselves
  532.     CFrameWnd::OnContextHelp();
  533.  
  534.     // echo help mode to top-level frame
  535.     if (pFrameWnd != this)
  536.         pFrameWnd->m_bHelpMode = m_bHelpMode;
  537.  
  538.     if (m_bHelpMode == HELP_INACTIVE)
  539.     {
  540.         // make sure container exits context sensitive help mode
  541.         m_lpFrame->ContextSensitiveHelp(FALSE);
  542.         if (m_lpDocFrame != NULL)
  543.             m_lpDocFrame->ContextSensitiveHelp(FALSE);
  544.     }
  545. }
  546.  
  547. /////////////////////////////////////////////////////////////////////////////
  548. // In-place activation startup
  549.  
  550. HMENU COleIPFrameWnd::GetInPlaceMenu()
  551. {
  552.     // get active document associated with this frame window
  553.     CDocument* pDoc = GetActiveDocument();
  554.     ASSERT_VALID(pDoc);
  555.  
  556.     // get in-place menu from the doc template
  557.     CDocTemplate* pTemplate = pDoc->GetDocTemplate();
  558.     ASSERT_VALID(pTemplate);
  559.     return pTemplate->m_hMenuInPlaceServer;
  560. }
  561.  
  562. BOOL COleIPFrameWnd::BuildSharedMenu()
  563. {
  564.     HMENU hMenu = GetInPlaceMenu();
  565.  
  566.     // create shared menu
  567.     ASSERT(m_hSharedMenu == NULL);
  568.     if ((m_hSharedMenu = ::CreateMenu()) == NULL)
  569.         return FALSE;
  570.  
  571.     // start out by getting menu from container
  572.     memset(&m_menuWidths, 0, sizeof m_menuWidths);
  573.     if (m_lpFrame->InsertMenus(m_hSharedMenu, &m_menuWidths) != S_OK)
  574.     {
  575.         ::DestroyMenu(m_hSharedMenu);
  576.         m_hSharedMenu = NULL;
  577.         return FALSE;
  578.     }
  579.     // container shouldn't touch these
  580.     ASSERT(m_menuWidths.width[1] == 0);
  581.     ASSERT(m_menuWidths.width[3] == 0);
  582.     ASSERT(m_menuWidths.width[5] == 0);
  583.  
  584.     // only copy the popups if there is a menu loaded
  585.     if (hMenu == NULL)
  586.         return TRUE;
  587.  
  588.     // insert our menu popups amongst the container menus
  589.     AfxMergeMenus(m_hSharedMenu, hMenu, &m_menuWidths.width[0], 1);
  590.  
  591.     // finally create the special OLE menu descriptor
  592.     m_hOleMenu = ::OleCreateMenuDescriptor(m_hSharedMenu, &m_menuWidths);
  593.  
  594.     return m_hOleMenu != NULL;
  595. }
  596.  
  597. void COleIPFrameWnd::DestroySharedMenu()
  598. {
  599.     if (m_hSharedMenu == NULL)
  600.     {
  601.         ASSERT(m_hOleMenu == NULL);
  602.         return;
  603.     }
  604.  
  605.     // get in-place menu to be unmerged (must be same as during activation)
  606.     HMENU hMenu = GetInPlaceMenu();
  607.     if (hMenu == NULL)
  608.         return;
  609.  
  610.     // remove our menu popups from the shared menu
  611.     AfxUnmergeMenus(m_hSharedMenu, hMenu);
  612.  
  613.     // allow container to remove its items from the menu
  614.     ASSERT(m_lpFrame != NULL);
  615.     VERIFY(m_lpFrame->RemoveMenus(m_hSharedMenu) == S_OK);
  616.  
  617.     // now destroy the menu
  618.     ::DestroyMenu(m_hSharedMenu);
  619.     m_hSharedMenu = NULL;
  620.  
  621.     if (m_hOleMenu != NULL)
  622.     {
  623.         VERIFY(::OleDestroyMenuDescriptor(m_hOleMenu) == S_OK);
  624.         m_hOleMenu = NULL;
  625.     }
  626. }
  627.  
  628. /////////////////////////////////////////////////////////////////////////////
  629. // COleIPFrameWnd diagnostics
  630.  
  631. #ifdef _DEBUG
  632. void COleIPFrameWnd::AssertValid() const
  633. {
  634.     CFrameWnd::AssertValid();
  635.     if (m_hSharedMenu != NULL)
  636.         ASSERT(::IsMenu(m_hSharedMenu));
  637. }
  638.  
  639. void COleIPFrameWnd::Dump(CDumpContext& dc) const
  640. {
  641.     CFrameWnd::Dump(dc);
  642.  
  643.     dc << "m_lpFrame = " << m_lpFrame;
  644.     dc << "\nm_lpDocFrame = " << m_lpDocFrame;
  645.     dc << "\nm_hOleMenu = " << m_hOleMenu;
  646.     dc << "\nm_rectPos = " << m_rectPos;
  647.     dc << "\nm_rectClip = " << m_rectClip;
  648.     dc << "\nm_bInsideRecalc = " << m_bInsideRecalc;
  649.     dc << "\nm_hSharedMenu = " << m_hSharedMenu;
  650.  
  651.     dc << "\n";
  652. }
  653. #endif //_DEBUG
  654.  
  655. #ifdef AFX_INIT_SEG
  656. #pragma code_seg(AFX_INIT_SEG)
  657. #endif
  658.  
  659. IMPLEMENT_DYNCREATE(COleIPFrameWnd, CFrameWnd)
  660.  
  661. /////////////////////////////////////////////////////////////////////////////
  662.