|
|
Microsoft Windows NT Build 511 (SDK Final Release) 07-24-1993
/*************************************************************************
**
** OLE 2 Container Sample Code
**
** cntrinpl.c
**
** This file contains all interfaces, methods and related support
** functions for an In-Place Container application (aka. Visual
** Editing). The in-place Container application includes the following
** implementation objects:
**
** ContainerApp Object
** exposed interfaces:
** IOleInPlaceFrame
**
** ContainerDoc Object
** support functions only
** (ICntrOtl is an SDI app; it doesn't support a Doc level IOleUIWindow)
**
** ContainerLin Object
** exposed interfaces:
** IOleInPlaceSite
**
** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
**
*************************************************************************/
#include "outline.h"
OLEDBGDATA
#if defined( INPLACE_CNTR )
extern LPOUTLINEAPP g_lpApp;
extern BOOL g_fInsideOutContainer;
extern RECT g_rectNull;
#define NUM_INPLACE_ACCELS 4
/*************************************************************************
** ContainerApp::IOleInPlaceFrame interface implementation
*************************************************************************/
STDMETHODIMP CntrApp_IPFrame_QueryInterface(
LPOLEINPLACEFRAME lpThis,
REFIID riid,
LPVOID FAR* lplpvObj
)
{
SCODE sc = E_NOINTERFACE;
LPCONTAINERAPP lpContainerApp =
((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp;
/* The object should not be able to access the other interfaces
** of our App object by doing QI on this interface.
*/
*lplpvObj = NULL;
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IOleWindow) ||
IsEqualIID(riid, &IID_IOleInPlaceUIWindow) ||
IsEqualIID(riid, &IID_IOleInPlaceFrame)) {
OleDbgOut4("CntrApp_IPFrame_QueryInterface: IOleInPlaceFrame* RETURNED\r\n");
*lplpvObj = (LPVOID) &lpContainerApp->m_OleInPlaceFrame;
OleApp_AddRef((LPOLEAPP)lpContainerApp);
sc = S_OK;
}
OleDbgQueryInterfaceMethod(*lplpvObj);
return ResultFromScode(sc);
}
STDMETHODIMP_(ULONG) CntrApp_IPFrame_AddRef(LPOLEINPLACEFRAME lpThis)
{
OleDbgAddRefMethod(lpThis, "IOleInPlaceFrame");
return OleApp_AddRef((LPOLEAPP)g_lpApp);
}
STDMETHODIMP_(ULONG) CntrApp_IPFrame_Release(LPOLEINPLACEFRAME lpThis)
{
OleDbgReleaseMethod(lpThis, "IOleInPlaceFrame");
return OleApp_Release((LPOLEAPP)g_lpApp);
}
STDMETHODIMP CntrApp_IPFrame_GetWindow(
LPOLEINPLACEFRAME lpThis,
HWND FAR* lphwnd
)
{
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
OLEDBG_BEGIN2("CntrApp_IPFrame_GetWindow\r\n")
*lphwnd = lpOutlineApp->m_hWndApp;
OLEDBG_END2
return NOERROR;
}
STDMETHODIMP CntrApp_IPFrame_ContextSensitiveHelp(
LPOLEINPLACEFRAME lpThis,
BOOL fEnterMode
)
{
OLEDBG_BEGIN2("CntrApp_IPFrame_ContextSensitiveHelp\r\n")
#if defined( LATER )
LPOLEINPLACEFRAME lpFrame = m_pEItem->m_pAC->GetInPlaceFrame();
HRESULT hresult = lpFrame->ContextSensitiveHelp(fEnterMode);
lpFrame->Release();
#endif // LATER
OLEDBG_END2
return NOERROR;
}
STDMETHODIMP CntrApp_IPFrame_GetBorder(
LPOLEINPLACEFRAME lpThis,
LPRECT lprectBorder
)
{
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
OLEDBG_BEGIN2("CntrApp_IPFrame_GetBorder\r\n")
OutlineApp_GetFrameRect(lpOutlineApp, lprectBorder);
OLEDBG_END2
return NOERROR;
}
STDMETHODIMP CntrApp_IPFrame_RequestBorderSpace(
LPOLEINPLACEFRAME lpThis,
LPCBORDERWIDTHS lpWidths
)
{
OleDbgOut2("CntrApp_IPFrame_RequestBorderSpace\r\n");
#if defined( _DEBUG )
{
/* FOR DEBUGING PURPOSES ONLY -- we will fail to allow to an
** object to get any frame border space for frame tools if
** our own frame tools are poped up in the tool pallet. this
** is NOT recommended UI behavior but it allows us to test
** in the condition when the frame does not give border
** space for the object. an object in this situation must
** then either popup its tools in a floating pallet, do
** without the tools, or fail to in-place activate.
*/
LPCONTAINERAPP lpContainerApp =
((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp;
LPFRAMETOOLS lpft = OutlineApp_GetFrameTools(
(LPOUTLINEAPP)lpContainerApp);
if (lpft->m_ButtonBar.m_nState == BARSTATE_POPUP &&
lpft->m_FormulaBar.m_nState == BARSTATE_POPUP) {
OleDbgOut3(
"CntrApp_IPFrame_RequestBorderSpace: allow NO SPACE\r\n");
return ResultFromScode(E_FAIL);
}
}
#endif // _DEBUG
return NOERROR;
}
STDMETHODIMP CntrApp_IPFrame_SetBorderSpace(
LPOLEINPLACEFRAME lpThis,
LPCBORDERWIDTHS lpWidths
)
{
LPCONTAINERAPP lpContainerApp =
((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp;
OLEDBG_BEGIN2("CntrApp_IPFrame_SetBorderSpace\r\n")
if (lpWidths == NULL) {
/* OLE2NOTE: IOleInPlaceSite::SetBorderSpace(NULL) is called
** when the in-place active object does NOT want any tool
** space. in this situation the in-place container should
** put up its tools.
*/
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp;
LPCONTAINERDOC lpContainerDoc;
lpContainerDoc =(LPCONTAINERDOC)OutlineApp_GetActiveDoc(lpOutlineApp);
ContainerDoc_AddFrameLevelTools(lpContainerDoc);
} else {
// OLE2NOTE: you could do validation of borderwidths here
#if defined( _DEBUG )
/* FOR DEBUGING PURPOSES ONLY -- we will fail to allow to an
** object to get any frame border space for frame tools if
** our own frame tools are poped up in the tool pallet. this
** is NOT recommended UI behavior but it allows us to test
** in the condition when the frame does not give border
** space for the object. an object in this situation must
** then either popup its tools in a floating pallet, do
** without the tools, or fail to in-place activate.
*/
LPFRAMETOOLS lpft = OutlineApp_GetFrameTools(
(LPOUTLINEAPP)lpContainerApp);
if ((lpft->m_ButtonBar.m_nState == BARSTATE_POPUP &&
lpft->m_FormulaBar.m_nState == BARSTATE_POPUP) &&
(lpWidths->top || lpWidths->bottom ||
lpWidths->left || lpWidths->right) ) {
OleDbgOut3("CntrApp_IPFrame_SetBorderSpace: allow NO SPACE\r\n");
OLEDBG_END2
OutlineApp_SetBorderSpace(
(LPOUTLINEAPP) lpContainerApp,
(LPBORDERWIDTHS)&g_rectNull
);
OLEDBG_END2
return ResultFromScode(E_FAIL);
}
#endif // _DEBUG
OutlineApp_SetBorderSpace(
(LPOUTLINEAPP) lpContainerApp,
(LPBORDERWIDTHS)lpWidths
);
}
OLEDBG_END2
return NOERROR;
}
STDMETHODIMP CntrApp_IPFrame_SetActiveObject(
LPOLEINPLACEFRAME lpThis,
LPOLEINPLACEACTIVEOBJECT lpActiveObject,
LPCSTR lpszObjName
)
{
char szTitle[256];
LPCONTAINERAPP lpContainerApp =
((struct COleInPlaceFrameImpl FAR*)lpThis)->lpContainerApp;
OLEDBG_BEGIN2("CntrApp_IPFrame_SetActiveObject\r\n")
if (lpContainerApp->m_lpIPActiveObj)
lpContainerApp->m_lpIPActiveObj->lpVtbl->Release(lpContainerApp->m_lpIPActiveObj);
if (lpContainerApp->m_lpIPActiveObj = lpActiveObject)
lpContainerApp->m_lpIPActiveObj->lpVtbl->AddRef(lpContainerApp->m_lpIPActiveObj);
#if !defined (MDI_VERSION)
// MDI apps will change the document window title..
if (lpActiveObject) {
lstrcpy (szTitle, lpszObjName);
lstrcat (szTitle, " in ");
lstrcat (szTitle, g_lpApp->m_lpDoc->m_lpszDocTitle);
SetWindowText (g_lpApp->m_hWndApp, szTitle);
} else {
OutlineDoc_SetTitle(g_lpApp->m_lpDoc);
}
#endif // !defined (MDI_VERSION)
OLEDBG_END2
return NOERROR;
}
STDMETHODIMP CntrApp_IPFrame_InsertMenus(
LPOLEINPLACEFRAME lpThis,
HMENU hMenu,
LPOLEMENUGROUPWIDTHS lpMenuWidths
)
{
LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
BOOL fNoError = TRUE;
OLEDBG_BEGIN2("CntrApp_IPFrame_InsertMenus\r\n")
fNoError &= AppendMenu(hMenu, MF_POPUP, (UINT)lpContainerApp->m_hMenuFile,
"&File");
fNoError &= AppendMenu(hMenu, MF_POPUP, (UINT)lpContainerApp->m_hMenuView,
"O&utline");
fNoError &= AppendMenu(hMenu, MF_POPUP,(UINT)lpContainerApp->m_hMenuDebug,
"DbgI&Cntr");
lpMenuWidths->width[0] = 1;
lpMenuWidths->width[2] = 1;
lpMenuWidths->width[4] = 1;
OLEDBG_END2
return (fNoError ? NOERROR : ResultFromScode(E_FAIL));
}
STDMETHODIMP CntrApp_IPFrame_SetMenu(
LPOLEINPLACEFRAME lpThis,
HMENU hMenuShared,
HOLEMENU hOleMenu,
HWND hwndActiveObject
)
{
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
HMENU hMenu;
HRESULT hrErr;
OLEDBG_BEGIN2("CntrApp_IPFrame_InsertMenus\r\n")
/* OLE2NOTE: either put up the shared menu (combined menu from
** in-place server and in-place container) or our container's
** normal menu as directed.
*/
if (hOleMenu && hMenuShared)
hMenu = hMenuShared;
else
hMenu = lpOutlineApp->m_hMenuApp;
/* OLE2NOTE: SDI apps put menu on frame by calling SetMenu.
** MDI apps would send WM_MDISETMENU message instead.
*/
SetMenu (lpOutlineApp->m_hWndApp, hMenu);
OLEDBG_BEGIN2("OleSetMenuDescriptor called\r\n")
hrErr = OleSetMenuDescriptor (hOleMenu, lpOutlineApp->m_hWndApp,
hwndActiveObject, NULL, NULL);
OLEDBG_END2
OLEDBG_END2
return hrErr;
}
STDMETHODIMP CntrApp_IPFrame_RemoveMenus(
LPOLEINPLACEFRAME lpThis,
HMENU hMenu
)
{
LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
BOOL fNoError = TRUE;
OLEDBG_BEGIN2("CntrApp_IPFrame_RemoveMenus\r\n")
/* Remove container group menus */
while (GetMenuItemCount(hMenu))
fNoError &= RemoveMenu(hMenu, 0, MF_BYPOSITION);
OleDbgAssert(fNoError == TRUE);
OLEDBG_END2
return (fNoError ? NOERROR : ResultFromScode(E_FAIL));
}
STDMETHODIMP CntrApp_IPFrame_SetStatusText(
LPOLEINPLACEFRAME lpThis,
LPCSTR lpszStatusText
)
{
OleDbgOut2("CntrApp_IPFrame_SetStatusText\r\n");
// REVIEW: NOT YET IMPLEMENTED
return ResultFromScode(E_NOTIMPL);
}
STDMETHODIMP CntrApp_IPFrame_EnableModeless(
LPOLEINPLACEFRAME lpThis,
BOOL fEnable
)
{
return NOERROR;
}
STDMETHODIMP CntrApp_IPFrame_TranslateAccelerator(
LPOLEINPLACEFRAME lpThis,
LPMSG lpmsg,
WORD wID
)
{
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
SCODE sc;
if (TranslateAccelerator (lpOutlineApp->m_hWndApp,
lpContainerApp->m_hAccelIPCntr, lpmsg))
sc = S_OK;
#if defined (MDI_VERSION)
else if (TranslateMDISysAccel(lpOutlineApp->m_hWndMDIClient, lpmsg))
sc = S_OK;
#endif // MDI_VERSION
else
sc = S_FALSE;
return ResultFromScode(sc);
}
/*************************************************************************
** ContainerDoc Support Functions
*************************************************************************/
/* ContainerDoc_UpdateInPlaceObjectRects
** -------------------------------------
** Update the PosRect and ClipRect of the currently in-place active
** object. if there is no object active in-place, then do nothing.
**
** OLE2NOTE: this function should be called when an action occurs
** that changes either the position of the object in the document
** (eg. changing document margins changes PosRect) or the clipRect
** changes (eg. resizing the document window changes the ClipRect).
*/
void ContainerDoc_UpdateInPlaceObjectRects(LPCONTAINERDOC lpContainerDoc, int nIndex)
{
LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
int i;
LPLINE lpLine;
RECT rcClipRect;
if (g_fInsideOutContainer) {
if (lpContainerDoc->m_cIPActiveObjects) {
/* OLE2NOTE: (INSIDE-OUT CONTAINER) we must update the
** PosRect/ClipRect for all in-place active objects
** starting from line "nIndex".
*/
ContainerDoc_GetClipRect(lpContainerDoc, (LPRECT)&rcClipRect);
OleDbgOutRect3(
"OutlineDoc_Resize (ClipRect)", (LPRECT)&rcClipRect);
for (i = nIndex; i < lpLL->m_nNumLines; i++) {
lpLine=LineList_GetLine(lpLL, i);
if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
ContainerLine_UpdateInPlaceObjectRects(
lpContainerLine, &rcClipRect);
}
}
}
}
else {
/* OLE2NOTE: (OUTSIDE-IN CONTAINER) if there is a currently
** UIActive object, we must inform it that the
** PosRect/ClipRect has now changed.
*/
LPCONTAINERLINE lpLastUIActiveLine =
lpContainerDoc->m_lpLastUIActiveLine;
if (lpLastUIActiveLine && lpLastUIActiveLine->m_fUIActive) {
ContainerDoc_GetClipRect(lpContainerDoc, (LPRECT)&rcClipRect);
OleDbgOutRect3(
"OutlineDoc_Resize (ClipRect)", (LPRECT)&rcClipRect);
ContainerLine_UpdateInPlaceObjectRects(
lpLastUIActiveLine, &rcClipRect);
}
}
}
/* ContainerDoc_IsUIDeactivateNeeded
** ---------------------------------
** Check if it is necessary to UIDeactivate an in-place active
** object upon a mouse LBUTTONDOWN event. The position of the button
** down click is given by "pt".
** If there is not currently an in-place active line, then
** UIDeactivate is NOT needed.
** If there is a current in-place active line, then check if the
** point position is outside of the object extents on the screen. If
** so, then the object should be UIDeactivated, otherwise not.
*/
BOOL ContainerDoc_IsUIDeactivateNeeded(
LPCONTAINERDOC lpContainerDoc,
POINT pt
)
{
LPCONTAINERLINE lpUIActiveLine=lpContainerDoc->m_lpLastUIActiveLine;
RECT rect;
if (! lpUIActiveLine || ! lpUIActiveLine->m_fUIActive)
return FALSE;
ContainerLine_GetOleObjectRectInPixels(
lpUIActiveLine,
(LPRECT) &rect
);
if (! PtInRect((LPRECT) &rect, pt))
return TRUE;
return FALSE;
}
/* ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded
** -------------------------------------------------
** OLE2NOTE: this function ONLY applies for OUTSIDE-IN containers
**
** If there is a previous in-place active server still running and
** this server will not be needed to support the next OLE object
** about to be activated, then shut it down.
** in this way we manage a policy of having at most one in-place
** server running at a time. we do not imediately shut down the
** in-place server when the object is UIDeactivated because we want
** it to be fast if the server decides to re-activate the object
** in-place.
**
** shutting down the server is achieved by forcing the object to
** transition from running to loaded by calling IOleObject::Close.
*/
void ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded(
LPCONTAINERDOC lpContainerDoc,
LPCONTAINERLINE lpNextActiveLine
)
{
LPCONTAINERLINE lpLastIpActiveLine = lpContainerDoc->m_lpLastIpActiveLine;
BOOL fEnableServerShutDown = TRUE;
LPMONIKER lpmkLinkSrc;
LPMONIKER lpmkLastActiveObj;
LPMONIKER lpmkCommonPrefix;
LPOLELINK lpOleLink;
HRESULT hrErr;
/* OLE2NOTE: an inside-out style container can NOT use this scheme
** to shut down in-place servers. it would have to have a more
** sophistocated mechanism by which it keeps track of which
** objects are on screen and which were the last recently used.
*/
if (g_fInsideOutContainer)
return;
if (lpLastIpActiveLine != lpNextActiveLine) {
if (lpLastIpActiveLine) {
/* OLE2NOTE: if the object which is about to be activated is
** actually a link to the OLE object in last activated line,
** then we do NOT want to shut down the last activated
** server because it is about to be used. when activating a
** linked object, the source of the link gets activated.
*/
lpOleLink = (LPOLELINK)ContainerLine_GetOleObject(
lpNextActiveLine,
&IID_IOleLink
);
if (lpOleLink) {
OLEDBG_BEGIN2("IOleObject::GetSourceMoniker called\r\n")
lpOleLink->lpVtbl->GetSourceMoniker(
lpOleLink,
(LPMONIKER FAR*)&lpmkLinkSrc
);
OLEDBG_END2
if (lpmkLinkSrc) {
lpmkLastActiveObj = ContainerLine_GetFullMoniker(
lpLastIpActiveLine,
GETMONIKER_ONLYIFTHERE
);
if (lpmkLastActiveObj) {
hrErr = lpmkLinkSrc->lpVtbl->CommonPrefixWith(
lpmkLinkSrc,
lpmkLastActiveObj,
&lpmkCommonPrefix
);
if (GetScode(hrErr) == MK_S_HIM ||
GetScode(hrErr) == MK_S_US) {
/* the link source IS to the object
** contained in the last activated
** line of the document; disable the
** attempt to shut down the last
** running in-place server.
*/
fEnableServerShutDown = FALSE;
}
if (lpmkCommonPrefix)
OleStdRelease((LPUNKNOWN)lpmkCommonPrefix);
OleStdRelease((LPUNKNOWN)lpmkLastActiveObj);
}
OleStdRelease((LPUNKNOWN)lpmkLinkSrc);
}
OleStdRelease((LPUNKNOWN)lpOleLink);
}
/* if it is OK to shut down the previous in-place server
** and one is still running, then shut it down. shutting
** down the server is accomplished by forcing the OLE
** object to close. this forces the object to transition
** from running to loaded. if the object is actually
** only loaded then this is a NOP.
*/
if (fEnableServerShutDown &&
lpLastIpActiveLine->m_fIpServerRunning) {
OleDbgOut1("@@@ previous in-place server SHUT DOWN\r\n");
ContainerLine_CloseOleObject(lpLastIpActiveLine);
// we can now forget this last in-place active line.
lpContainerDoc->m_lpLastIpActiveLine = NULL;
}
}
}
}
/* ContainerDoc_GetUIActiveWindow
** ------------------------------
** If there is an UIActive object, then return its HWND.
*/
HWND ContainerDoc_GetUIActiveWindow(LPCONTAINERDOC lpContainerDoc)
{
return lpContainerDoc->m_hwndUIActiveObj;
}
/* ContainerDoc_GetClipRect
** ------------------------
** Get the ClipRect in client coordinates.
**
** OLE2NOTE: the ClipRect is defined as the maximum window rectangle
** that the in-place active object must be clipped to. this
** rectangle MUST be described in Client Coordinates of the window
** that is used as the Parent of the in-place active object's
** window. in our case, the LineList ListBox window is both the
** parent of the in-place active object AND defines precisely the
** clipping rectangle.
*/
void ContainerDoc_GetClipRect(
LPCONTAINERDOC lpContainerDoc,
LPRECT lprcClipRect
)
{
LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
/* OLE2NOTE: the ClipRect can be used to ensure that the in-place
** server does not overwrite areas of the window that the
** container paints into but which should never be overwritten
** (eg. if an app were to paint row and col headings directly in
** the same window that is the parent of the in-place window.
** whenever the window size changes or gets scrolled, in-place
** active object must be informed of the new clip rect.
**
** normally an app would pass the rect returned from GetClientRect.
** but because CntrOutl uses separate windows for row/column
** headings, status line, formula/tool bars, etc. it is NOT
** necessary to pass a constrained clip rect. Windows standard
** window clipping will automatically take care of all clipping
** that is necessary. thus we can take a short cut of passing an
** "infinite" clip rect, and then we do NOT need to call
** IOleInPlaceObject::SetObjectRects when our document is scrolled.
*/
lprcClipRect->top = 0;
lprcClipRect->left = 0;
lprcClipRect->right = 32767;
lprcClipRect->bottom = 32767;
}
/* ContainerDoc_GetTopInPlaceFrame
** -------------------------------
** returns NON-AddRef'ed pointer to Top In-Place Frame interface
*/
LPOLEINPLACEFRAME ContainerDoc_GetTopInPlaceFrame(
LPCONTAINERDOC lpContainerDoc
)
{
#if defined( INPLACE_CNTRSVR )
return lpContainerDoc->m_lpTopIPFrame;
#else
return (LPOLEINPLACEFRAME)&((LPCONTAINERAPP)g_lpApp)->m_OleInPlaceFrame;
#endif
}
void ContainerDoc_GetSharedMenuHandles(
LPCONTAINERDOC lpContainerDoc,
HMENU FAR* lphSharedMenu,
HOLEMENU FAR* lphOleMenu
)
{
#if defined( INPLACE_CNTRSVR )
if (lpContainerDoc->m_DocType == DOCTYPE_EMEBEDDEDOBJECT) {
*lphSharedMenu = lpContainerDoc->m_hSharedMenu;
*lphOleMenu = lpContainerDoc->m_hOleMenu;
return;
}
#endif
*lphSharedMenu = NULL;
*lphOleMenu = NULL;
}
#if defined( USE_FRAMETOOLS )
void ContainerDoc_RemoveFrameLevelTools(LPCONTAINERDOC lpContainerDoc)
{
LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
OleDbgAssert(lpOutlineDoc->m_lpFrameTools != NULL);
FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, FALSE);
}
#endif
void ContainerDoc_AddFrameLevelUI(LPCONTAINERDOC lpContainerDoc)
{
LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
LPOLEINPLACEFRAME lpTopIPFrame = ContainerDoc_GetTopInPlaceFrame(
lpContainerDoc);
HMENU hSharedMenu; // combined obj/cntr menu
HOLEMENU hOleMenu; // returned by OleCreateMenuDesc.
ContainerDoc_GetSharedMenuHandles(
lpContainerDoc,
&hSharedMenu,
&hOleMenu
);
lpTopIPFrame->lpVtbl->SetMenu(
lpTopIPFrame,
hSharedMenu,
hOleMenu,
lpOutlineDoc->m_hWndDoc
);
/* OLE2NOTE: even if our app does NOT use FrameTools, we must still
** call IOleInPlaceFrame::SetBorderSpace.
*/
ContainerDoc_AddFrameLevelTools(lpContainerDoc);
}
void ContainerDoc_AddFrameLevelTools(LPCONTAINERDOC lpContainerDoc)
{
LPOLEINPLACEFRAME lpTopIPFrame = ContainerDoc_GetTopInPlaceFrame(
lpContainerDoc);
LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc;
OleDbgAssert(lpTopIPFrame != NULL);
#if defined( USE_FRAMETOOLS )
FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, TRUE);
FrameTools_NegotiateForSpaceAndShow(
lpOutlineDoc->m_lpFrameTools,
NULL,
lpTopIPFrame
);
#else // ! USE_FRAMETOOLS
#if defined( INPLACE_CNTRSVR )
if (lpContainerDoc->m_DocType == DOCTYPE_EMBEDDEDOBJECT) {
/* this says i do not need space, so the top Frame should
** leave its tools behind
*/
OLEDBG_BEGIN2("IOleInPlaceFrame::SetBorderSpace(NULL) called\r\n")
lpTopIPFrame->lpVtbl->SetBorderSpace(lpTopIPFrame, NULL);
OLEDBG_END2
return;
}
#else // INPLACE_CNTR && ! USE_FRAMETOOLS
OLEDBG_BEGIN2("IOleInPlaceFrame::SetBorderSpace(0,0,0,0) called\r\n")
lpTopIPFrame->lpVtbl->SetBorderSpace(
lpTopIPFrame,
(LPCBORDERWIDTHS)&g_rectNull
);
OLEDBG_END2
#endif // INPLACE_CNTR && ! USE_FRAMETOOLS
#endif // ! USE_FRAMETOOLS
}
void ContainerDoc_FrameWindowResized(LPCONTAINERDOC lpContainerDoc)
{
LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
if (lpContainerApp->m_lpIPActiveObj) {
RECT rcFrameRect;
OutlineApp_GetFrameRect(g_lpApp, (LPRECT)&rcFrameRect);
OLEDBG_BEGIN2("IOleInPlaceActiveObject::ResizeBorder called\r\n")
lpContainerApp->m_lpIPActiveObj->lpVtbl->ResizeBorder(
lpContainerApp->m_lpIPActiveObj,
(LPCRECT)&rcFrameRect,
(LPOLEINPLACEUIWINDOW)&lpContainerApp->m_OleInPlaceFrame,
TRUE /* fFrameWindow */
);
OLEDBG_END2
}
#if defined( USE_FRAMETOOLS )
else {
ContainerDoc_AddFrameLevelTools(lpContainerDoc);
}
#endif
}
#if defined( INPLACE_CNTRSVR ) || defined( INPLACE_MDICNTR )
/* ContainerDoc_GetTopInPlaceDoc
** returns NON-AddRef'ed pointer to Top In-Place Doc interface
*/
LPOLEINPLACEUIWINDOW ContainerDoc_GetTopInPlaceDoc(
LPCONTAINERDOC lpContainerDoc
)
{
#if defined( INPLACE_CNTRSVR )
return lpContainerDoc->m_lpTopIPDoc;
#else
return (LPOLEINPLACEUIWINDOW)&lpContainerDoc->m_OleInPlaceDoc;
#endif
}
void ContainerDoc_RemoveDocLevelTools(LPCONTAINERDOC lpContainerDoc);
{
LPOLEINPLACEUIWINDOW lpTopIPDoc = ContainerDoc_GetTopInPlaceDoc(
lpContainerDoc);
if (lpTopIPDoc && lpContainerDoc->m_fMyToolsOnDoc) {
lpContainerDoc->m_fMyToolsOnDoc = FALSE;
// if we had doc tools we would HIDE them here;
// but NOT call SetBorderSpace(NULL)
}
}
void ContainerDoc_AddDocLevelTools(LPCONTAINERDOC lpContainerDoc)
{
LPOLEINPLACEUIWINDOW lpTopIPDoc = ContainerDoc_GetTopInPlaceDoc(
lpContainerDoc);
if (! lpTopIPDoc)
return;
#if defined( USE_DOCTOOLS )
if (lpTopIPDoc && ! lpContainerDoc->m_fMyToolsOnDoc) {
/* if we had doc tools we would negotiate for toolbar space at
** doc level and SHOW them.
*/
/* we do NOT have doc level tools, so we just call
** SetBorderSpace() to indicate to the top doc that
** our object does not need tool space.
*/
lpContainerDoc->m_fMyToolsOnDoc = TRUE;
return;
}
#else // ! USE_DOCTOOLS
#if defined( INPLACE_CNTRSVR )
if (lpContainerDoc->m_DocType == DOCTYPE_EMBEDDEDOBJECT) {
/* this says i do not need space, so the top doc should
** leave its tools behind
*/
lpTopIPDoc->lpVtbl->SetBorderSpace(lpTopIPDoc, NULL);
return;
}
#else
lpTopIPDoc->lpVtbl->SetBorderSpace(
lpTopIPDoc,
(LPCBORDERWIDTHS)&g_rectNull
);
#endif
#endif // ! USE_DOCTOOLS
}
#endif // INPLACE_CNTRSVR || INPLACE_MDICNTR
/*************************************************************************
** ContainerLine Support Functions and Interfaces
*************************************************************************/
/* ContainerLine_UIDeactivate
** --------------------------
** tell the OLE object associated with the ContainerLine to
** UIDeactivate. this informs the in-place server to tear down
** the UI and window that it put up for the object. it will remove
** its active editor menus and any frame and object adornments
** (eg. toolbars, rulers, etc.).
*/
void ContainerLine_UIDeactivate(LPCONTAINERLINE lpContainerLine)
{
HRESULT hrErr;
if (!lpContainerLine || !lpContainerLine->m_fUIActive)
return;
OLEDBG_BEGIN2("IOleInPlaceObject::UIDeactivate called\r\n")
hrErr = lpContainerLine->m_lpOleIPObj->lpVtbl->UIDeactivate(
lpContainerLine->m_lpOleIPObj);
OLEDBG_END2
if (hrErr != NOERROR) {
OleDbgOutHResult("IOleInPlaceObject::UIDeactivate returned", hrErr);
return;
}
#if defined( UNDOSUPPORTED )
/* OLE2NOTE: an outside-in style container that supports UNDO would
** call IOleObject::DoVerb(OLEIVERB_HIDE) to make the in-place
** object go invisible. when it wants the in-place active object
** to discard its undo state, it would call
** IOleInPlaceObject::InPlaceDeactivate when it wants the object
** to discard its undo state. there is no need for an outside-in
** style container to call
** IOleObject::DoVerb(OLEIVERB_DISCARDUNDOSTATE). if either the
** container or the object do not support UNDO, then the
** container might as well immediately call InPlaceDeactivate
** instead of calling DoVerb(HIDE).
**
** an inside-out style container that supports UNDO would simply
** UIDeactivate the object. it would call
** IOleObject::DoVerb(OLEIVERB_DISCARDUNDOSTATE) when it wants
** the object discard its undo state. it would call
** IOleInPlaceObject::InPlaceDeactivate if it wants the object
** to take down its window.
*/
if (! g_fInsideOutContainer) {
if (lpContainerLine->m_fIpChangesUndoable) {
ContainerLine_DoVerb(lpContainerLine,OLEIVERB_HIDE,FALSE,FALSE);
} else {
lpContainerLine->m_lpOleIPObj->lpVtbl->InPlaceDeactivate(
lpContainerLine->m_lpOleIPObj);
}
lpContainerLine->m_fIpVisible = FALSE;
}
#else
/* OLE2NOTE: an outside-in style container that does NOT support
** UNDO would immediately tell the UIDeactivated server (UI
** removed) to IOleInPlaceObject::InPlaceDeactivate.
**
** an inside-out style container that does NOT support UNDO
** would call IOleObject::DoVerb(OLEIVERB_DISCARDUNDOSTATE) to
** tell the object to discard its undo state. it would call
** IOleInPlaceObject::InPlaceDeactivate if it wants the object
** to take down its window.
*/
if (g_fInsideOutContainer) {
if (lpContainerLine->m_fInsideOutObj) {
if (lpContainerLine->m_fIpChangesUndoable) {
OLEDBG_BEGIN3("ContainerLine_DoVerb(OLEIVERB_DISCARDUNDOSTATE) called!\r\n")
ContainerLine_DoVerb(
lpContainerLine,OLEIVERB_DISCARDUNDOSTATE,FALSE,FALSE);
OLEDBG_END3
}
} else { // !fInsideOutObj
/* OLE2NOTE: (INSIDEOUT CONTAINER) if the object is not
** registered OLEMISC_ACTIVATEWHENVISIBLE, then we will
** make the object behave in an outside-in manner. since
** we do NOT deal with UNDO we can simply
** InPlaceDeactivate the object. it should NOT be
** allowed to leave its window visible when
** UIDeactivated.
*/
OLEDBG_BEGIN2("IOleInPlaceObject::InPlaceDeactivate called\r\n")
hrErr = lpContainerLine->m_lpOleIPObj->lpVtbl->InPlaceDeactivate(
lpContainerLine->m_lpOleIPObj);
OLEDBG_END2
if (hrErr != NOERROR) {
OleDbgOutHResult("IOleInPlaceObject::InPlaceDeactivate returned", hrErr);
}
}
} else {
/* OLE2NOTE: (OUTSIDE-IN CONTAINER) since we do NOT deal with
** UNDO we can simply InPlaceDeactivate the object. it
** should NOT be allowed to leave its window visible when
** UIDeactivated.
*/
OLEDBG_BEGIN2("IOleInPlaceObject::InPlaceDeactivate called\r\n")
hrErr = lpContainerLine->m_lpOleIPObj->lpVtbl->InPlaceDeactivate(
lpContainerLine->m_lpOleIPObj);
OLEDBG_END2
if (hrErr != NOERROR) {
OleDbgOutHResult("IOleInPlaceObject::InPlaceDeactivate returned", hrErr);
}
}
#endif // ! UNDOSUPPORTED
}
/* ContainerLine_UpdateInPlaceObjectRects
** -------------------------------------
** Update the PosRect and ClipRect of the given line
** currently in-place active
** object. if there is no object active in-place, then do nothing.
**
** OLE2NOTE: this function should be called when an action occurs
** that changes either the position of the object in the document
** (eg. changing document margins changes PosRect) or the clipRect
** changes (eg. resizing the document window changes the ClipRect).
*/
void ContainerLine_UpdateInPlaceObjectRects(
LPCONTAINERLINE lpContainerLine,
LPRECT lprcClipRect
)
{
LPCONTAINERDOC lpContainerDoc = lpContainerLine->m_lpDoc;
RECT rcClipRect;
RECT rcPosRect;
if (! lpContainerLine->m_fIpActive)
return;
if (! lprcClipRect) {
ContainerDoc_GetClipRect(lpContainerDoc, (LPRECT)&rcClipRect);
lprcClipRect = (LPRECT)&rcClipRect;
}
OleDbgOutRect3("OutlineDoc_Resize (ClipRect)", (LPRECT)&rcClipRect);
ContainerLine_GetOleObjectRectInPixels(
lpContainerLine,(LPRECT)&rcPosRect);
OleDbgOutRect3(
"ContainerLine_UpdateInPlaceObjectRects (PosRect)", (LPRECT)&rcPosRect);
OLEDBG_BEGIN2("IOleInPlaceObject::SetObjectRects called\r\n")
lpContainerLine->m_lpOleIPObj->lpVtbl->SetObjectRects(
lpContainerLine->m_lpOleIPObj,
(LPRECT)&rcPosRect,
lprcClipRect
);
OLEDBG_END2
}
/*************************************************************************
** ContainerLine::IOleInPlaceSite interface implementation
*************************************************************************/
STDMETHODIMP CntrLine_IPSite_QueryInterface(
LPOLEINPLACESITE lpThis,
REFIID riid,
LPVOID FAR* lplpvObj
)
{
LPCONTAINERLINE lpContainerLine =
((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
return ContainerLine_QueryInterface(lpContainerLine, riid, lplpvObj);
}
STDMETHODIMP_(ULONG) CntrLine_IPSite_AddRef(LPOLEINPLACESITE lpThis)
{
LPCONTAINERLINE lpContainerLine =
((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
OleDbgAddRefMethod(lpThis, "IOleInPlaceSite");
return ContainerLine_AddRef(lpContainerLine);
}
STDMETHODIMP_(ULONG) CntrLine_IPSite_Release(LPOLEINPLACESITE lpThis)
{
LPCONTAINERLINE lpContainerLine =
((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
OleDbgReleaseMethod(lpThis, "IOleInPlaceSite");
return ContainerLine_Release(lpContainerLine);
}
STDMETHODIMP CntrLine_IPSite_GetWindow(
LPOLEINPLACESITE lpThis,
HWND FAR* lphwnd
)
{
LPCONTAINERLINE lpContainerLine =
((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
OleDbgOut2("CntrLine_IPSite_GetWindow\r\n");
*lphwnd = LineList_GetWindow(&((LPOUTLINEDOC)lpContainerLine->m_lpDoc)->m_LineList);
return NOERROR;
}
STDMETHODIMP CntrLine_IPSite_ContextSensitiveHelp(
LPOLEINPLACESITE lpThis,
BOOL fEnterMode
)
{
OleDbgOut2("CntrLine_IPSite_ContextSensitiveHelp\r\n");
#if defined( LATER )
LPOLEINPLACEFRAME lpFrame = m_pEItem->m_pAC->GetInPlaceFrame();
HRESULT hrErr = lpFrame->ContextSensitiveHelp(fEnterMode);
lpFrame->Release();
#endif // LATER
return NOERROR;
}
STDMETHODIMP CntrLine_IPSite_CanInPlaceActivate(LPOLEINPLACESITE lpThis)
{
LPCONTAINERLINE lpContainerLine =
((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
OleDbgOut2("CntrLine_IPSite_CanInPlaceActivate\r\n");
/* OLE2NOTE: the container can NOT allow in-place activation if it
** is currently displaying the object as an ICON
** (DVASPECT_ICON). it can ONLY do in-place activation if it is
** displaying the DVASPECT_CONTENT of the OLE object.
*/
if (lpContainerLine->m_dwDrawAspect == DVASPECT_CONTENT)
return NOERROR;
else
return ResultFromScode(S_FALSE);
}
STDMETHODIMP CntrLine_IPSite_OnInPlaceActivate(LPOLEINPLACESITE lpThis)
{
LPCONTAINERLINE lpContainerLine =
((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
LPCONTAINERDOC lpContainerDoc = lpContainerLine->m_lpDoc;
SCODE sc = S_OK;
OLEDBG_BEGIN2("CntrLine_IPSite_OnInPlaceActivate\r\n");
/* OLE2NOTE: (OUTSIDE-IN CONTAINER) as a policy for managing
** running in-place servers, we will keep only 1 inplace server
** active at any given time. so when we start to inp-place activate
** another line, then we want to shut down the previously
** activated server. in this way we keep at most one inplace
** server active at a time. this is NOT a required policy. apps
** may choose to have a more sophisticated strategy. inside-out
** containers will HAVE to have a more sophisticated strategy,
** because they need (at a minimum) to keep all visible object
** servers running.
**
** if the in-place activation is the result of activating a
** linked object in another container, then we may arrive at
** this method while another object is currently active.
** normally, if the object is in-place activated by
** double-clicking or Edit.<verb> from our own container, then
** the previous in-place object would have been de-activated in
** ContainerLine_DoVerb method.
*/
if (!g_fInsideOutContainer) {
if (lpContainerDoc->m_lpLastIpActiveLine) {
ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded(
lpContainerDoc, lpContainerLine);
}
lpContainerDoc->m_lpLastIpActiveLine = lpContainerLine;
}
lpContainerLine->m_fIpActive = TRUE;
lpContainerLine->m_fIpVisible = TRUE;
lpContainerLine->m_fIpServerRunning = TRUE;
/* OLE2NOTE: to avoid LRPC problems it is important to cache the
** IOleInPlaceObject* pointer and NOT to call QueryInterface
** each time it is needed.
*/
lpContainerLine->m_lpOleIPObj =
(LPOLEINPLACEOBJECT) ContainerLine_GetOleObject (
lpContainerLine,
&IID_IOleInPlaceObject
);
OleDbgAssertSz(
lpContainerLine->m_lpOleIPObj!=NULL,
"OLE object must support IOleInPlaceObject"
);
if (! lpContainerLine->m_lpOleIPObj)
return ResultFromScode(E_FAIL); // ERROR: refuse to in-place activate
OLEDBG_END2
lpContainerLine->m_lpDoc->m_cIPActiveObjects++;
return NOERROR;
}
STDMETHODIMP CntrLine_IPSite_OnUIActivate (LPOLEINPLACESITE lpThis)
{
LPCONTAINERLINE lpContainerLine =
((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
LPCONTAINERDOC lpContainerDoc = lpContainerLine->m_lpDoc;
LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc;
LPCONTAINERLINE lpLastUIActiveLine = lpContainerDoc->m_lpLastUIActiveLine;
HWND hWndNewUIActiveObj;
OLEDBG_BEGIN2("CntrLine_IPSite_OnUIActivate\r\n");
lpContainerLine->m_fUIActive = TRUE;
lpContainerDoc->m_fAddMyUI = FALSE;
lpContainerDoc->m_lpLastUIActiveLine = lpContainerLine;
OLEDBG_BEGIN2("IOleInPlaceObject::GetWindow called\r\n")
lpContainerLine->m_lpOleIPObj->lpVtbl->GetWindow(
lpContainerLine->m_lpOleIPObj,
(HWND FAR*)&hWndNewUIActiveObj
);
OLEDBG_END2
if (g_fInsideOutContainer) {
/* OLE2NOTE: (INSIDE-OUT CONTAINER) an inside-out style
** container must UIDeactivate the previous UIActive object
** when a new object is going UIActive. since the inside-out
** objects have their own windows visible, it is possible
** that a click directly in an another server window will
** cause it to UIActivate. OnUIActivate is the containers
** notification that such has occured. it must then
** UIDeactivate the other because at most one object can be
** UIActive at a time.
*/
if (lpLastUIActiveLine && (lpLastUIActiveLine!=lpContainerLine)) {
ContainerLine_UIDeactivate(lpLastUIActiveLine);
// Make sure new UIActive window is on top of all others
SetWindowPos(
hWndNewUIActiveObj,
HWND_TOPMOST,
0,0,0,0,
SWP_NOMOVE | SWP_NOSIZE
);
OLEDBG_END2
return NOERROR;
}
}
lpContainerDoc->m_hwndUIActiveObj = hWndNewUIActiveObj;
#if defined( USE_FRAMETOOLS )
ContainerDoc_RemoveFrameLevelTools(lpContainerDoc);
#endif
#if defined( USE_DOCTOOLS )
ContainerDoc_RemoveDocLevelTools(lpContainerDoc);
#endif
OLEDBG_END2
return NOERROR;
}
STDMETHODIMP CntrLine_IPSite_GetWindowContext(
LPOLEINPLACESITE lpThis,
LPOLEINPLACEFRAME FAR* lplpFrame,
LPOLEINPLACEUIWINDOW FAR* lplpDoc,
LPRECT lprcPosRect,
LPRECT lprcClipRect,
LPOLEINPLACEFRAMEINFO lpFrameInfo
)
{
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp;
LPCONTAINERLINE lpContainerLine =
((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
OLEDBG_BEGIN2("CntrLine_IPSite_GetWindowContext\r\n")
/* OLE2NOTE: The server should fill in the "cb" field so that the
** container can tell what size structure the server is
** expecting. this enables this structure to be easily extended
** in future releases of OLE. the container should check this
** field so that it doesn't try to use fields that do not exist
** since the server may be using an old structure definition.
** Since this is the first release of OLE2.0, the structure is
** guaranteed to be at least large enough for the current
** definition of OLEINPLACEFRAMEINFO struct. thus we do NOT need
** to consider this an error if the server did not fill in this
** field correctly. this server may have trouble in the future,
** however, when the structure is extended.
*/
// OleDbgAssert(lpFrameInfo->cb >= sizeof(OLEINPLACEFRAMEINFO));
*lplpFrame = (LPOLEINPLACEFRAME)&lpContainerApp->m_OleInPlaceFrame;
(*lplpFrame)->lpVtbl->AddRef(*lplpFrame); // must return AddRef'ed ptr
// OLE2NOTE: an MDI app would have to provide *lplpDoc
*lplpDoc = NULL;
ContainerLine_GetOleObjectRectInPixels(lpContainerLine, lprcPosRect);
ContainerDoc_GetClipRect(lpContainerLine->m_lpDoc, lprcClipRect);
OleDbgOutRect3("CntrLine_IPSite_GetWindowContext (PosRect)", lprcPosRect);
OleDbgOutRect3("CntrLine_IPSite_GetWindowContext (ClipRect)",lprcClipRect);
lpFrameInfo->hwndFrame = lpOutlineApp->m_hWndApp;
#if defined( MDI_VERSION )
lpFrameInfo->fMDIApp = TRUE;
#else
lpFrameInfo->fMDIApp = FALSE;
#endif
lpFrameInfo->haccel = lpContainerApp->m_hAccelIPCntr;
lpFrameInfo->cAccelEntries = NUM_INPLACE_ACCELS;
OLEDBG_END2
return NOERROR;
}
STDMETHODIMP CntrLine_IPSite_Scroll(
LPOLEINPLACESITE lpThis,
SIZE scrollExtent
)
{
OleDbgOut2("CntrLine_IPSite_Scroll\r\n");
return ResultFromScode(E_FAIL);
}
STDMETHODIMP CntrLine_IPSite_OnUIDeactivate(
LPOLEINPLACESITE lpThis,
BOOL fUndoable
)
{
LPCONTAINERLINE lpContainerLine =
((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc;
LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP) g_lpApp;
LPLINELIST lpLL;
int nIndex;
MSG msg;
OLEDBG_BEGIN2("CntrLine_IPSite_OnUIDeactivate\r\n")
lpContainerLine->m_fUIActive = FALSE;
lpContainerLine->m_fIpChangesUndoable = fUndoable;
lpContainerLine->m_lpDoc->m_hwndUIActiveObj = NULL;
if (lpContainerLine == lpContainerLine->m_lpDoc->m_lpLastUIActiveLine) {
lpContainerLine->m_lpDoc->m_lpLastUIActiveLine = NULL;
/* OLE2NOTE: here we look ahead if there is a DBLCLK sitting in our
** message queue. if so, it could result in in-place activating
** another object. we want to avoid placing our tools and
** repainting if immediately another object is going to do the
** same. SO, if there is a DBLCLK in the queue for this document
** we will only set the fAddMyUI flag to indicate that this work
** is still to be done. if another object actually in-place
** activates then this flag will be cleared in
** IOleInPlaceSite::OnUIActivate. if it does NOT get cleared,
** then at the end of processing the DBLCLK message in our
** OutlineDocWndProc we will put our tools back.
*/
if (! PeekMessage(&msg, lpOutlineDoc->m_hWndDoc,
WM_LBUTTONDBLCLK, WM_LBUTTONDBLCLK,
PM_NOREMOVE | PM_NOYIELD)) {
#if defined( USE_DOCTOOLS )
ContainerDoc_AddDocLevelTools(lpContainerLine->m_lpDoc);
#endif
#if defined( USE_FRAMETOOLS )
ContainerDoc_AddFrameLevelUI(lpContainerLine->m_lpDoc);
#endif
} else {
lpContainerLine->m_lpDoc->m_fAddMyUI = TRUE;
}
/* OLE2NOTE: we should re-take focus. the in-place server window
** previously had the focus; this window has just been removed.
*/
SetFocus(OutlineDoc_GetWindow((LPOUTLINEDOC)lpContainerLine->m_lpDoc));
// force the line to redraw to remove in-place active hatch
lpLL = OutlineDoc_GetLineList(lpOutlineDoc);
nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine);
LineList_ForceLineRedraw(lpLL, nIndex, TRUE);
}
OLEDBG_END2
return NOERROR;
}
STDMETHODIMP CntrLine_IPSite_OnInPlaceDeactivate(LPOLEINPLACESITE lpThis)
{
LPCONTAINERLINE lpContainerLine =
((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
OLEDBG_BEGIN2("CntrLine_IPSite_OnInPlaceDeactivate\r\n");
lpContainerLine->m_fIpActive = FALSE;
lpContainerLine->m_fIpVisible = FALSE;
lpContainerLine->m_fIpChangesUndoable = FALSE;
OleStdRelease((LPUNKNOWN) lpContainerLine->m_lpOleIPObj);
lpContainerLine->m_lpOleIPObj = NULL;
lpContainerLine->m_lpDoc->m_cIPActiveObjects--;
OLEDBG_END2
return NOERROR;
}
STDMETHODIMP CntrLine_IPSite_DiscardUndoState(LPOLEINPLACESITE lpThis)
{
OleDbgOut2("CntrLine_IPSite_DiscardUndoState\r\n");
return NOERROR;
}
STDMETHODIMP CntrLine_IPSite_DeactivateAndUndo(LPOLEINPLACESITE lpThis)
{
OleDbgOut2("CntrLine_IPSite_DeactivateAndUndo\r\n");
return NOERROR;
}
STDMETHODIMP CntrLine_IPSite_OnPosRectChange(
LPOLEINPLACESITE lpThis,
LPCRECT lprcPosRect
)
{
LPCONTAINERLINE lpContainerLine =
((struct COleInPlaceSiteImpl FAR*)lpThis)->lpContainerLine;
LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc;
LPSCALEFACTOR lpscale = OutlineDoc_GetScaleFactor(lpOutlineDoc);
LPLINE lpLine = (LPLINE)lpContainerLine;
LPLINELIST lpLL;
int nIndex;
RECT rcClipRect;
RECT rcNewPosRect;
SIZEL sizelPix;
SIZEL sizelHim;
int nIPObjHeight = lprcPosRect->bottom - lprcPosRect->top;
int nIPObjWidth = lprcPosRect->right - lprcPosRect->left;
OLEDBG_BEGIN2("CntrLine_IPSite_OnPosRectChange\r\n")
OleDbgOutRect3("CntrLine_IPSite_OnPosRectChange (PosRect --IN)",
(LPRECT)lprcPosRect);
/* OLE2NOTE: if the in-place container does NOT impose any
** size contraints on its in-place active objects, then it may
** simply grant the size requested by the object by immediately
** calling IOleInPlaceObject::SetObjectRects with the
** lprcPosRect passed by the in-place object.
**
** Container Outline, however, imposes a size constraint on its
** embedded objects (see comment in ContainerLine_UpdateExtent),
** thus it is necessary to calculate the size that the in-place
** active object is allowed to be.
*/
/* calculate the new object extents. we can NOT directly ask the
** object via IOleObject::GetExtent because this method will
** retreive the extents of the last cached metafile. the cache
** has not yet been updated by this point. the best we can do is
** determine the scale factor that the object is operating at
** and scale the lprcPosRect back to HIMETRIC units.
*/
if (lpContainerLine->m_sizeInHimetric.cx > 0 &&
lpContainerLine->m_sizeInHimetric.cy > 0) {
sizelHim.cx = lpLine->m_nWidthInHimetric;
sizelHim.cy = lpLine->m_nHeightInHimetric;
XformSizeInHimetricToPixels(NULL, &sizelHim, &sizelPix);
sizelPix.cx -= 2* LINE_BOUNDARY_WIDTH;
sizelPix.cy -= 2* LINE_BOUNDARY_WIDTH;
sizelHim.cx = lpContainerLine->m_sizeInHimetric.cx * nIPObjWidth /
sizelPix.cx;
sizelHim.cy = lpContainerLine->m_sizeInHimetric.cy * nIPObjHeight /
sizelPix.cy;
// Convert size back to 100% zoom
sizelHim.cx = sizelHim.cx * lpscale->dwSxD / lpscale->dwSxN;
sizelHim.cy = sizelHim.cy * lpscale->dwSyD / lpscale->dwSyN;
} else {
sizelHim.cx = (long)DEFOBJWIDTH;
sizelHim.cy = (long)DEFOBJHEIGHT;
XformSizeInHimetricToPixels(NULL, &sizelHim, &sizelPix);
sizelHim.cx = sizelHim.cx * nIPObjWidth / sizelPix.cx;
sizelHim.cy = sizelHim.cy * nIPObjHeight / sizelPix.cy;
}
ContainerLine_UpdateExtent(lpContainerLine, &sizelHim);
ContainerLine_GetOleObjectRectInPixels(
lpContainerLine, (LPRECT)&rcNewPosRect);
ContainerDoc_GetClipRect(lpContainerLine->m_lpDoc, (LPRECT)&rcClipRect);
OleDbgOutRect3("CntrLine_IPSite_OnPosRectChange (PosRect --OUT)",
(LPRECT)&rcNewPosRect);
OleDbgOutRect3("CntrLine_IPSite_OnPosRectChange (ClipRect--OUT)",
(LPRECT)&rcClipRect);
OLEDBG_BEGIN2("IOleInPlaceObject::SetObjectRects called\r\n")
lpContainerLine->m_lpOleIPObj->lpVtbl->SetObjectRects(
lpContainerLine->m_lpOleIPObj,
(LPRECT)&rcNewPosRect,
(LPRECT)&rcClipRect
);
OLEDBG_END2
lpLL = OutlineDoc_GetLineList(lpOutlineDoc);
nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine);
ContainerDoc_UpdateInPlaceObjectRects(lpContainerLine->m_lpDoc, nIndex);
OLEDBG_END2
return NOERROR;
}
#endif // INPLACE_CNTR
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.