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