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