oleipfrm.cpp 18 KB

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