Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1940 lines
63 KiB

  1. /*************************************************************************
  2. **
  3. ** OLE 2 Container Sample Code
  4. **
  5. ** cntrinpl.c
  6. **
  7. ** This file contains all interfaces, methods and related support
  8. ** functions for an In-Place Container application (aka. Visual
  9. ** Editing). The in-place Container application includes the following
  10. ** implementation objects:
  11. **
  12. ** ContainerApp Object
  13. ** exposed interfaces:
  14. ** IOleInPlaceFrame
  15. **
  16. ** ContainerDoc Object
  17. ** support functions only
  18. ** (ICntrOtl is an SDI app; it doesn't support a Doc level IOleUIWindow)
  19. **
  20. ** ContainerLin Object
  21. ** exposed interfaces:
  22. ** IOleInPlaceSite
  23. **
  24. ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
  25. **
  26. *************************************************************************/
  27. #include "outline.h"
  28. #if defined( USE_STATUSBAR )
  29. #include "status.h"
  30. #endif
  31. OLEDBGDATA
  32. extern LPOUTLINEAPP g_lpApp;
  33. extern BOOL g_fInsideOutContainer;
  34. extern RECT g_rectNull;
  35. /*************************************************************************
  36. ** ContainerApp::IOleInPlaceFrame interface implementation
  37. *************************************************************************/
  38. // IOleInPlaceFrame::QueryInterface
  39. STDMETHODIMP CntrApp_IPFrame_QueryInterface(
  40. LPOLEINPLACEFRAME lpThis,
  41. REFIID riid,
  42. LPVOID FAR* lplpvObj
  43. )
  44. {
  45. SCODE sc = E_NOINTERFACE;
  46. LPCONTAINERAPP lpContainerApp =
  47. ((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp;
  48. /* The object should not be able to access the other interfaces
  49. ** of our App object by doing QI on this interface.
  50. */
  51. *lplpvObj = NULL;
  52. if (IsEqualIID(riid, &IID_IUnknown) ||
  53. IsEqualIID(riid, &IID_IOleWindow) ||
  54. IsEqualIID(riid, &IID_IOleInPlaceUIWindow) ||
  55. IsEqualIID(riid, &IID_IOleInPlaceFrame)) {
  56. OleDbgOut4("CntrApp_IPFrame_QueryInterface: IOleInPlaceFrame* RETURNED\r\n");
  57. *lplpvObj = (LPVOID) &lpContainerApp->m_OleInPlaceFrame;
  58. OleApp_AddRef((LPOLEAPP)lpContainerApp);
  59. sc = S_OK;
  60. }
  61. OleDbgQueryInterfaceMethod(*lplpvObj);
  62. return ResultFromScode(sc);
  63. }
  64. // IOleInPlaceFrame::AddRef
  65. STDMETHODIMP_(ULONG) CntrApp_IPFrame_AddRef(LPOLEINPLACEFRAME lpThis)
  66. {
  67. OleDbgAddRefMethod(lpThis, "IOleInPlaceFrame");
  68. return OleApp_AddRef((LPOLEAPP)g_lpApp);
  69. }
  70. // IOleInPlaceFrame::Release
  71. STDMETHODIMP_(ULONG) CntrApp_IPFrame_Release(LPOLEINPLACEFRAME lpThis)
  72. {
  73. OleDbgReleaseMethod(lpThis, "IOleInPlaceFrame");
  74. return OleApp_Release((LPOLEAPP)g_lpApp);
  75. }
  76. // IOleInPlaceFrame::GetWindow
  77. STDMETHODIMP CntrApp_IPFrame_GetWindow(
  78. LPOLEINPLACEFRAME lpThis,
  79. HWND FAR* lphwnd
  80. )
  81. {
  82. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  83. OLEDBG_BEGIN2("CntrApp_IPFrame_GetWindow\r\n")
  84. *lphwnd = lpOutlineApp->m_hWndApp;
  85. OLEDBG_END2
  86. return NOERROR;
  87. }
  88. // IOleInPlaceFrame::ContextSensitiveHelp
  89. STDMETHODIMP CntrApp_IPFrame_ContextSensitiveHelp(
  90. LPOLEINPLACEFRAME lpThis,
  91. BOOL fEnterMode
  92. )
  93. {
  94. LPCONTAINERAPP lpContainerApp =
  95. ((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp;
  96. OleDbgOut("CntrApp_IPFrame_ContextSensitiveHelp\r\n");
  97. /* OLE2NOTE: see context sensitive help technote (CSHELP.DOC)
  98. ** This method is called when F1 is pressed when a menu item is
  99. ** selected. We set the frame's m_fMenuMode flag here. later,
  100. ** in WM_COMMAND processing in the AppWndProc, if this flag is
  101. ** set then the command is NOT executed and help is given
  102. ** instead.
  103. */
  104. lpContainerApp->m_fMenuHelpMode = fEnterMode;
  105. return NOERROR;
  106. }
  107. // IOleInPlaceFrame::GetBorder
  108. STDMETHODIMP CntrApp_IPFrame_GetBorder(
  109. LPOLEINPLACEFRAME lpThis,
  110. LPRECT lprectBorder
  111. )
  112. {
  113. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  114. OLEDBG_BEGIN2("CntrApp_IPFrame_GetBorder\r\n")
  115. OutlineApp_GetFrameRect(lpOutlineApp, lprectBorder);
  116. OLEDBG_END2
  117. return NOERROR;
  118. }
  119. // IOleInPlaceFrame::RequestBorderSpace
  120. STDMETHODIMP CntrApp_IPFrame_RequestBorderSpace(
  121. LPOLEINPLACEFRAME lpThis,
  122. LPCBORDERWIDTHS lpWidths
  123. )
  124. {
  125. #if defined( _DEBUG )
  126. OleDbgOut2("CntrApp_IPFrame_RequestBorderSpace\r\n");
  127. {
  128. /* FOR DEBUGING PURPOSES ONLY -- we will fail to allow to an
  129. ** object to get any frame border space for frame tools if
  130. ** our own frame tools are poped up in the tool pallet. this
  131. ** is NOT recommended UI behavior but it allows us to test
  132. ** in the condition when the frame does not give border
  133. ** space for the object. an object in this situation must
  134. ** then either popup its tools in a floating pallet, do
  135. ** without the tools, or fail to in-place activate.
  136. */
  137. LPCONTAINERAPP lpContainerApp =
  138. ((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp;
  139. LPFRAMETOOLS lpft = OutlineApp_GetFrameTools(
  140. (LPOUTLINEAPP)lpContainerApp);
  141. if (lpft->m_ButtonBar.m_nState == BARSTATE_POPUP &&
  142. lpft->m_FormulaBar.m_nState == BARSTATE_POPUP) {
  143. OleDbgOut3(
  144. "CntrApp_IPFrame_RequestBorderSpace: allow NO SPACE\r\n");
  145. return ResultFromScode(E_FAIL);
  146. }
  147. }
  148. #endif // _DEBUG
  149. /* OLE2NOTE: we allow the object to have as much border space as it
  150. ** wants.
  151. */
  152. return NOERROR;
  153. }
  154. // IOleInPlaceFrame::SetBorderSpace
  155. STDMETHODIMP CntrApp_IPFrame_SetBorderSpace(
  156. LPOLEINPLACEFRAME lpThis,
  157. LPCBORDERWIDTHS lpWidths
  158. )
  159. {
  160. LPCONTAINERAPP lpContainerApp =
  161. ((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp;
  162. OLEDBG_BEGIN2("CntrApp_IPFrame_SetBorderSpace\r\n")
  163. /* OLE2NOTE: this fMustResizeClientArea flag is used as part of our
  164. ** defensive programming for frame window resizing. when the
  165. ** frame window is resized,IOleInPlaceActiveObject::ResizeBorder
  166. ** is called the object should normally call back to renegotiate
  167. ** for frame-level tools space. if SetBorderSpace is called then
  168. ** our client area windows are properly resized. if the in-place
  169. ** active object does NOT call SetBorderSpace, then the
  170. ** container must take care to resize its client area windows
  171. ** itself (see ContainerDoc_FrameWindowResized)
  172. */
  173. if (lpContainerApp->m_fMustResizeClientArea)
  174. lpContainerApp->m_fMustResizeClientArea = FALSE;
  175. if (lpWidths == NULL) {
  176. /* OLE2NOTE: IOleInPlaceSite::SetBorderSpace(NULL) is called
  177. ** when the in-place active object does NOT want any tool
  178. ** space. in this situation the in-place container should
  179. ** put up its tools.
  180. */
  181. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp;
  182. LPCONTAINERDOC lpContainerDoc;
  183. lpContainerDoc =(LPCONTAINERDOC)OutlineApp_GetActiveDoc(lpOutlineApp);
  184. ContainerDoc_AddFrameLevelTools(lpContainerDoc);
  185. } else {
  186. // OLE2NOTE: you could do validation of borderwidths here
  187. #if defined( _DEBUG )
  188. /* FOR DEBUGING PURPOSES ONLY -- we will fail to allow to an
  189. ** object to get any frame border space for frame tools if
  190. ** our own frame tools are poped up in the tool pallet. this
  191. ** is NOT recommended UI behavior but it allows us to test
  192. ** in the condition when the frame does not give border
  193. ** space for the object. an object in this situation must
  194. ** then either popup its tools in a floating pallet, do
  195. ** without the tools, or fail to in-place activate.
  196. */
  197. LPFRAMETOOLS lpft = OutlineApp_GetFrameTools(
  198. (LPOUTLINEAPP)lpContainerApp);
  199. if ((lpft->m_ButtonBar.m_nState == BARSTATE_POPUP &&
  200. lpft->m_FormulaBar.m_nState == BARSTATE_POPUP) &&
  201. (lpWidths->top || lpWidths->bottom ||
  202. lpWidths->left || lpWidths->right) ) {
  203. OleDbgOut3("CntrApp_IPFrame_SetBorderSpace: allow NO SPACE\r\n");
  204. OLEDBG_END2
  205. OutlineApp_SetBorderSpace(
  206. (LPOUTLINEAPP) lpContainerApp,
  207. (LPBORDERWIDTHS)&g_rectNull
  208. );
  209. OLEDBG_END2
  210. return ResultFromScode(E_FAIL);
  211. }
  212. #endif // _DEBUG
  213. OutlineApp_SetBorderSpace(
  214. (LPOUTLINEAPP) lpContainerApp,
  215. (LPBORDERWIDTHS)lpWidths
  216. );
  217. }
  218. OLEDBG_END2
  219. return NOERROR;
  220. }
  221. // IOleInPlaceFrame::SetActiveObject
  222. STDMETHODIMP CntrApp_IPFrame_SetActiveObjectA(
  223. LPOLEINPLACEFRAME lpThis,
  224. LPOLEINPLACEACTIVEOBJECT lpActiveObject,
  225. LPCSTR lpszObjName
  226. )
  227. {
  228. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
  229. OLEDBG_BEGIN2("CntrApp_IPFrame_SetActiveObject\r\n")
  230. lpContainerApp->m_hWndUIActiveObj = NULL;
  231. if (lpContainerApp->m_lpIPActiveObj)
  232. lpContainerApp->m_lpIPActiveObj->lpVtbl->Release(lpContainerApp->m_lpIPActiveObj);
  233. if ((lpContainerApp->m_lpIPActiveObj = lpActiveObject) != NULL) {
  234. lpContainerApp->m_lpIPActiveObj->lpVtbl->AddRef(
  235. lpContainerApp->m_lpIPActiveObj);
  236. OLEDBG_BEGIN2("IOleInPlaceActiveObject::GetWindow called\r\n")
  237. lpActiveObject->lpVtbl->GetWindow(
  238. lpActiveObject,
  239. (HWND FAR*)&lpContainerApp->m_hWndUIActiveObj
  240. );
  241. OLEDBG_END2
  242. /* OLE2NOTE: see comment for ContainerDoc_ForwardPaletteChangedMsg */
  243. /* No need to do this if you don't allow object to own the palette */
  244. OleApp_QueryNewPalette((LPOLEAPP)lpContainerApp);
  245. }
  246. /* OLE2NOTE: the new UI Guidelines recommend that in-place
  247. ** containers do NOT change their window titles when an object
  248. ** becomes in-place (UI) active.
  249. */
  250. OLEDBG_END2
  251. return NOERROR;
  252. }
  253. STDMETHODIMP CntrApp_IPFrame_SetActiveObject(
  254. LPOLEINPLACEFRAME lpThis,
  255. LPOLEINPLACEACTIVEOBJECT lpActiveObject,
  256. LPCOLESTR lpszObjName
  257. )
  258. {
  259. CREATESTR(pstr, lpszObjName)
  260. HRESULT hr = CntrApp_IPFrame_SetActiveObjectA(lpThis, lpActiveObject, pstr);
  261. FREESTR(pstr)
  262. return hr;
  263. }
  264. // IOleInPlaceFrame::InsertMenus
  265. STDMETHODIMP CntrApp_IPFrame_InsertMenus(
  266. LPOLEINPLACEFRAME lpThis,
  267. HMENU hMenu,
  268. LPOLEMENUGROUPWIDTHS lpMenuWidths
  269. )
  270. {
  271. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
  272. BOOL fNoError = TRUE;
  273. OLEDBG_BEGIN2("CntrApp_IPFrame_InsertMenus\r\n")
  274. fNoError &= AppendMenu(hMenu, MF_POPUP, (UINT)lpContainerApp->m_hMenuFile,
  275. "&File");
  276. fNoError &= AppendMenu(hMenu, MF_POPUP, (UINT)lpContainerApp->m_hMenuView,
  277. "O&utline");
  278. fNoError &= AppendMenu(hMenu, MF_POPUP,(UINT)lpContainerApp->m_hMenuDebug,
  279. "DbgI&Cntr");
  280. lpMenuWidths->width[0] = 1;
  281. lpMenuWidths->width[2] = 1;
  282. lpMenuWidths->width[4] = 1;
  283. OLEDBG_END2
  284. return (fNoError ? NOERROR : ResultFromScode(E_FAIL));
  285. }
  286. // IOleInPlaceFrame::SetMenu
  287. STDMETHODIMP CntrApp_IPFrame_SetMenu(
  288. LPOLEINPLACEFRAME lpThis,
  289. HMENU hMenuShared,
  290. HOLEMENU hOleMenu,
  291. HWND hwndActiveObject
  292. )
  293. {
  294. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
  295. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  296. HMENU hMenu;
  297. HRESULT hrErr;
  298. OLEDBG_BEGIN2("CntrApp_IPFrame_InsertMenus\r\n")
  299. /* OLE2NOTE: either put up the shared menu (combined menu from
  300. ** in-place server and in-place container) or our container's
  301. ** normal menu as directed.
  302. */
  303. if (hOleMenu && hMenuShared)
  304. hMenu = hMenuShared;
  305. else
  306. hMenu = lpOutlineApp->m_hMenuApp;
  307. /* OLE2NOTE: SDI apps put menu on frame by calling SetMenu.
  308. ** MDI apps would send WM_MDISETMENU message instead.
  309. */
  310. SetMenu (lpOutlineApp->m_hWndApp, hMenu);
  311. OLEDBG_BEGIN2("OleSetMenuDescriptor called\r\n")
  312. hrErr = OleSetMenuDescriptor (hOleMenu, lpOutlineApp->m_hWndApp,
  313. hwndActiveObject, NULL, NULL);
  314. OLEDBG_END2
  315. OLEDBG_END2
  316. return hrErr;
  317. }
  318. // IOleInPlaceFrame::RemoveMenus
  319. STDMETHODIMP CntrApp_IPFrame_RemoveMenus(
  320. LPOLEINPLACEFRAME lpThis,
  321. HMENU hMenu
  322. )
  323. {
  324. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
  325. BOOL fNoError = TRUE;
  326. OLEDBG_BEGIN2("CntrApp_IPFrame_RemoveMenus\r\n")
  327. /* Remove container group menus */
  328. while (GetMenuItemCount(hMenu))
  329. fNoError &= RemoveMenu(hMenu, 0, MF_BYPOSITION);
  330. OleDbgAssert(fNoError == TRUE);
  331. OLEDBG_END2
  332. return (fNoError ? NOERROR : ResultFromScode(E_FAIL));
  333. }
  334. // IOleInPlaceFrame::SetStatusText
  335. STDMETHODIMP CntrApp_IPFrame_SetStatusTextA(
  336. LPOLEINPLACEFRAME lpThis,
  337. LPCSTR lpszStatusText
  338. )
  339. {
  340. #if defined( USE_STATUSBAR )
  341. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  342. static char szMessageHold[128];
  343. OleDbgOut2("CntrApp_IPFrame_SetStatusText\r\n");
  344. /* OLE2NOTE: it is important to save a private copy of status text.
  345. ** lpszStatusText is only valid for the duration of this call.
  346. */
  347. LSTRCPYN(szMessageHold, lpszStatusText, sizeof(szMessageHold));
  348. OutlineApp_SetStatusText(lpOutlineApp, (LPSTR)szMessageHold);
  349. return ResultFromScode(S_OK);
  350. #else
  351. return ResultFromScode(E_NOTIMPL);
  352. #endif // USE_STATUSBAR
  353. }
  354. STDMETHODIMP CntrApp_IPFrame_SetStatusText(
  355. LPOLEINPLACEFRAME lpThis,
  356. LPCOLESTR lpszStatusText
  357. )
  358. {
  359. CREATESTR(pstr, lpszStatusText)
  360. HRESULT hr = CntrApp_IPFrame_SetStatusTextA(lpThis, pstr);
  361. FREESTR(pstr)
  362. return hr;
  363. }
  364. // IOleInPlaceFrame::EnableModeless
  365. STDMETHODIMP CntrApp_IPFrame_EnableModeless(
  366. LPOLEINPLACEFRAME lpThis,
  367. BOOL fEnable
  368. )
  369. {
  370. LPOLEAPP lpOleApp = (LPOLEAPP)
  371. ((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp;
  372. #if defined( _DEBUG )
  373. if (fEnable)
  374. OleDbgOut2("CntrApp_IPFrame_EnableModeless(TRUE)\r\n");
  375. else
  376. OleDbgOut2("CntrApp_IPFrame_EnableModeless(FALSE)\r\n");
  377. #endif // _DEBUG
  378. /* OLE2NOTE: this method is called when an object puts up a modal
  379. ** dialog. it tells the top-level in-place container to disable
  380. ** it modeless dialogs for the duration that the object is
  381. ** displaying a modal dialog.
  382. **
  383. ** ICNTROTL does not use any modeless dialogs, thus we can
  384. ** ignore this method.
  385. */
  386. return NOERROR;
  387. }
  388. // IOleInPlaceFrame::TranslateAccelerator
  389. STDMETHODIMP CntrApp_IPFrame_TranslateAccelerator(
  390. LPOLEINPLACEFRAME lpThis,
  391. LPMSG lpmsg,
  392. WORD wID
  393. )
  394. {
  395. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  396. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
  397. SCODE sc;
  398. if (TranslateAccelerator (lpOutlineApp->m_hWndApp,
  399. lpContainerApp->m_hAccelIPCntr, lpmsg))
  400. sc = S_OK;
  401. #if defined (MDI_VERSION)
  402. else if (TranslateMDISysAccel(lpOutlineApp->m_hWndMDIClient, lpmsg))
  403. sc = S_OK;
  404. #endif // MDI_VERSION
  405. else
  406. sc = S_FALSE;
  407. return ResultFromScode(sc);
  408. }
  409. /*************************************************************************
  410. ** ContainerDoc Support Functions
  411. *************************************************************************/
  412. /* ContainerDoc_UpdateInPlaceObjectRects
  413. ** -------------------------------------
  414. ** Update the PosRect and ClipRect of the currently in-place active
  415. ** object. if there is no object active in-place, then do nothing.
  416. **
  417. ** OLE2NOTE: this function should be called when an action occurs
  418. ** that changes either the position of the object in the document
  419. ** (eg. changing document margins changes PosRect) or the clipRect
  420. ** changes (eg. resizing the document window changes the ClipRect).
  421. */
  422. void ContainerDoc_UpdateInPlaceObjectRects(LPCONTAINERDOC lpContainerDoc, int nIndex)
  423. {
  424. LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
  425. int i;
  426. LPLINE lpLine;
  427. RECT rcClipRect;
  428. if (g_fInsideOutContainer) {
  429. if (lpContainerDoc->m_cIPActiveObjects) {
  430. /* OLE2NOTE: (INSIDE-OUT CONTAINER) we must update the
  431. ** PosRect/ClipRect for all in-place active objects
  432. ** starting from line "nIndex".
  433. */
  434. ContainerDoc_GetClipRect(lpContainerDoc, (LPRECT)&rcClipRect);
  435. #if defined( _DEBUG )
  436. OleDbgOutRect3(
  437. "ContainerDoc_UpdateInPlaceObjectRects (ClipRect)",
  438. (LPRECT)&rcClipRect
  439. );
  440. #endif
  441. for (i = nIndex; i < lpLL->m_nNumLines; i++) {
  442. lpLine=LineList_GetLine(lpLL, i);
  443. if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
  444. LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
  445. ContainerLine_UpdateInPlaceObjectRects(
  446. lpContainerLine, &rcClipRect);
  447. }
  448. }
  449. }
  450. }
  451. else {
  452. /* OLE2NOTE: (OUTSIDE-IN CONTAINER) if there is a currently
  453. ** UIActive object, we must inform it that the
  454. ** PosRect/ClipRect has now changed.
  455. */
  456. LPCONTAINERLINE lpLastUIActiveLine =
  457. lpContainerDoc->m_lpLastUIActiveLine;
  458. if (lpLastUIActiveLine && lpLastUIActiveLine->m_fUIActive) {
  459. ContainerDoc_GetClipRect(lpContainerDoc, (LPRECT)&rcClipRect);
  460. OleDbgOutRect3("OutlineDoc_Resize (ClipRect)",(LPRECT)&rcClipRect);
  461. ContainerLine_UpdateInPlaceObjectRects(
  462. lpLastUIActiveLine, &rcClipRect);
  463. }
  464. }
  465. }
  466. /* ContainerDoc_IsUIDeactivateNeeded
  467. ** ---------------------------------
  468. ** Check if it is necessary to UIDeactivate an in-place active
  469. ** object upon a mouse LBUTTONDOWN event. The position of the button
  470. ** down click is given by "pt".
  471. ** If there is not currently an in-place active line, then
  472. ** UIDeactivate is NOT needed.
  473. ** If there is a current in-place active line, then check if the
  474. ** point position is outside of the object extents on the screen. If
  475. ** so, then the object should be UIDeactivated, otherwise not.
  476. */
  477. BOOL ContainerDoc_IsUIDeactivateNeeded(
  478. LPCONTAINERDOC lpContainerDoc,
  479. POINT pt
  480. )
  481. {
  482. LPCONTAINERLINE lpUIActiveLine=lpContainerDoc->m_lpLastUIActiveLine;
  483. RECT rect;
  484. if (! lpUIActiveLine || ! lpUIActiveLine->m_fUIActive)
  485. return FALSE;
  486. ContainerLine_GetPosRect(
  487. lpUIActiveLine,
  488. (LPRECT) &rect
  489. );
  490. if (! PtInRect((LPRECT) &rect, pt))
  491. return TRUE;
  492. return FALSE;
  493. }
  494. /* ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded
  495. ** -------------------------------------------------
  496. ** OLE2NOTE: this function ONLY applies for OUTSIDE-IN containers
  497. **
  498. ** If there is a previous in-place active server still running and
  499. ** this server will not be needed to support the next OLE object
  500. ** about to be activated, then shut it down.
  501. ** in this way we manage a policy of having at most one in-place
  502. ** server running at a time. we do not imediately shut down the
  503. ** in-place server when the object is UIDeactivated because we want
  504. ** it to be fast if the server decides to re-activate the object
  505. ** in-place.
  506. **
  507. ** shutting down the server is achieved by forcing the object to
  508. ** transition from running to loaded by calling IOleObject::Close.
  509. */
  510. void ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded(
  511. LPCONTAINERDOC lpContainerDoc,
  512. LPCONTAINERLINE lpNextActiveLine
  513. )
  514. {
  515. LPCONTAINERLINE lpLastIpActiveLine = lpContainerDoc->m_lpLastIpActiveLine;
  516. BOOL fEnableServerShutDown = TRUE;
  517. LPMONIKER lpmkLinkSrc;
  518. LPMONIKER lpmkLastActiveObj;
  519. LPMONIKER lpmkCommonPrefix;
  520. LPOLELINK lpOleLink;
  521. HRESULT hrErr;
  522. /* OLE2NOTE: an inside-out style container can NOT use this scheme
  523. ** to shut down in-place servers. it would have to have a more
  524. ** sophistocated mechanism by which it keeps track of which
  525. ** objects are on screen and which were the last recently used.
  526. */
  527. if (g_fInsideOutContainer)
  528. return;
  529. if (lpLastIpActiveLine != lpNextActiveLine) {
  530. if (lpLastIpActiveLine) {
  531. /* OLE2NOTE: if the object which is about to be activated is
  532. ** actually a link to the OLE object in last activated line,
  533. ** then we do NOT want to shut down the last activated
  534. ** server because it is about to be used. when activating a
  535. ** linked object, the source of the link gets activated.
  536. */
  537. lpOleLink = (LPOLELINK)ContainerLine_GetOleObject(
  538. lpNextActiveLine,
  539. &IID_IOleLink
  540. );
  541. if (lpOleLink) {
  542. OLEDBG_BEGIN2("IOleObject::GetSourceMoniker called\r\n")
  543. lpOleLink->lpVtbl->GetSourceMoniker(
  544. lpOleLink,
  545. (LPMONIKER FAR*)&lpmkLinkSrc
  546. );
  547. OLEDBG_END2
  548. if (lpmkLinkSrc) {
  549. lpmkLastActiveObj = ContainerLine_GetFullMoniker(
  550. lpLastIpActiveLine,
  551. GETMONIKER_ONLYIFTHERE
  552. );
  553. if (lpmkLastActiveObj) {
  554. hrErr = lpmkLinkSrc->lpVtbl->CommonPrefixWith(
  555. lpmkLinkSrc,
  556. lpmkLastActiveObj,
  557. &lpmkCommonPrefix
  558. );
  559. if (GetScode(hrErr) == MK_S_HIM ||
  560. hrErr == NOERROR ||
  561. GetScode(hrErr) == MK_S_US) {
  562. /* the link source IS to the object
  563. ** contained in the last activated
  564. ** line of the document; disable the
  565. ** attempt to shut down the last
  566. ** running in-place server.
  567. */
  568. fEnableServerShutDown = FALSE;
  569. }
  570. if (lpmkCommonPrefix)
  571. OleStdRelease((LPUNKNOWN)lpmkCommonPrefix);
  572. OleStdRelease((LPUNKNOWN)lpmkLastActiveObj);
  573. }
  574. OleStdRelease((LPUNKNOWN)lpmkLinkSrc);
  575. }
  576. OleStdRelease((LPUNKNOWN)lpOleLink);
  577. }
  578. /* if it is OK to shut down the previous in-place server
  579. ** and one is still running, then shut it down. shutting
  580. ** down the server is accomplished by forcing the OLE
  581. ** object to close. this forces the object to transition
  582. ** from running to loaded. if the object is actually
  583. ** only loaded then this is a NOP.
  584. */
  585. if (fEnableServerShutDown &&
  586. lpLastIpActiveLine->m_fIpServerRunning) {
  587. OleDbgOut1("@@@ previous in-place server SHUT DOWN\r\n");
  588. ContainerLine_CloseOleObject(
  589. lpLastIpActiveLine, OLECLOSE_SAVEIFDIRTY);
  590. // we can now forget this last in-place active line.
  591. lpContainerDoc->m_lpLastIpActiveLine = NULL;
  592. }
  593. }
  594. }
  595. }
  596. /* ContainerDoc_GetUIActiveWindow
  597. ** ------------------------------
  598. ** If there is an UIActive object, then return its HWND.
  599. */
  600. HWND ContainerDoc_GetUIActiveWindow(LPCONTAINERDOC lpContainerDoc)
  601. {
  602. return lpContainerDoc->m_hWndUIActiveObj;
  603. }
  604. /* ContainerDoc_GetClipRect
  605. ** ------------------------
  606. ** Get the ClipRect in client coordinates.
  607. **
  608. ** OLE2NOTE: the ClipRect is defined as the maximum window rectangle
  609. ** that the in-place active object must be clipped to. this
  610. ** rectangle MUST be described in Client Coordinates of the window
  611. ** that is used as the Parent of the in-place active object's
  612. ** window. in our case, the LineList ListBox window is both the
  613. ** parent of the in-place active object AND defines precisely the
  614. ** clipping rectangle.
  615. */
  616. void ContainerDoc_GetClipRect(
  617. LPCONTAINERDOC lpContainerDoc,
  618. LPRECT lprcClipRect
  619. )
  620. {
  621. /* OLE2NOTE: the ClipRect can be used to ensure that the in-place
  622. ** server does not overwrite areas of the window that the
  623. ** container paints into but which should never be overwritten
  624. ** (eg. if an app were to paint row and col headings directly in
  625. ** the same window that is the parent of the in-place window.
  626. ** whenever the window size changes or gets scrolled, in-place
  627. ** active object must be informed of the new clip rect.
  628. **
  629. ** normally an app would pass the rect returned from GetClientRect.
  630. ** but because CntrOutl uses separate windows for row/column
  631. ** headings, status line, formula/tool bars, etc. it is NOT
  632. ** necessary to pass a constrained clip rect. Windows standard
  633. ** window clipping will automatically take care of all clipping
  634. ** that is necessary. thus we can take a short cut of passing an
  635. ** "infinite" clip rect, and then we do NOT need to call
  636. ** IOleInPlaceObject::SetObjectRects when our document is scrolled.
  637. */
  638. lprcClipRect->top = -32767;
  639. lprcClipRect->left = -32767;
  640. lprcClipRect->right = 32767;
  641. lprcClipRect->bottom = 32767;
  642. }
  643. /* ContainerDoc_GetTopInPlaceFrame
  644. ** -------------------------------
  645. ** returns NON-AddRef'ed pointer to Top In-Place Frame interface
  646. */
  647. LPOLEINPLACEFRAME ContainerDoc_GetTopInPlaceFrame(
  648. LPCONTAINERDOC lpContainerDoc
  649. )
  650. {
  651. #if defined( INPLACE_CNTRSVR )
  652. return lpContainerDoc->m_lpTopIPFrame;
  653. #else
  654. return (LPOLEINPLACEFRAME)&((LPCONTAINERAPP)g_lpApp)->m_OleInPlaceFrame;
  655. #endif
  656. }
  657. void ContainerDoc_GetSharedMenuHandles(
  658. LPCONTAINERDOC lpContainerDoc,
  659. HMENU FAR* lphSharedMenu,
  660. HOLEMENU FAR* lphOleMenu
  661. )
  662. {
  663. #if defined( INPLACE_CNTRSVR )
  664. if (lpContainerDoc->m_DocType == DOCTYPE_EMEBEDDEDOBJECT) {
  665. *lphSharedMenu = lpContainerDoc->m_hSharedMenu;
  666. *lphOleMenu = lpContainerDoc->m_hOleMenu;
  667. return;
  668. }
  669. #endif
  670. *lphSharedMenu = NULL;
  671. *lphOleMenu = NULL;
  672. }
  673. #if defined( USE_FRAMETOOLS )
  674. void ContainerDoc_RemoveFrameLevelTools(LPCONTAINERDOC lpContainerDoc)
  675. {
  676. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
  677. OleDbgAssert(lpOutlineDoc->m_lpFrameTools != NULL);
  678. FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, FALSE);
  679. }
  680. #endif
  681. void ContainerDoc_AddFrameLevelUI(LPCONTAINERDOC lpContainerDoc)
  682. {
  683. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
  684. LPOLEINPLACEFRAME lpTopIPFrame = ContainerDoc_GetTopInPlaceFrame(
  685. lpContainerDoc);
  686. HMENU hSharedMenu; // combined obj/cntr menu
  687. HOLEMENU hOleMenu; // returned by OleCreateMenuDesc.
  688. ContainerDoc_GetSharedMenuHandles(
  689. lpContainerDoc,
  690. &hSharedMenu,
  691. &hOleMenu
  692. );
  693. lpTopIPFrame->lpVtbl->SetMenu(
  694. lpTopIPFrame,
  695. hSharedMenu,
  696. hOleMenu,
  697. lpOutlineDoc->m_hWndDoc
  698. );
  699. /* OLE2NOTE: even if our app does NOT use FrameTools, we must still
  700. ** call IOleInPlaceFrame::SetBorderSpace.
  701. */
  702. ContainerDoc_AddFrameLevelTools(lpContainerDoc);
  703. }
  704. void ContainerDoc_AddFrameLevelTools(LPCONTAINERDOC lpContainerDoc)
  705. {
  706. LPOLEINPLACEFRAME lpTopIPFrame = ContainerDoc_GetTopInPlaceFrame(
  707. lpContainerDoc);
  708. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
  709. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
  710. OleDbgAssert(lpTopIPFrame != NULL);
  711. #if defined( USE_FRAMETOOLS )
  712. FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, TRUE);
  713. OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc);
  714. FrameTools_NegotiateForSpaceAndShow(
  715. lpOutlineDoc->m_lpFrameTools,
  716. NULL,
  717. lpTopIPFrame
  718. );
  719. #else // ! USE_FRAMETOOLS
  720. #if defined( INPLACE_CNTRSVR )
  721. if (lpContainerDoc->m_DocType == DOCTYPE_EMBEDDEDOBJECT) {
  722. /* this says i do not need space, so the top Frame should
  723. ** leave its tools behind
  724. */
  725. OLEDBG_BEGIN2("IOleInPlaceFrame::SetBorderSpace(NULL) called\r\n")
  726. lpTopIPFrame->lpVtbl->SetBorderSpace(lpTopIPFrame, NULL);
  727. OLEDBG_END2
  728. return;
  729. }
  730. #else // INPLACE_CNTR && ! USE_FRAMETOOLS
  731. OLEDBG_BEGIN2("IOleInPlaceFrame::SetBorderSpace(0,0,0,0) called\r\n")
  732. lpTopIPFrame->lpVtbl->SetBorderSpace(
  733. lpTopIPFrame,
  734. (LPCBORDERWIDTHS)&g_rectNull
  735. );
  736. OLEDBG_END2
  737. #endif // INPLACE_CNTR && ! USE_FRAMETOOLS
  738. #endif // ! USE_FRAMETOOLS
  739. }
  740. void ContainerDoc_FrameWindowResized(LPCONTAINERDOC lpContainerDoc)
  741. {
  742. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
  743. if (lpContainerApp->m_lpIPActiveObj) {
  744. RECT rcFrameRect;
  745. /* OLE2NOTE: this fMustResizeClientArea flag is used as part of
  746. ** our defensive programming for frame window resizing. when
  747. ** the frame window is
  748. ** resized, IOleInPlaceActiveObject::ResizeBorder is called
  749. ** the object should normally call back to renegotiate
  750. ** for frame-level tools space. if SetBorderSpace is called
  751. ** then our client area windows are properly resized.
  752. ** CntrApp_IPFrame_SetBorderSpace clears this flag. if the
  753. ** in-place active object does NOT call SetBorderSpace, then
  754. ** the container must take care to resize its client area
  755. ** windows itself.
  756. */
  757. lpContainerApp->m_fMustResizeClientArea = TRUE;
  758. OutlineApp_GetFrameRect(g_lpApp, (LPRECT)&rcFrameRect);
  759. OLEDBG_BEGIN2("IOleInPlaceActiveObject::ResizeBorder called\r\n")
  760. lpContainerApp->m_lpIPActiveObj->lpVtbl->ResizeBorder(
  761. lpContainerApp->m_lpIPActiveObj,
  762. (LPCRECT)&rcFrameRect,
  763. (LPOLEINPLACEUIWINDOW)&lpContainerApp->m_OleInPlaceFrame,
  764. TRUE /* fFrameWindow */
  765. );
  766. OLEDBG_END2
  767. /* the object did NOT call IOleInPlaceUIWindow::SetBorderSpace
  768. ** therefore we must resize our client area windows ourself.
  769. */
  770. if (lpContainerApp->m_fMustResizeClientArea) {
  771. lpContainerApp->m_fMustResizeClientArea = FALSE;
  772. OutlineApp_ResizeClientArea(g_lpApp);
  773. }
  774. }
  775. #if defined( USE_FRAMETOOLS )
  776. else {
  777. ContainerDoc_AddFrameLevelTools(lpContainerDoc);
  778. }
  779. #endif
  780. }
  781. #if defined( INPLACE_CNTRSVR ) || defined( INPLACE_MDICNTR )
  782. /* ContainerDoc_GetTopInPlaceDoc
  783. ** returns NON-AddRef'ed pointer to Top In-Place Doc interface
  784. */
  785. LPOLEINPLACEUIWINDOW ContainerDoc_GetTopInPlaceDoc(
  786. LPCONTAINERDOC lpContainerDoc
  787. )
  788. {
  789. #if defined( INPLACE_CNTRSVR )
  790. return lpContainerDoc->m_lpTopIPDoc;
  791. #else
  792. return (LPOLEINPLACEUIWINDOW)&lpContainerDoc->m_OleInPlaceDoc;
  793. #endif
  794. }
  795. void ContainerDoc_RemoveDocLevelTools(LPCONTAINERDOC lpContainerDoc);
  796. {
  797. LPOLEINPLACEUIWINDOW lpTopIPDoc = ContainerDoc_GetTopInPlaceDoc(
  798. lpContainerDoc);
  799. if (lpTopIPDoc && lpContainerDoc->m_fMyToolsOnDoc) {
  800. lpContainerDoc->m_fMyToolsOnDoc = FALSE;
  801. // if we had doc tools we would HIDE them here;
  802. // but NOT call SetBorderSpace(NULL)
  803. }
  804. }
  805. void ContainerDoc_AddDocLevelTools(LPCONTAINERDOC lpContainerDoc)
  806. {
  807. LPOLEINPLACEUIWINDOW lpTopIPDoc = ContainerDoc_GetTopInPlaceDoc(
  808. lpContainerDoc);
  809. if (! lpTopIPDoc)
  810. return;
  811. #if defined( USE_DOCTOOLS )
  812. if (lpTopIPDoc && ! lpContainerDoc->m_fMyToolsOnDoc) {
  813. /* if we had doc tools we would negotiate for toolbar space at
  814. ** doc level and SHOW them.
  815. */
  816. /* we do NOT have doc level tools, so we just call
  817. ** SetBorderSpace() to indicate to the top doc that
  818. ** our object does not need tool space.
  819. */
  820. lpContainerDoc->m_fMyToolsOnDoc = TRUE;
  821. return;
  822. }
  823. #else // ! USE_DOCTOOLS
  824. #if defined( INPLACE_CNTRSVR )
  825. if (lpContainerDoc->m_DocType == DOCTYPE_EMBEDDEDOBJECT) {
  826. /* this says i do not need space, so the top doc should
  827. ** leave its tools behind
  828. */
  829. lpTopIPDoc->lpVtbl->SetBorderSpace(lpTopIPDoc, NULL);
  830. return;
  831. }
  832. #else
  833. lpTopIPDoc->lpVtbl->SetBorderSpace(
  834. lpTopIPDoc,
  835. (LPCBORDERWIDTHS)&g_rectNull
  836. );
  837. #endif
  838. #endif // ! USE_DOCTOOLS
  839. }
  840. #endif // INPLACE_CNTRSVR || INPLACE_MDICNTR
  841. /* ContainerDoc_ContextSensitiveHelp
  842. ** ---------------------------------
  843. ** forward the ContextSensitiveHelp mode on to any in-place objects
  844. ** that currently have their window visible. this informs the
  845. ** objects whether to give help or take action on subsequent mouse
  846. ** clicks and menu commands. this function is called from our
  847. ** IOleInPlaceSite::ContextSensitiveHelp implementation.
  848. **
  849. ** OLE2NOTE: see context sensitive help technote (CSHELP.DOC).
  850. ** This function is called when SHIFT-F1 context sensitive help is
  851. ** entered. the cursor should then change to a question mark
  852. ** cursor and the app should enter a modal state where the next
  853. ** mouse click does not perform its normal action but rather
  854. ** gives help corresponding to the location clicked. if the app
  855. ** does not implement a help system, it should at least eat the
  856. ** click and do nothing.
  857. */
  858. void ContainerDoc_ContextSensitiveHelp(
  859. LPCONTAINERDOC lpContainerDoc,
  860. BOOL fEnterMode,
  861. BOOL fInitiatedByObj
  862. )
  863. {
  864. LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc;
  865. LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
  866. int i;
  867. LPLINE lpLine;
  868. lpOleDoc->m_fCSHelpMode = fEnterMode;
  869. if (g_fInsideOutContainer) {
  870. if (lpContainerDoc->m_cIPActiveObjects) {
  871. for (i = 0; i < lpLL->m_nNumLines; i++) {
  872. lpLine=LineList_GetLine(lpLL, i);
  873. if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
  874. LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
  875. ContainerLine_ContextSensitiveHelp(
  876. lpContainerLine, fEnterMode);
  877. }
  878. }
  879. }
  880. }
  881. else if (! fInitiatedByObj) {
  882. /* OLE2NOTE: (OUTSIDE-IN CONTAINER) if there is a currently
  883. ** UIActive object (ie. its window is visible), we must
  884. ** forward the ContextSensitiveHelp mode on to the
  885. ** object--assuming it was not the object that initiated the
  886. ** context sensitve help mode.
  887. */
  888. LPCONTAINERLINE lpLastUIActiveLine =
  889. lpContainerDoc->m_lpLastUIActiveLine;
  890. if (lpLastUIActiveLine && lpLastUIActiveLine->m_fUIActive) {
  891. ContainerLine_ContextSensitiveHelp(lpLastUIActiveLine,fEnterMode);
  892. }
  893. }
  894. }
  895. /* ContainerDoc_ForwardPaletteChangedMsg
  896. ** -------------------------------------
  897. ** forward the WM_PALETTECHANGED message (via SendMessage) to any
  898. ** in-place objects that currently have their window visible. this
  899. ** gives these objects the chance to select their palette as a
  900. ** BACKGROUND palette.
  901. **
  902. ** SEE THE TECHNOTE FOR DETAILED INFORMATION ON PALETTE COORDINATION
  903. **
  904. ** OLE2NOTE: For containers and objects to manage palettes properly
  905. ** (when objects are getting inplace edited) they should follow a
  906. ** set of rules.
  907. **
  908. ** Rule 1: The Container can decide if it wants to own the palette or
  909. ** it wants to allow its UIActive object to own the palette.
  910. ** a) If the container wants to let its UIActive object own the
  911. ** palette then it should forward WM_QUERYNEWPALETTE to the object
  912. ** when it is received to the top frame window. also it should send
  913. ** WM_QUERYNEWPALETTE to the object in its
  914. ** IOleInPlaceFrame::SetActiveObject implementation. if the object
  915. ** is given ownership of the palette, then it owns the palette until
  916. ** it is UIDeactivated.
  917. ** b) If the container wants to own the palette it should NOT send
  918. ** WM_QUERYNEWPALETTE to the UIActive object.
  919. **
  920. ** Rule 2: Whether the container wants to own the palette or not, it
  921. ** should forward the WM_PALETTECHANGED to the immediate child
  922. ** inplace active objects in its documents. if it is an inside-out
  923. ** style container then it must forward it to ALL objects that
  924. ** currently have their windows visible. When the object recives the
  925. ** WM_PALETTECHANGED message it must select its color palette as the
  926. ** background palette. When the objects are in loaded state they will be
  927. ** drawn by (OLE) by selecting their palettes as background palettes
  928. ** anyway.
  929. **
  930. ** Note: IOleObject::SetColorScheme is not related to the palette
  931. ** issue.
  932. */
  933. void ContainerDoc_ForwardPaletteChangedMsg(
  934. LPCONTAINERDOC lpContainerDoc,
  935. HWND hwndPalChg
  936. )
  937. {
  938. LPLINELIST lpLL;
  939. int i;
  940. LPLINE lpLine;
  941. if (!lpContainerDoc)
  942. return;
  943. lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
  944. if (g_fInsideOutContainer) {
  945. if (lpContainerDoc->m_cIPActiveObjects) {
  946. for (i = 0; i < lpLL->m_nNumLines; i++) {
  947. lpLine=LineList_GetLine(lpLL, i);
  948. if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
  949. LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
  950. ContainerLine_ForwardPaletteChangedMsg(
  951. lpContainerLine, hwndPalChg);
  952. }
  953. }
  954. }
  955. }
  956. else {
  957. /* OLE2NOTE: (OUTSIDE-IN CONTAINER) if there is a currently
  958. ** UIActive object (ie. its window is visible), we must
  959. ** forward it the WM_PALETTECHANGED message.
  960. */
  961. LPCONTAINERLINE lpLastUIActiveLine =
  962. lpContainerDoc->m_lpLastUIActiveLine;
  963. if (lpLastUIActiveLine && lpLastUIActiveLine->m_fUIActive) {
  964. ContainerLine_ForwardPaletteChangedMsg(
  965. lpLastUIActiveLine, hwndPalChg);
  966. }
  967. }
  968. }
  969. /*************************************************************************
  970. ** ContainerLine Support Functions and Interfaces
  971. *************************************************************************/
  972. /* ContainerLine_UIDeactivate
  973. ** --------------------------
  974. ** tell the OLE object associated with the ContainerLine to
  975. ** UIDeactivate. this informs the in-place server to tear down
  976. ** the UI and window that it put up for the object. it will remove
  977. ** its active editor menus and any frame and object adornments
  978. ** (eg. toolbars, rulers, etc.).
  979. */
  980. void ContainerLine_UIDeactivate(LPCONTAINERLINE lpContainerLine)
  981. {
  982. HRESULT hrErr;
  983. if (!lpContainerLine || !lpContainerLine->m_fUIActive)
  984. return;
  985. OLEDBG_BEGIN2("IOleInPlaceObject::UIDeactivate called\r\n")
  986. hrErr = lpContainerLine->m_lpOleIPObj->lpVtbl->UIDeactivate(
  987. lpContainerLine->m_lpOleIPObj);
  988. OLEDBG_END2
  989. if (hrErr != NOERROR) {
  990. OleDbgOutHResult("IOleInPlaceObject::UIDeactivate returned", hrErr);
  991. return;
  992. }
  993. }
  994. /* ContainerLine_UpdateInPlaceObjectRects
  995. ** -------------------------------------
  996. ** Update the PosRect and ClipRect of the given line
  997. ** currently in-place active
  998. ** object. if there is no object active in-place, then do nothing.
  999. **
  1000. ** OLE2NOTE: this function should be called when an action occurs
  1001. ** that changes either the position of the object in the document
  1002. ** (eg. changing document margins changes PosRect) or the clipRect
  1003. ** changes (eg. resizing the document window changes the ClipRect).
  1004. */
  1005. void ContainerLine_UpdateInPlaceObjectRects(
  1006. LPCONTAINERLINE lpContainerLine,
  1007. LPRECT lprcClipRect
  1008. )
  1009. {
  1010. LPCONTAINERDOC lpContainerDoc = lpContainerLine->m_lpDoc;
  1011. RECT rcClipRect;
  1012. RECT rcPosRect;
  1013. if (! lpContainerLine->m_fIpVisible)
  1014. return;
  1015. if (! lprcClipRect) {
  1016. ContainerDoc_GetClipRect(lpContainerDoc, (LPRECT)&rcClipRect);
  1017. lprcClipRect = (LPRECT)&rcClipRect;
  1018. }
  1019. #if defined( _DEBUG )
  1020. OleDbgOutRect3(
  1021. "ContainerLine_UpdateInPlaceObjectRects (ClipRect)",
  1022. (LPRECT)&rcClipRect
  1023. );
  1024. #endif
  1025. ContainerLine_GetPosRect(lpContainerLine,(LPRECT)&rcPosRect);
  1026. #if defined( _DEBUG )
  1027. OleDbgOutRect3(
  1028. "ContainerLine_UpdateInPlaceObjectRects (PosRect)",(LPRECT)&rcPosRect);
  1029. #endif
  1030. OLEDBG_BEGIN2("IOleInPlaceObject::SetObjectRects called\r\n")
  1031. lpContainerLine->m_lpOleIPObj->lpVtbl->SetObjectRects(
  1032. lpContainerLine->m_lpOleIPObj,
  1033. (LPRECT)&rcPosRect,
  1034. lprcClipRect
  1035. );
  1036. OLEDBG_END2
  1037. }
  1038. /* ContainerLine_ContextSensitveHelp
  1039. ** ---------------------------------
  1040. ** forward the ContextSensitiveHelp mode on to the in-place object
  1041. ** if it currently has its window visible. this informs the
  1042. ** object whether to give help or take action on subsequent mouse
  1043. ** clicks and menu commands.
  1044. **
  1045. ** this function is called from ContainerDoc_ContextSensitiveHelp
  1046. ** function as a result of a call to
  1047. ** IOleInPlaceSite::ContextSensitiveHelp if the in-place container
  1048. ** is operating as an in-side out container.
  1049. */
  1050. void ContainerLine_ContextSensitiveHelp(
  1051. LPCONTAINERLINE lpContainerLine,
  1052. BOOL fEnterMode
  1053. )
  1054. {
  1055. if (! lpContainerLine->m_fIpVisible)
  1056. return;
  1057. OLEDBG_BEGIN2("IOleInPlaceObject::ContextSensitiveHelp called\r\n")
  1058. lpContainerLine->m_lpOleIPObj->lpVtbl->ContextSensitiveHelp(
  1059. lpContainerLine->m_lpOleIPObj, fEnterMode);
  1060. OLEDBG_END2
  1061. }
  1062. /* ContainerLine_ForwardPaletteChangedMsg
  1063. ** --------------------------------------
  1064. ** forward it the WM_PALETTECHANGED message (via SendMessage) to the
  1065. ** in-place object if it currently has its window visible. this
  1066. ** gives the object the chance to select its palette as a BACKGROUND
  1067. ** palette if it doesn't own the palette--or as the
  1068. ** foreground palette if it currently DOES own the palette.
  1069. **
  1070. ** SEE THE TECHNOTE FOR DETAILED INFORMATION ON PALETTE COORDINATION
  1071. */
  1072. void ContainerLine_ForwardPaletteChangedMsg(
  1073. LPCONTAINERLINE lpContainerLine,
  1074. HWND hwndPalChg
  1075. )
  1076. {
  1077. if (! lpContainerLine->m_fIpVisible)
  1078. return;
  1079. OleDbgAssert(lpContainerLine->m_hWndIpObject);
  1080. SendMessage(
  1081. lpContainerLine->m_hWndIpObject,
  1082. WM_PALETTECHANGED,
  1083. (WPARAM)hwndPalChg,
  1084. 0L
  1085. );
  1086. }
  1087. /*************************************************************************
  1088. ** ContainerLine::IOleInPlaceSite interface implementation
  1089. *************************************************************************/
  1090. STDMETHODIMP CntrLine_IPSite_QueryInterface(
  1091. LPOLEINPLACESITE lpThis,
  1092. REFIID riid,
  1093. LPVOID FAR* lplpvObj
  1094. )
  1095. {
  1096. LPCONTAINERLINE lpContainerLine =
  1097. ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
  1098. return ContainerLine_QueryInterface(lpContainerLine, riid, lplpvObj);
  1099. }
  1100. STDMETHODIMP_(ULONG) CntrLine_IPSite_AddRef(LPOLEINPLACESITE lpThis)
  1101. {
  1102. LPCONTAINERLINE lpContainerLine =
  1103. ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
  1104. OleDbgAddRefMethod(lpThis, "IOleInPlaceSite");
  1105. return ContainerLine_AddRef(lpContainerLine);
  1106. }
  1107. STDMETHODIMP_(ULONG) CntrLine_IPSite_Release(LPOLEINPLACESITE lpThis)
  1108. {
  1109. LPCONTAINERLINE lpContainerLine =
  1110. ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
  1111. OleDbgReleaseMethod(lpThis, "IOleInPlaceSite");
  1112. return ContainerLine_Release(lpContainerLine);
  1113. }
  1114. STDMETHODIMP CntrLine_IPSite_GetWindow(
  1115. LPOLEINPLACESITE lpThis,
  1116. HWND FAR* lphwnd
  1117. )
  1118. {
  1119. LPCONTAINERLINE lpContainerLine =
  1120. ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
  1121. OleDbgOut2("CntrLine_IPSite_GetWindow\r\n");
  1122. *lphwnd = LineList_GetWindow(
  1123. &((LPOUTLINEDOC)lpContainerLine->m_lpDoc)->m_LineList);
  1124. return NOERROR;
  1125. }
  1126. // IOleInPlaceSite::ContextSensitiveHelp
  1127. STDMETHODIMP CntrLine_IPSite_ContextSensitiveHelp(
  1128. LPOLEINPLACESITE lpThis,
  1129. BOOL fEnterMode
  1130. )
  1131. {
  1132. LPCONTAINERLINE lpContainerLine =
  1133. ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
  1134. LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerLine->m_lpDoc;
  1135. OleDbgOut2("CntrLine_IPSite_ContextSensitiveHelp\r\n");
  1136. /* OLE2NOTE: see context sensitive help technote (CSHELP.DOC).
  1137. ** This method is called when SHIFT-F1 context sensitive help is
  1138. ** entered. the cursor should then change to a question mark
  1139. ** cursor and the app should enter a modal state where the next
  1140. ** mouse click does not perform its normal action but rather
  1141. ** gives help corresponding to the location clicked. if the app
  1142. ** does not implement a help system, it should at least eat the
  1143. ** click and do nothing.
  1144. **
  1145. ** NOTE: the implementation here is specific to an SDI simple
  1146. ** container. an MDI container or container/server application
  1147. ** would have additional work to do (see the technote).
  1148. **
  1149. ** NOTE: (INSIDE-OUT CONTAINER) if there are currently
  1150. ** any in-place objects active with their windows visible
  1151. ** (ie. fIpVisible), we must forward the
  1152. ** ContextSensitiveHelp mode on to these objects.
  1153. */
  1154. ContainerDoc_ContextSensitiveHelp(
  1155. lpContainerLine->m_lpDoc,fEnterMode,TRUE /*InitiatedByObj*/);
  1156. return NOERROR;
  1157. }
  1158. STDMETHODIMP CntrLine_IPSite_CanInPlaceActivate(LPOLEINPLACESITE lpThis)
  1159. {
  1160. LPCONTAINERLINE lpContainerLine =
  1161. ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
  1162. OleDbgOut2("CntrLine_IPSite_CanInPlaceActivate\r\n");
  1163. /* OLE2NOTE: the container can NOT allow in-place activation if it
  1164. ** is currently displaying the object as an ICON
  1165. ** (DVASPECT_ICON). it can ONLY do in-place activation if it is
  1166. ** displaying the DVASPECT_CONTENT of the OLE object.
  1167. */
  1168. if (lpContainerLine->m_dwDrawAspect == DVASPECT_CONTENT)
  1169. return NOERROR;
  1170. else
  1171. return ResultFromScode(S_FALSE);
  1172. }
  1173. STDMETHODIMP CntrLine_IPSite_OnInPlaceActivate(LPOLEINPLACESITE lpThis)
  1174. {
  1175. LPCONTAINERLINE lpContainerLine =
  1176. ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
  1177. LPCONTAINERDOC lpContainerDoc = lpContainerLine->m_lpDoc;
  1178. SCODE sc = S_OK;
  1179. OLEDBG_BEGIN2("CntrLine_IPSite_OnInPlaceActivate\r\n");
  1180. /* OLE2NOTE: (OUTSIDE-IN CONTAINER) as a policy for managing
  1181. ** running in-place servers, we will keep only 1 inplace server
  1182. ** active at any given time. so when we start to inp-place activate
  1183. ** another line, then we want to shut down the previously
  1184. ** activated server. in this way we keep at most one inplace
  1185. ** server active at a time. this is NOT a required policy. apps
  1186. ** may choose to have a more sophisticated strategy. inside-out
  1187. ** containers will HAVE to have a more sophisticated strategy,
  1188. ** because they need (at a minimum) to keep all visible object
  1189. ** servers running.
  1190. **
  1191. ** if the in-place activation is the result of activating a
  1192. ** linked object in another container, then we may arrive at
  1193. ** this method while another object is currently active.
  1194. ** normally, if the object is in-place activated by
  1195. ** double-clicking or Edit.<verb> from our own container, then
  1196. ** the previous in-place object would have been de-activated in
  1197. ** ContainerLine_DoVerb method.
  1198. */
  1199. if (!g_fInsideOutContainer) {
  1200. if (lpContainerDoc->m_lpLastIpActiveLine) {
  1201. ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded(
  1202. lpContainerDoc, lpContainerLine);
  1203. }
  1204. lpContainerDoc->m_lpLastIpActiveLine = lpContainerLine;
  1205. }
  1206. /* OLE2NOTE: to avoid LRPC problems it is important to cache the
  1207. ** IOleInPlaceObject* pointer and NOT to call QueryInterface
  1208. ** each time it is needed.
  1209. */
  1210. lpContainerLine->m_lpOleIPObj = (LPOLEINPLACEOBJECT)
  1211. ContainerLine_GetOleObject(lpContainerLine,&IID_IOleInPlaceObject);
  1212. if (! lpContainerLine->m_lpOleIPObj) {
  1213. #if defined( _DEBUG )
  1214. OleDbgAssertSz(
  1215. lpContainerLine->m_lpOleIPObj!=NULL,
  1216. "OLE object must support IOleInPlaceObject"
  1217. );
  1218. #endif
  1219. return ResultFromScode(E_FAIL); // ERROR: refuse to in-place activate
  1220. }
  1221. lpContainerLine->m_fIpActive = TRUE;
  1222. lpContainerLine->m_fIpVisible = TRUE;
  1223. OLEDBG_BEGIN2("IOleInPlaceObject::GetWindow called\r\n")
  1224. lpContainerLine->m_lpOleIPObj->lpVtbl->GetWindow(
  1225. lpContainerLine->m_lpOleIPObj,
  1226. (HWND FAR*)&lpContainerLine->m_hWndIpObject
  1227. );
  1228. OLEDBG_END2
  1229. if (! lpContainerLine->m_fIpServerRunning) {
  1230. /* OLE2NOTE: it is VERY important that an in-place container
  1231. ** that also support linking to embeddings properly manage
  1232. ** the running of its in-place objects. in an outside-in
  1233. ** style in-place container, when the user clicks
  1234. ** outside of the in-place active object, the object gets
  1235. ** UIDeactivated and the object hides its window. in order
  1236. ** to make the object fast to reactivate, the container
  1237. ** deliberately does not call IOleObject::Close. the object
  1238. ** stays running in the invisible unlocked state. the idea
  1239. ** here is if the user simply clicks outside of the object
  1240. ** and then wants to double click again to re-activate the
  1241. ** object, we do not want this to be slow. if we want to
  1242. ** keep the object running, however, we MUST Lock it
  1243. ** running. otherwise the object will be in an unstable
  1244. ** state where if a linking client does a "silent-update"
  1245. ** (eg. UpdateNow from the Links dialog), then the in-place
  1246. ** server will shut down even before the object has a chance
  1247. ** to be saved back in its container. this saving normally
  1248. ** occurs when the in-place container closes the object. also
  1249. ** keeping the object in the unstable, hidden, running,
  1250. ** not-locked state can cause problems in some scenarios.
  1251. ** ICntrOtl keeps only one object running. if the user
  1252. ** intiates a DoVerb on another object, then that last
  1253. ** running in-place active object is closed. a more
  1254. ** sophistocated in-place container may keep more object running.
  1255. ** this lock gets unlocked in ContainerLine_CloseOleObject.
  1256. */
  1257. lpContainerLine->m_fIpServerRunning = TRUE;
  1258. OLEDBG_BEGIN2("OleLockRunning(TRUE, 0) called\r\n")
  1259. OleLockRunning((LPUNKNOWN)lpContainerLine->m_lpOleIPObj, TRUE, 0);
  1260. OLEDBG_END2
  1261. }
  1262. lpContainerLine->m_lpDoc->m_cIPActiveObjects++;
  1263. OLEDBG_END2
  1264. return NOERROR;
  1265. }
  1266. STDMETHODIMP CntrLine_IPSite_OnUIActivate (LPOLEINPLACESITE lpThis)
  1267. {
  1268. LPCONTAINERLINE lpContainerLine =
  1269. ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
  1270. LPCONTAINERDOC lpContainerDoc = lpContainerLine->m_lpDoc;
  1271. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc;
  1272. LPCONTAINERLINE lpLastUIActiveLine = lpContainerDoc->m_lpLastUIActiveLine;
  1273. OLEDBG_BEGIN2("CntrLine_IPSite_OnUIActivate\r\n");
  1274. lpContainerLine->m_fUIActive = TRUE;
  1275. lpContainerDoc->m_fAddMyUI = FALSE;
  1276. lpContainerDoc->m_lpLastUIActiveLine = lpContainerLine;
  1277. if (g_fInsideOutContainer) {
  1278. /* OLE2NOTE: (INSIDE-OUT CONTAINER) an inside-out style
  1279. ** container must UIDeactivate the previous UIActive object
  1280. ** when a new object is going UIActive. since the inside-out
  1281. ** objects have their own windows visible, it is possible
  1282. ** that a click directly in an another server window will
  1283. ** cause it to UIActivate. OnUIActivate is the containers
  1284. ** notification that such has occured. it must then
  1285. ** UIDeactivate the other because at most one object can be
  1286. ** UIActive at a time.
  1287. */
  1288. if (lpLastUIActiveLine && (lpLastUIActiveLine!=lpContainerLine)) {
  1289. ContainerLine_UIDeactivate(lpLastUIActiveLine);
  1290. // Make sure new UIActive window is on top of all others
  1291. SetWindowPos(
  1292. lpContainerLine->m_hWndIpObject,
  1293. HWND_TOPMOST,
  1294. 0,0,0,0,
  1295. SWP_NOMOVE | SWP_NOSIZE
  1296. );
  1297. OLEDBG_END2
  1298. return NOERROR;
  1299. }
  1300. }
  1301. lpContainerDoc->m_hWndUIActiveObj = lpContainerLine->m_hWndIpObject;
  1302. #if defined( USE_FRAMETOOLS )
  1303. ContainerDoc_RemoveFrameLevelTools(lpContainerDoc);
  1304. #endif
  1305. #if defined( USE_DOCTOOLS )
  1306. ContainerDoc_RemoveDocLevelTools(lpContainerDoc);
  1307. #endif
  1308. OLEDBG_END2
  1309. return NOERROR;
  1310. }
  1311. STDMETHODIMP CntrLine_IPSite_GetWindowContext(
  1312. LPOLEINPLACESITE lpThis,
  1313. LPOLEINPLACEFRAME FAR* lplpFrame,
  1314. LPOLEINPLACEUIWINDOW FAR* lplpDoc,
  1315. LPRECT lprcPosRect,
  1316. LPRECT lprcClipRect,
  1317. LPOLEINPLACEFRAMEINFO lpFrameInfo
  1318. )
  1319. {
  1320. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1321. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
  1322. LPCONTAINERLINE lpContainerLine =
  1323. ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
  1324. OLEDBG_BEGIN2("CntrLine_IPSite_GetWindowContext\r\n")
  1325. /* OLE2NOTE: The server should fill in the "cb" field so that the
  1326. ** container can tell what size structure the server is
  1327. ** expecting. this enables this structure to be easily extended
  1328. ** in future releases of OLE. the container should check this
  1329. ** field so that it doesn't try to use fields that do not exist
  1330. ** since the server may be using an old structure definition.
  1331. ** Since this is the first release of OLE2.0, the structure is
  1332. ** guaranteed to be at least large enough for the current
  1333. ** definition of OLEINPLACEFRAMEINFO struct. thus we do NOT need
  1334. ** to consider this an error if the server did not fill in this
  1335. ** field correctly. this server may have trouble in the future,
  1336. ** however, when the structure is extended.
  1337. */
  1338. *lplpFrame = (LPOLEINPLACEFRAME)&lpContainerApp->m_OleInPlaceFrame;
  1339. (*lplpFrame)->lpVtbl->AddRef(*lplpFrame); // must return AddRef'ed ptr
  1340. // OLE2NOTE: an MDI app would have to provide *lplpDoc
  1341. *lplpDoc = NULL;
  1342. ContainerLine_GetPosRect(lpContainerLine, lprcPosRect);
  1343. ContainerDoc_GetClipRect(lpContainerLine->m_lpDoc, lprcClipRect);
  1344. OleDbgOutRect3("CntrLine_IPSite_GetWindowContext (PosRect)", lprcPosRect);
  1345. OleDbgOutRect3("CntrLine_IPSite_GetWindowContext (ClipRect)",lprcClipRect);
  1346. lpFrameInfo->hwndFrame = lpOutlineApp->m_hWndApp;
  1347. #if defined( MDI_VERSION )
  1348. lpFrameInfo->fMDIApp = TRUE;
  1349. #else
  1350. lpFrameInfo->fMDIApp = FALSE;
  1351. #endif
  1352. lpFrameInfo->haccel = lpContainerApp->m_hAccelIPCntr;
  1353. lpFrameInfo->cAccelEntries =
  1354. GetAccelItemCount(lpContainerApp->m_hAccelIPCntr);
  1355. OLEDBG_END2
  1356. return NOERROR;
  1357. }
  1358. STDMETHODIMP CntrLine_IPSite_Scroll(
  1359. LPOLEINPLACESITE lpThis,
  1360. SIZE scrollExtent
  1361. )
  1362. {
  1363. OleDbgOut2("CntrLine_IPSite_Scroll\r\n");
  1364. return ResultFromScode(E_FAIL);
  1365. }
  1366. STDMETHODIMP CntrLine_IPSite_OnUIDeactivate(
  1367. LPOLEINPLACESITE lpThis,
  1368. BOOL fUndoable
  1369. )
  1370. {
  1371. LPCONTAINERLINE lpContainerLine =
  1372. ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
  1373. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc;
  1374. LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP) g_lpApp;
  1375. LPLINELIST lpLL;
  1376. int nIndex;
  1377. MSG msg;
  1378. HRESULT hrErr;
  1379. OLEDBG_BEGIN2("CntrLine_IPSite_OnUIDeactivate\r\n")
  1380. lpContainerLine->m_fUIActive = FALSE;
  1381. lpContainerLine->m_fIpChangesUndoable = fUndoable;
  1382. lpContainerLine->m_lpDoc->m_hWndUIActiveObj = NULL;
  1383. if (lpContainerLine == lpContainerLine->m_lpDoc->m_lpLastUIActiveLine) {
  1384. lpContainerLine->m_lpDoc->m_lpLastUIActiveLine = NULL;
  1385. /* OLE2NOTE: here we look ahead if there is a DBLCLK sitting in our
  1386. ** message queue. if so, it could result in in-place activating
  1387. ** another object. we want to avoid placing our tools and
  1388. ** repainting if immediately another object is going to do the
  1389. ** same. SO, if there is a DBLCLK in the queue for this document
  1390. ** we will only set the fAddMyUI flag to indicate that this work
  1391. ** is still to be done. if another object actually in-place
  1392. ** activates then this flag will be cleared in
  1393. ** IOleInPlaceSite::OnUIActivate. if it does NOT get cleared,
  1394. ** then at the end of processing the DBLCLK message in our
  1395. ** OutlineDocWndProc we will put our tools back.
  1396. */
  1397. if (! PeekMessage(&msg, lpOutlineDoc->m_hWndDoc,
  1398. WM_LBUTTONDBLCLK, WM_LBUTTONDBLCLK,
  1399. PM_NOREMOVE | PM_NOYIELD)) {
  1400. /* OLE2NOTE: You need to generate QueryNewPalette only if
  1401. ** you own the top level frame (ie. you are a top-level
  1402. ** inplace container).
  1403. */
  1404. OleApp_QueryNewPalette((LPOLEAPP)g_lpApp);
  1405. #if defined( USE_DOCTOOLS )
  1406. ContainerDoc_AddDocLevelTools(lpContainerLine->m_lpDoc);
  1407. #endif
  1408. #if defined( USE_FRAMETOOLS )
  1409. ContainerDoc_AddFrameLevelUI(lpContainerLine->m_lpDoc);
  1410. #endif
  1411. } else {
  1412. lpContainerLine->m_lpDoc->m_fAddMyUI = TRUE;
  1413. }
  1414. /* OLE2NOTE: we should re-take focus. the in-place server window
  1415. ** previously had the focus; this window has just been removed.
  1416. */
  1417. SetFocus(OutlineDoc_GetWindow((LPOUTLINEDOC)lpContainerLine->m_lpDoc));
  1418. // force the line to redraw to remove in-place active hatch
  1419. lpLL = OutlineDoc_GetLineList(lpOutlineDoc);
  1420. nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine);
  1421. LineList_ForceLineRedraw(lpLL, nIndex, TRUE);
  1422. }
  1423. #if defined( UNDOSUPPORTED )
  1424. /* OLE2NOTE: an outside-in style container that supports UNDO would
  1425. ** call IOleObject::DoVerb(OLEIVERB_HIDE) to make the in-place
  1426. ** object go invisible. when it wants the in-place active object
  1427. ** to discard its undo state, it would call
  1428. ** IOleInPlaceObject::InPlaceDeactivate when it wants the object
  1429. ** to discard its undo state. there is no need for an outside-in
  1430. ** style container to call
  1431. ** IOleObject::DoVerb(OLEIVERB_DISCARDUNDOSTATE). if either the
  1432. ** container or the object do not support UNDO, then the
  1433. ** container might as well immediately call InPlaceDeactivate
  1434. ** instead of calling DoVerb(HIDE).
  1435. **
  1436. ** an inside-out style container that supports UNDO would simply
  1437. ** UIDeactivate the object. it would call
  1438. ** IOleObject::DoVerb(OLEIVERB_DISCARDUNDOSTATE) when it wants
  1439. ** the object discard its undo state. it would call
  1440. ** IOleInPlaceObject::InPlaceDeactivate if it wants the object
  1441. ** to take down its window.
  1442. */
  1443. if (! g_fInsideOutContainer || !lpContainerLine->m_fInsideOutObj) {
  1444. if (lpContainerLine->m_fIpChangesUndoable) {
  1445. ContainerLine_DoVerb(
  1446. lpContainerLine,OLEIVERB_HIDE,NULL,FALSE,FALSE);
  1447. } else {
  1448. lpContainerLine->m_lpOleIPObj->lpVtbl->InPlaceDeactivate(
  1449. lpContainerLine->m_lpOleIPObj);
  1450. }
  1451. lpContainerLine->m_fIpVisible = FALSE;
  1452. lpContainerLine->m_hWndIpObject = NULL;
  1453. }
  1454. #else
  1455. /* OLE2NOTE: an outside-in style container that does NOT support
  1456. ** UNDO would immediately tell the UIDeactivated server (UI
  1457. ** removed) to IOleInPlaceObject::InPlaceDeactivate.
  1458. **
  1459. ** an inside-out style container that does NOT support UNDO
  1460. ** would call IOleObject::DoVerb(OLEIVERB_DISCARDUNDOSTATE) to
  1461. ** tell the object to discard its undo state. it would call
  1462. ** IOleInPlaceObject::InPlaceDeactivate if it wants the object
  1463. ** to take down its window.
  1464. */
  1465. if (g_fInsideOutContainer) {
  1466. if (lpContainerLine->m_fInsideOutObj) {
  1467. if (lpContainerLine->m_fIpChangesUndoable) {
  1468. OLEDBG_BEGIN3("ContainerLine_DoVerb(OLEIVERB_DISCARDUNDOSTATE) called!\r\n")
  1469. ContainerLine_DoVerb(lpContainerLine,
  1470. OLEIVERB_DISCARDUNDOSTATE,NULL,FALSE,FALSE);
  1471. OLEDBG_END3
  1472. }
  1473. } else { // !fInsideOutObj
  1474. /* OLE2NOTE: (INSIDEOUT CONTAINER) if the object is not
  1475. ** registered OLEMISC_ACTIVATEWHENVISIBLE, then we will
  1476. ** make the object behave in an outside-in manner. since
  1477. ** we do NOT deal with UNDO we can simply
  1478. ** InPlaceDeactivate the object. it should NOT be
  1479. ** allowed to leave its window visible when
  1480. ** UIDeactivated.
  1481. */
  1482. OLEDBG_BEGIN2("IOleInPlaceObject::InPlaceDeactivate called\r\n")
  1483. hrErr = lpContainerLine->m_lpOleIPObj->lpVtbl->InPlaceDeactivate(
  1484. lpContainerLine->m_lpOleIPObj);
  1485. OLEDBG_END2
  1486. if (hrErr != NOERROR) {
  1487. OleDbgOutHResult("IOleInPlaceObject::InPlaceDeactivate returned", hrErr);
  1488. }
  1489. }
  1490. } else {
  1491. /* OLE2NOTE: (OUTSIDE-IN CONTAINER) since we do NOT deal with
  1492. ** UNDO we can simply InPlaceDeactivate the object. it
  1493. ** should NOT be allowed to leave its window visible when
  1494. ** UIDeactivated.
  1495. **
  1496. ** NOTE: In-place servers must handle InPlaceDeactivate
  1497. ** being called before its call to
  1498. ** IOleInPlaceSite::OnUIDeactivate returns. in case there
  1499. ** are misbehaving servers out there, one way to work around
  1500. ** this problem is to call
  1501. ** IOleObject::DoVerb(OLEIVERB_HIDE...) here.
  1502. */
  1503. OLEDBG_BEGIN2("IOleInPlaceObject::InPlaceDeactivate called\r\n")
  1504. hrErr = lpContainerLine->m_lpOleIPObj->lpVtbl->InPlaceDeactivate(
  1505. lpContainerLine->m_lpOleIPObj);
  1506. OLEDBG_END2
  1507. if (hrErr != NOERROR) {
  1508. OleDbgOutHResult("IOleInPlaceObject::InPlaceDeactivate returned", hrErr);
  1509. }
  1510. }
  1511. #endif // ! UNDOSUPPORTED
  1512. OLEDBG_END2
  1513. return NOERROR;
  1514. }
  1515. STDMETHODIMP CntrLine_IPSite_OnInPlaceDeactivate(LPOLEINPLACESITE lpThis)
  1516. {
  1517. LPCONTAINERLINE lpContainerLine =
  1518. ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
  1519. OLEDBG_BEGIN2("CntrLine_IPSite_OnInPlaceDeactivate\r\n");
  1520. lpContainerLine->m_fIpActive = FALSE;
  1521. lpContainerLine->m_fIpVisible = FALSE;
  1522. lpContainerLine->m_fIpChangesUndoable = FALSE;
  1523. lpContainerLine->m_hWndIpObject = NULL;
  1524. OleStdRelease((LPUNKNOWN) lpContainerLine->m_lpOleIPObj);
  1525. lpContainerLine->m_lpOleIPObj = NULL;
  1526. lpContainerLine->m_lpDoc->m_cIPActiveObjects--;
  1527. OLEDBG_END2
  1528. return NOERROR;
  1529. }
  1530. STDMETHODIMP CntrLine_IPSite_DiscardUndoState(LPOLEINPLACESITE lpThis)
  1531. {
  1532. OleDbgOut2("CntrLine_IPSite_DiscardUndoState\r\n");
  1533. return NOERROR;
  1534. }
  1535. STDMETHODIMP CntrLine_IPSite_DeactivateAndUndo(LPOLEINPLACESITE lpThis)
  1536. {
  1537. OleDbgOut2("CntrLine_IPSite_DeactivateAndUndo\r\n");
  1538. return NOERROR;
  1539. }
  1540. STDMETHODIMP CntrLine_IPSite_OnPosRectChange(
  1541. LPOLEINPLACESITE lpThis,
  1542. LPCRECT lprcPosRect
  1543. )
  1544. {
  1545. LPCONTAINERLINE lpContainerLine =
  1546. ((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
  1547. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc;
  1548. LPSCALEFACTOR lpscale = OutlineDoc_GetScaleFactor(lpOutlineDoc);
  1549. LPLINE lpLine = (LPLINE)lpContainerLine;
  1550. LPLINELIST lpLL;
  1551. int nIndex;
  1552. RECT rcClipRect;
  1553. RECT rcNewPosRect;
  1554. SIZEL sizelPix;
  1555. SIZEL sizelHim;
  1556. int nIPObjHeight = lprcPosRect->bottom - lprcPosRect->top;
  1557. int nIPObjWidth = lprcPosRect->right - lprcPosRect->left;
  1558. OLEDBG_BEGIN2("CntrLine_IPSite_OnPosRectChange\r\n")
  1559. OleDbgOutRect3("CntrLine_IPSite_OnPosRectChange (PosRect --IN)", (LPRECT)lprcPosRect);
  1560. /* OLE2NOTE: if the in-place container does NOT impose any
  1561. ** size contraints on its in-place active objects, then it may
  1562. ** simply grant the size requested by the object by immediately
  1563. ** calling IOleInPlaceObject::SetObjectRects with the
  1564. ** lprcPosRect passed by the in-place object.
  1565. **
  1566. ** Container Outline, however, imposes a size constraint on its
  1567. ** embedded objects (see comment in ContainerLine_UpdateExtent),
  1568. ** thus it is necessary to calculate the size that the in-place
  1569. ** active object is allowed to be.
  1570. **
  1571. ** Here we need to know the new extents of the in-place object.
  1572. ** We can NOT directly ask the object via IOleObject::GetExtent
  1573. ** because this method will retreive the extents of the last
  1574. ** cached metafile. the cache has not yet been updated by this
  1575. ** point. We can not reliably call IOleObject::GetExtent
  1576. ** because, despite the fact that will be delegated to the
  1577. ** object properly, some objects may not have reformated their
  1578. ** object and computed the new extents at the time of calling
  1579. ** OnPosRectChange.
  1580. **
  1581. ** the best we can do to get the new extents of the object is
  1582. ** to determine the scale factor that the object was operating at
  1583. ** prior to the OnPosRect call and scale the new lprcPosRect
  1584. ** using this scale factor back to HIMETRIC units.
  1585. */
  1586. if (lpContainerLine->m_sizeInHimetric.cx > 0 &&
  1587. lpContainerLine->m_sizeInHimetric.cy > 0) {
  1588. sizelHim.cx = lpLine->m_nWidthInHimetric;
  1589. sizelHim.cy = lpLine->m_nHeightInHimetric;
  1590. XformSizeInHimetricToPixels(NULL, &sizelHim, &sizelPix);
  1591. sizelHim.cx = lpContainerLine->m_sizeInHimetric.cx *
  1592. nIPObjWidth / sizelPix.cx;
  1593. sizelHim.cy = lpContainerLine->m_sizeInHimetric.cy *
  1594. nIPObjHeight / sizelPix.cy;
  1595. // Convert size back to 100% zoom
  1596. sizelHim.cx = sizelHim.cx * lpscale->dwSxD / lpscale->dwSxN;
  1597. sizelHim.cy = sizelHim.cy * lpscale->dwSyD / lpscale->dwSyN;
  1598. } else {
  1599. sizelHim.cx = (long)DEFOBJWIDTH;
  1600. sizelHim.cy = (long)DEFOBJHEIGHT;
  1601. XformSizeInHimetricToPixels(NULL, &sizelHim, &sizelPix);
  1602. sizelHim.cx = sizelHim.cx * nIPObjWidth / sizelPix.cx;
  1603. sizelHim.cy = sizelHim.cy * nIPObjHeight / sizelPix.cy;
  1604. }
  1605. ContainerLine_UpdateExtent(lpContainerLine, &sizelHim);
  1606. ContainerLine_GetPosRect(lpContainerLine, (LPRECT)&rcNewPosRect);
  1607. ContainerDoc_GetClipRect(lpContainerLine->m_lpDoc, (LPRECT)&rcClipRect);
  1608. #if defined( _DEBUG )
  1609. OleDbgOutRect3("CntrLine_IPSite_OnPosRectChange (PosRect --OUT)",
  1610. (LPRECT)&rcNewPosRect);
  1611. OleDbgOutRect3("CntrLine_IPSite_OnPosRectChange (ClipRect--OUT)",
  1612. (LPRECT)&rcClipRect);
  1613. #endif
  1614. OLEDBG_BEGIN2("IOleInPlaceObject::SetObjectRects called\r\n")
  1615. lpContainerLine->m_lpOleIPObj->lpVtbl->SetObjectRects(
  1616. lpContainerLine->m_lpOleIPObj,
  1617. (LPRECT)&rcNewPosRect,
  1618. (LPRECT)&rcClipRect
  1619. );
  1620. OLEDBG_END2
  1621. /* OLE2NOTE: (INSIDEOUT CONTAINER) Because this object just changed
  1622. ** size, this may cause other in-place active objects in the
  1623. ** document to move. in ICNTROTL's case any object below this
  1624. ** object would be affected. in this case it would be necessary
  1625. ** to call SetObjectRects to each affected in-place active object.
  1626. */
  1627. if (g_fInsideOutContainer) {
  1628. lpLL = OutlineDoc_GetLineList(lpOutlineDoc);
  1629. nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine);
  1630. ContainerDoc_UpdateInPlaceObjectRects(
  1631. lpContainerLine->m_lpDoc, nIndex);
  1632. }
  1633. OLEDBG_END2
  1634. return NOERROR;
  1635. }