/************************************************************************* ** ** OLE 2 Server Sample Code ** ** svrinpl.c ** ** This file contains all interfaces, methods and related support ** functions for an In-Place Object (Server) application (aka. Visual ** Editing). The in-place Object application includes the following ** implementation objects: ** ** ServerDoc Object ** exposed interfaces: ** IOleInPlaceObject ** IOleInPlaceActiveObject ** ** ServerApp Object ** exposed interfaces: ** IUnknown ** ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved ** *************************************************************************/ #include "outline.h" OLEDBGDATA extern LPOUTLINEAPP g_lpApp; /* OLE2NOTE: the object should compose a string that is used by ** in-place containers to be used for the window titles. this string ** is passed to the container application via ** IOleInPlaceUIWindow::SetActiveObject. the string should have the ** following form: ** - ** SDI containers can use the string directly to display in the ** frame window title. the container would concatenate the string ** " in ". ** an MDI container with the MDI child window maximized can do the ** same as the SDI container. an MDI container with the MDI child ** windows NOT maximized can look for the " - " in the string from ** the object. the first part of the string (app name) would be put ** as the frame window title; the second part would be composed with ** " in " and used as the MDI child window ** title. */ // REVIEW: should use string resource for messages char g_szIPObjectTitle[] = APPNAME " - " SHORTUSERTYPENAME; extern RECT g_rectNull; /************************************************************************* ** ServerDoc::IOleInPlaceObject interface implementation *************************************************************************/ // IOleInPlaceObject::QueryInterface method STDMETHODIMP SvrDoc_IPObj_QueryInterface( LPOLEINPLACEOBJECT lpThis, REFIID riid, LPVOID FAR * lplpvObj ) { LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; return OleDoc_QueryInterface((LPOLEDOC)lpServerDoc, riid, lplpvObj); } // IOleInPlaceObject::AddRef method STDMETHODIMP_(ULONG) SvrDoc_IPObj_AddRef(LPOLEINPLACEOBJECT lpThis) { LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; OleDbgAddRefMethod(lpThis, "IOleInPlaceObject"); return OleDoc_AddRef((LPOLEDOC)lpServerDoc); } // IOleInPlaceObject::Release method STDMETHODIMP_(ULONG) SvrDoc_IPObj_Release(LPOLEINPLACEOBJECT lpThis) { LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; OleDbgReleaseMethod(lpThis, "IOleInPlaceObject"); return OleDoc_Release((LPOLEDOC)lpServerDoc); } // IOleInPlaceObject::GetWindow method STDMETHODIMP SvrDoc_IPObj_GetWindow( LPOLEINPLACEOBJECT lpThis, HWND FAR* lphwnd ) { LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; OLEDBG_BEGIN2("SvrDoc_IPObj_GetWindow\r\n") *lphwnd = ((LPOUTLINEDOC)lpServerDoc)->m_hWndDoc; OLEDBG_END2 return S_OK; } // IOleInPlaceObject::ContextSensitiveHelp method STDMETHODIMP SvrDoc_IPObj_ContextSensitiveHelp( LPOLEINPLACEOBJECT lpThis, BOOL fEnable ) { LPOLEDOC lpOleDoc = (LPOLEDOC)((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; OleDbgOut2("SvrDoc_IPObj_ContextSensitiveHelp\r\n"); /* OLE2NOTE: see context sensitive help technote (CSHELP.DOC). ** This method is called when SHIFT-F1 context sensitive help is ** entered. the cursor should then change to a question mark ** cursor and the app should enter a modal state where the next ** mouse click does not perform its normal action but rather ** gives help corresponding to the location clicked. if the app ** does not implement a help system, it should at least eat the ** click and do nothing. */ lpOleDoc->m_fCSHelpMode = fEnable; return S_OK; } // IOleInPlaceObject::InPlaceDeactivate method STDMETHODIMP SvrDoc_IPObj_InPlaceDeactivate(LPOLEINPLACEOBJECT lpThis) { LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; HRESULT hrErr; OLEDBG_BEGIN2("SvrDoc_IPObj_InPlaceDeactivate\r\n") hrErr = ServerDoc_DoInPlaceDeactivate(lpServerDoc); OLEDBG_END2 return hrErr; } // IOleInPlaceObject::UIDeactivate method STDMETHODIMP SvrDoc_IPObj_UIDeactivate(LPOLEINPLACEOBJECT lpThis) { LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpServerDoc)->m_LineList; HWND hWndApp = OutlineApp_GetWindow(g_lpApp); OLEDBG_BEGIN2("SvrDoc_IPObj_UIDeactivate\r\n"); if (!lpServerDoc->m_fUIActive) { OLEDBG_END2 return NOERROR; } lpServerDoc->m_fUIActive = FALSE; // Clip the hatch window to the size of pos rect so, that the object // adornments and hatch border will not be visible. ServerDoc_ResizeInPlaceWindow(lpServerDoc, (LPRECT)&(lpServerDoc->m_lpIPData->rcPosRect), (LPRECT)&(lpServerDoc->m_lpIPData->rcPosRect) ); if (lpIPData->lpDoc) lpIPData->lpDoc->lpVtbl->SetActiveObject(lpIPData->lpDoc, NULL, NULL); if (lpIPData->lpFrame) { lpIPData->lpFrame->lpVtbl->SetActiveObject( lpIPData->lpFrame, NULL, NULL ); } #if defined( USE_FRAMETOOLS ) /* OLE2NOTE: we must hide our frame tools here but NOT call ** IOleInPlaceFrame::SetBorderSpace(NULL) or SetMenu(NULL). ** we must hide our tools BEFORE calling ** IOleInPlaceSite::OnUIDeactivate. the container will put ** his menus and tools back when OnUIDeactivate is called. */ ServerDoc_RemoveFrameLevelTools(lpServerDoc); #endif OLEDBG_BEGIN2("IOleInPlaceSite::OnUIDeactivate called\r\n"); lpIPData->lpSite->lpVtbl->OnUIDeactivate(lpIPData->lpSite, FALSE); OLEDBG_END2 /* Reset to use our normal app's accelerator table */ g_lpApp->m_hAccelApp = lpServerApp->m_hAccelBaseApp; g_lpApp->m_hAccel = lpServerApp->m_hAccelBaseApp; g_lpApp->m_hWndAccelTarget = hWndApp; OLEDBG_END2 #if !defined( SVR_INSIDEOUT ) /* OLE2NOTE: an "outside-in" style in-place server would hide its ** window here. an "inside-out" style server leaves its window ** visible when it is UIDeactivated. it would only hide its ** window when InPlaceDeactivated. this app is an "inside-out" ** style server. it is recommended for most server to support ** inside-out behavior if possible. */ ServerDoc_DoInPlaceHide(lpServerDoc); #endif // INSIEDOUT return NOERROR; } // IOleInPlaceObject::SetObjectRects method STDMETHODIMP SvrDoc_IPObj_SetObjectRects( LPOLEINPLACEOBJECT lpThis, LPCRECT lprcPosRect, LPCRECT lprcClipRect ) { LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; LPLINELIST lpLL = OutlineDoc_GetLineList((LPOUTLINEDOC)lpServerDoc); OLEDBG_BEGIN2("SvrDoc_IPObj_SetObjectRects\r\n") #if defined( _DEBUG ) OleDbgOutRect3("SvrDoc_IPObj_SetObjectRects (PosRect)", (LPRECT)lprcPosRect); OleDbgOutRect3("SvrDoc_IPObj_SetObjectRects (ClipRect)", (LPRECT)lprcClipRect); #endif // save the current PosRect and ClipRect lpIPData->rcPosRect = *lprcPosRect; lpIPData->rcClipRect = *lprcClipRect; if (! lpServerDoc->m_fUIActive) // hatch and adornaments must not be drawn lprcClipRect = lprcPosRect; ServerDoc_ResizeInPlaceWindow( lpServerDoc, (LPRECT)lprcPosRect, (LPRECT)lprcClipRect); OLEDBG_END2 return NOERROR; } // IOleInPlaceObject::ReactivateAndUndo method STDMETHODIMP SvrDoc_IPObj_ReactivateAndUndo(LPOLEINPLACEOBJECT lpThis) { OLEDBG_BEGIN2("SvrDoc_IPObj_ReactivateAndUndo\r\n") // We do not support support UNDO. /* REVIEW: for debugging purposes it would be useful to give a ** message box indicating that this method has been called. */ OLEDBG_END2 return NOERROR; } /************************************************************************* ** ServerDoc::IOleInPlaceActiveObject interface implementation *************************************************************************/ // IOleInPlaceActiveObject::QueryInterface method STDMETHODIMP SvrDoc_IPActiveObj_QueryInterface( LPOLEINPLACEACTIVEOBJECT lpThis, REFIID riid, LPVOID FAR * lplpvObj ) { SCODE sc = E_NOINTERFACE; LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; /* The container should not be able to access the other interfaces ** of our object by doing QI on this interface. */ *lplpvObj = NULL; if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IOleWindow) || IsEqualIID(riid, &IID_IOleInPlaceActiveObject)) { OleDbgOut4("OleDoc_QueryInterface: IOleInPlaceActiveObject* RETURNED\r\n"); *lplpvObj = lpThis; OleDoc_AddRef((LPOLEDOC)lpServerDoc); sc = NOERROR; } OleDbgQueryInterfaceMethod(*lplpvObj); return ResultFromScode(sc); } // IOleInPlaceActiveObject::AddRef method STDMETHODIMP_(ULONG) SvrDoc_IPActiveObj_AddRef( LPOLEINPLACEACTIVEOBJECT lpThis ) { LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; OleDbgAddRefMethod(lpThis, "IOleInPlaceActiveObject"); return OleDoc_AddRef((LPOLEDOC)lpServerDoc); } // IOleInPlaceActiveObject::Release method STDMETHODIMP_(ULONG) SvrDoc_IPActiveObj_Release( LPOLEINPLACEACTIVEOBJECT lpThis ) { LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; OleDbgReleaseMethod(lpThis, "IOleInPlaceActiveObject"); return OleDoc_Release((LPOLEDOC)lpServerDoc); } // IOleInPlaceActiveObject::GetWindow method STDMETHODIMP SvrDoc_IPActiveObj_GetWindow( LPOLEINPLACEACTIVEOBJECT lpThis, HWND FAR* lphwnd ) { LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; OLEDBG_BEGIN2("SvrDoc_IPActiveObj_GetWindow\r\n") *lphwnd = ((LPOUTLINEDOC)lpServerDoc)->m_hWndDoc; OLEDBG_END2 return NOERROR; } // IOleInPlaceActiveObject::ContextSensitiveHelp method STDMETHODIMP SvrDoc_IPActiveObj_ContextSensitiveHelp( LPOLEINPLACEACTIVEOBJECT lpThis, BOOL fEnterMode ) { LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; OleDbgOut2("SvrDoc_IPActiveObj_ContextSensitiveHelp\r\n"); /* OLE2NOTE: see context sensitive help technote (CSHELP.DOC) ** This method is called when F1 is pressed when a menu item is ** selected. this tells the in-place server application to give ** help rather than execute the next menu command. at a minimum, ** even if the in-place server application does not implement a ** help system, it should NOT execute the next command when ** fEnable==TRUE. We set the active object's m_fMenuMode flag here. ** later, in WM_COMMAND processing in the DocWndProc, if this ** flag is set then the command is NOT executed (and help could ** be given if we had a help system....but we don't.) */ lpServerDoc->m_fMenuHelpMode = fEnterMode; #if !defined( HACK ) ((LPOLEDOC)lpServerDoc)->m_fCSHelpMode = fEnterMode; #endif return NOERROR; } // IOleInPlaceActiveObject::TranslateAccelerator method STDMETHODIMP SvrDoc_IPActiveObj_TranslateAccelerator( LPOLEINPLACEACTIVEOBJECT lpThis, LPMSG lpmsg ) { // This will never be called because this server is implemented as an EXE return NOERROR; } // IOleInPlaceActiveObject::OnFrameWindowActivate method STDMETHODIMP SvrDoc_IPActiveObj_OnFrameWindowActivate( LPOLEINPLACEACTIVEOBJECT lpThis, BOOL fActivate ) { LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC) ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; HWND hWndDoc = OutlineDoc_GetWindow(lpOutlineDoc); #if defined( _DEBUG ) if (fActivate) OleDbgOut2("SvrDoc_IPActiveObj_OnFrameWindowActivate(TRUE)\r\n"); else OleDbgOut2("SvrDoc_IPActiveObj_OnFrameWindowActivate(FALSE)\r\n"); #endif // _DEBUG /* OLE2NOTE: this is a notification of the container application's ** WM_ACTIVATEAPP status. some applications may find this ** important. we need to update the enable/disable status of our ** tool bar buttons. */ // OLE2NOTE: We can't call OutlineDoc_UpdateFrameToolButtons // right away which // would generate some OLE calls and eventually // WM_ACTIVATEAPP and a loop was formed. Therefore, we // should delay the frame tool initialization until // WM_ACTIVATEAPP is finished by posting a message // to ourselves. /* Update enable/disable state of buttons in toolbar */ if (fActivate) PostMessage(hWndDoc, WM_U_INITFRAMETOOLS, 0, 0L); return NOERROR; } // IOleInPlaceActiveObject::OnDocWindowActivate method STDMETHODIMP SvrDoc_IPActiveObj_OnDocWindowActivate( LPOLEINPLACEACTIVEOBJECT lpThis, BOOL fActivate ) { LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; #if defined( _DEBUG ) if (fActivate) OleDbgOut2("SvrDoc_IPActiveObj_OnDocWindowActivate(TRUE)\r\n"); else OleDbgOut2("SvrDoc_IPActiveObj_OnDocWindowActivate(FALSE)\r\n"); #endif if (fActivate) { ServerDoc_AddFrameLevelUI(lpServerDoc); } else { #if defined( USE_FRAMETOOLS ) /* OLE2NOTE: we must NOT call IOleInPlaceFrame::SetBorderSpace(NULL) ** or SetMenu(NULL) here. we should simply hide our tools. */ ServerDoc_RemoveFrameLevelTools(lpServerDoc); #endif } OLEDBG_END2 return NOERROR; } // IOleInPlaceActiveObject::ResizeBorder method STDMETHODIMP SvrDoc_IPActiveObj_ResizeBorder( LPOLEINPLACEACTIVEOBJECT lpThis, LPCRECT lprectBorder, LPOLEINPLACEUIWINDOW lpIPUiWnd, BOOL fFrameWindow ) { LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; OLEDBG_BEGIN2("SvrDoc_IPActiveObj_ResizeBorder\r\n") #if defined( USE_FRAMETOOLS ) if (fFrameWindow) { FrameTools_NegotiateForSpaceAndShow( lpOutlineDoc->m_lpFrameTools, (LPRECT)lprectBorder, (LPOLEINPLACEFRAME)lpIPUiWnd ); } #endif OLEDBG_END2 return NOERROR; } // IOleInPlaceActiveObject::EnableModeless method STDMETHODIMP SvrDoc_IPActiveObj_EnableModeless( LPOLEINPLACEACTIVEOBJECT lpThis, BOOL fEnable ) { #if defined( USE_FRAMETOOLS ) LPSERVERDOC lpServerDoc = ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc; LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; LPFRAMETOOLS lptb; /* OLE2NOTE: we must enable/disable mouse and keyboard input to our ** floating tool palette */ if (lpOutlineDoc) { lptb = lpOutlineDoc->m_lpFrameTools; if (lptb) FrameTools_EnableWindow(lptb, fEnable); } #endif // USE_FRAMETOOLS #if defined( _DEBUG ) if (fEnable) OleDbgOut2("SvrDoc_IPActiveObj_EnableModeless(TRUE)\r\n"); else OleDbgOut2("SvrDoc_IPActiveObj_EnableModeless(FALSE)\r\n"); #endif // _DEBUG /* OLE2NOTE: this method is called when the top-level, in-place ** container puts up a modal dialog. it tells the UIActive ** object to disable it modeless dialogs for the duration that ** the container is displaying a modal dialog. ** ** ISVROTL does not use any modeless dialogs, thus we can ** ignore this method. */ return NOERROR; } /************************************************************************* ** Support Functions *************************************************************************/ HRESULT ServerDoc_DoInPlaceActivate( LPSERVERDOC lpServerDoc, LONG lVerb, LPMSG lpmsg, LPOLECLIENTSITE lpActiveSite ) { LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; SCODE sc = E_FAIL; RECT rcPos; RECT rcClip; LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; LPOUTLINEDOC lpOutlineDoc=(LPOUTLINEDOC)lpServerDoc; HWND hWndDoc = lpOutlineDoc->m_hWndDoc; HWND hWndHatch = lpServerDoc->m_hWndHatch; HRESULT hrErr; LPLINELIST lpLL=(LPLINELIST)&lpOutlineDoc->m_LineList; LPOLEINPLACESITE lpIPSite = NULL; /* OLE2NOTE: lpActiveSite should be used only for InPlace PLAYing. ** This app does not do inplace PLAYing, so it never uses ** lpActiveSite. */ /* InPlace activation can only be done if the ClientSite is non-NULL. */ if (! lpServerDoc->m_lpOleClientSite) return NOERROR; if (! lpServerDoc->m_fInPlaceActive) { // if the object is in open mode then we do not want to do inplace // activation. if (IsWindowVisible(lpOutlineDoc->m_hWndDoc)) return NOERROR; lpIPSite = (LPOLEINPLACESITE)OleStdQueryInterface( (LPUNKNOWN)lpServerDoc->m_lpOleClientSite, &IID_IOleInPlaceSite ); if (! lpIPSite) goto errActivate; OLEDBG_BEGIN2("IOleInPlaceSite::CanInPlaceActivate called\r\n"); hrErr = lpIPSite->lpVtbl->CanInPlaceActivate(lpIPSite); OLEDBG_END2 if (hrErr != NOERROR) goto errActivate; lpServerDoc->m_fInPlaceActive = TRUE; OLEDBG_BEGIN2("IOleInPlaceSite::OnInPlaceActivate called\r\n"); hrErr = lpIPSite->lpVtbl->OnInPlaceActivate(lpIPSite); OLEDBG_END2 if (hrErr != NOERROR) goto errActivate; if (! ServerDoc_AllocInPlaceData(lpServerDoc)) { sc = E_OUTOFMEMORY; OLEDBG_BEGIN2("IOleInPlaceSite::OnInPlaceDeactivate called\r\n"); lpIPSite->lpVtbl->OnInPlaceDeactivate(lpIPSite); OLEDBG_END2 goto errActivate; } (lpIPData = lpServerDoc->m_lpIPData)->lpSite = lpIPSite; goto InPlaceActive; errActivate: lpServerDoc->m_fInPlaceActive = FALSE; if (lpIPSite) OleStdRelease((LPUNKNOWN)lpIPSite); return ResultFromScode(sc); } InPlaceActive: if (! lpServerDoc->m_fInPlaceVisible) { lpServerDoc->m_fInPlaceVisible = TRUE; OLEDBG_BEGIN2("IOleInPlaceSite::GetWindow called\r\n"); hrErr = lpIPData->lpSite->lpVtbl->GetWindow( lpIPData->lpSite, &lpServerDoc->m_hWndParent); OLEDBG_END2 if (hrErr != NOERROR) { sc = GetScode(hrErr); goto errRtn; } if (! lpServerDoc->m_hWndParent) goto errRtn; /* 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. */ _fmemset( (LPOLEINPLACEFRAMEINFO)&lpIPData->frameInfo, 0, sizeof(OLEINPLACEFRAMEINFO) ); lpIPData->frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO); OLEDBG_BEGIN2("IOleInPlaceSite::GetWindowContext called\r\n"); hrErr = lpIPData->lpSite->lpVtbl->GetWindowContext(lpIPData->lpSite, (LPOLEINPLACEFRAME FAR*) &lpIPData->lpFrame, (LPOLEINPLACEUIWINDOW FAR*)&lpIPData->lpDoc, (LPRECT)&rcPos, (LPRECT)&rcClip, (LPOLEINPLACEFRAMEINFO)&lpIPData->frameInfo); OLEDBG_END2 if (hrErr != NOERROR) { sc = GetScode(hrErr); goto errRtn; } lpServerApp->m_lpIPData = lpIPData; ShowWindow(hWndDoc, SW_HIDE); // make sure we are hidden /* OLE2NOTE: reparent in-place server document's window to the ** special in-place hatch border window. set the in-place site's ** window as the parent of the hatch window. position the ** in-place and hatch border windows using the PosRect and ** ClipRect. ** it is important to properly parent and position the in-place ** server window BEFORE calling IOleInPlaceFrame::SetMenu and ** SetBorderSpace. */ ShowWindow(lpServerDoc->m_hWndHatch, SW_SHOW); // make sure App busy/blocked dialogs are parented to our // new hWndFrame OleStdMsgFilter_SetParentWindow( lpOleApp->m_lpMsgFilter,lpIPData->frameInfo.hwndFrame); SetParent(lpServerDoc->m_hWndHatch, lpServerDoc->m_hWndParent); SetParent(hWndDoc, lpServerDoc->m_hWndHatch); #if defined( _DEBUG ) OleDbgOutRect3("IOleInPlaceSite::GetWindowContext (PosRect)", (LPRECT)&rcPos); OleDbgOutRect3("IOleInPlaceSite::GetWindowContext (ClipRect)", (LPRECT)&rcClip); #endif // save the current PosRect and ClipRect lpIPData->rcPosRect = rcPos; lpIPData->rcClipRect = rcClip; /* OLE2NOTE: build the shared menu for the in-place container and ** the server. */ if (ServerDoc_AssembleMenus (lpServerDoc) != NOERROR) goto errRtn; #if defined( SVR_INSIDEOUT ) if (lVerb == OLEIVERB_INPLACEACTIVATE) { // Clip the hatch window to the size of pos rect so, that // hatch and object adornments will not be visible. ServerDoc_ResizeInPlaceWindow(lpServerDoc, (LPRECT)&(lpServerDoc->m_lpIPData->rcPosRect), (LPRECT)&(lpServerDoc->m_lpIPData->rcPosRect) ); } #endif // SVR_INSIDEOUT } #if defined( SVR_INSIDEOUT ) // OLE2NOTE: if verb is OLEIVERB_INPLACEACTIVATE we do NOT want to // show our UI if (lVerb == OLEIVERB_INPLACEACTIVATE) { return NOERROR; } #endif // SVR_INSIDEOUT if (! lpServerDoc->m_fUIActive) { lpServerDoc->m_fUIActive = TRUE; OLEDBG_BEGIN2("IOleInPlaceSite::OnUIActivate called\r\n"); hrErr = lpIPData->lpSite->lpVtbl->OnUIActivate(lpIPData->lpSite); OLEDBG_END2 if (hrErr != NOERROR) { lpServerDoc->m_fUIActive = FALSE; goto errRtn; } SetFocus(hWndDoc); // Show the object adornments and hacth border around them. ServerDoc_ResizeInPlaceWindow(lpServerDoc, (LPRECT)&lpIPData->rcPosRect, (LPRECT)&lpIPData->rcClipRect ); /* OLE2NOTE: IOleInPlaceFrame::SetActiveObject must be called BEFORE ** IOleInPlaceFrame::SetMenu. */ OLEDBG_BEGIN2("IOleInPlaceSite::SetActiveObject called\r\n"); CallIOleInPlaceUIWindowSetActiveObjectA( (struct IOleInPlaceUIWindow *) lpIPData->lpFrame, (LPOLEINPLACEACTIVEOBJECT) &lpServerDoc->m_OleInPlaceActiveObject, (LPSTR)g_szIPObjectTitle ); OLEDBG_END2 /* OLE2NOTE: If the container wants to give ownership of the ** palette then he would sendmessage WM_QUEYNEWPALETTE to ** the object window proc, before returning from ** IOleInPlaceFrame::SetActiveObject. Those objects which ** want to be edited inplace only if they have the ownership of ** the palette, can check at this point in the code whether ** they got WM_QUERYNEWPALETTE or not. If they didn't get ** the message, then they can inplace deactivate and do open ** editing instead. */ if (lpIPData->lpDoc) { CallIOleInPlaceUIWindowSetActiveObjectA( lpIPData->lpDoc, (LPOLEINPLACEACTIVEOBJECT)&lpServerDoc->m_OleInPlaceActiveObject, (LPSTR)g_szIPObjectTitle ); } /* OLE2NOTE: install the menu and frame-level tools on the in-place ** frame. */ ServerDoc_AddFrameLevelUI(lpServerDoc); } return NOERROR; errRtn: ServerDoc_DoInPlaceDeactivate(lpServerDoc); return ResultFromScode(sc); } HRESULT ServerDoc_DoInPlaceDeactivate(LPSERVERDOC lpServerDoc) { LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; if (!lpServerDoc->m_fInPlaceActive) return S_OK; lpServerDoc->m_fInPlaceActive = FALSE; SvrDoc_IPObj_UIDeactivate( (LPOLEINPLACEOBJECT)&lpServerDoc->m_OleInPlaceObject); /* OLE2NOTE: an inside-out style in-place server will ** NOT hide its window in UIDeactive (an outside-in ** style object will hide its window in UIDeactivate). ** thus, an inside-out server must explicitly hide ** its window in InPlaceDeactivate. it is ALSO important for an ** outside-in style object to call ServerDoc_DoInPlaceHide here ** BEFORE freeing the InPlaceData structure. it will be common ** for in-place containers to call IOleInPlaceObject:: ** InPlaceDeactivate in their IOleInPlaceSite::OnUIDeactiate ** implementation. */ ServerDoc_DoInPlaceHide(lpServerDoc); OLEDBG_BEGIN2("IOleInPlaceSite::OnInPlaceDeactivate called\r\n"); lpIPData->lpSite->lpVtbl->OnInPlaceDeactivate(lpIPData->lpSite); OLEDBG_END2 OleStdRelease((LPUNKNOWN)lpIPData->lpSite); lpIPData->lpSite = NULL; ServerDoc_FreeInPlaceData(lpServerDoc); return NOERROR; } HRESULT ServerDoc_DoInPlaceHide(LPSERVERDOC lpServerDoc) { LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; HWND hWndApp = OutlineApp_GetWindow(g_lpApp); if (! lpServerDoc->m_fInPlaceVisible) return NOERROR; // Set the parent back to server app's window OleDoc_HideWindow((LPOLEDOC)lpServerDoc, FALSE /* fShutdown */); /* we need to enusure that our window is set to normal 100% zoom. ** if the window is next shown in open mode it should start out ** at normal zoom factor. our window may have been set to a ** different zoom factor while it was in-place active. */ OutlineDoc_SetCurrentZoomCommand(lpOutlineDoc,IDM_V_ZOOM_100); lpServerDoc->m_fInPlaceVisible = FALSE; lpServerDoc->m_hWndParent = hWndApp; SetParent( lpOutlineDoc->m_hWndDoc, lpServerDoc->m_hWndParent ); // make sure App busy/blocked dialogs are parented to our own hWndApp OleStdMsgFilter_SetParentWindow(lpOleApp->m_lpMsgFilter, hWndApp); // Hide the in-place hatch border window. ShowWindow(lpServerDoc->m_hWndHatch, SW_HIDE); ServerDoc_DisassembleMenus(lpServerDoc); /* we no longer need the IOleInPlaceFrame* or the doc's ** IOleInPlaceWindow* interface pointers. */ if (lpIPData->lpDoc) { OleStdRelease((LPUNKNOWN)lpIPData->lpDoc); lpIPData->lpDoc = NULL; } if (lpIPData->lpFrame) { OleStdRelease((LPUNKNOWN)lpIPData->lpFrame); lpIPData->lpFrame = NULL; } ((LPSERVERAPP)g_lpApp)->m_lpIPData = NULL; return NOERROR; } BOOL ServerDoc_AllocInPlaceData(LPSERVERDOC lpServerDoc) { LPINPLACEDATA lpIPData; if (!(lpIPData = (LPINPLACEDATA) New(sizeof(INPLACEDATA)))) return FALSE; lpIPData->lpFrame = NULL; lpIPData->lpDoc = NULL; lpIPData->lpSite = NULL; lpIPData->hOlemenu = NULL; lpIPData->hMenuShared = NULL; lpServerDoc->m_lpIPData = lpIPData; return TRUE; } void ServerDoc_FreeInPlaceData(LPSERVERDOC lpServerDoc) { Delete(lpServerDoc->m_lpIPData); lpServerDoc->m_lpIPData = NULL; } HRESULT ServerDoc_AssembleMenus(LPSERVERDOC lpServerDoc) { HMENU hMenuShared; LONG FAR* lpWidths; UINT uPosition; UINT uPositionStart; LPSERVERAPP lpServerApp = (LPSERVERAPP) g_lpApp; LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; HRESULT hresult; BOOL fNoError = TRUE; lpWidths = lpIPData->menuGroupWidths.width; hMenuShared = CreateMenu(); if (hMenuShared && (hresult = lpIPData->lpFrame->lpVtbl->InsertMenus( lpIPData->lpFrame, hMenuShared, &lpIPData->menuGroupWidths)) == NOERROR) { /* Insert EDIT group menus */ uPosition = (UINT)lpWidths[0]; /* # of menus in the FILE group */ uPositionStart = uPosition; fNoError &= InsertMenu( hMenuShared, (UINT)uPosition, (UINT)(MF_BYPOSITION | MF_POPUP), (UINT)lpServerApp->m_hMenuEdit, (LPCSTR)"&Edit" ); uPosition++; lpWidths[1] = uPosition - uPositionStart; /* Insert OBJECT group menus */ uPosition += (UINT)lpWidths[2]; uPositionStart = uPosition; fNoError &= InsertMenu( hMenuShared, (UINT)uPosition, (UINT)(MF_BYPOSITION | MF_POPUP), (UINT)lpServerApp->m_hMenuLine, (LPCSTR)"&Line" ); uPosition++; fNoError &= InsertMenu( hMenuShared, (UINT)uPosition, (UINT)(MF_BYPOSITION | MF_POPUP), (UINT)lpServerApp->m_hMenuName, (LPCSTR)"&Name" ); uPosition++; fNoError &= InsertMenu( hMenuShared, (UINT)uPosition, (UINT)(MF_BYPOSITION | MF_POPUP), (UINT)lpServerApp->m_hMenuOptions, (LPCSTR)"&Options" ); uPosition++; fNoError &= InsertMenu( hMenuShared, (UINT)uPosition, (UINT)(MF_BYPOSITION | MF_POPUP), (UINT)lpServerApp->m_hMenuDebug, (LPCSTR)"DbgI&Svr" ); uPosition++; lpWidths[3] = uPosition - uPositionStart; /* Insert HELP group menus */ uPosition += (UINT) lpWidths[4]; /* # of menus in WINDOW group */ uPositionStart = uPosition; fNoError &= InsertMenu( hMenuShared, (UINT)uPosition, (UINT)(MF_BYPOSITION | MF_POPUP), (UINT)lpServerApp->m_hMenuHelp, (LPCSTR)"&Help" ); uPosition++; lpWidths[5] = uPosition - uPositionStart; OleDbgAssert(fNoError == TRUE); } else { /* In-place container does not allow us to add menus to the ** frame. ** OLE2NOTE: even when the in-place container does NOT allow ** the building of a merged menu bar, it is CRITICAL that ** the in-place server still call OleCreateMenuDescriptor ** passing NULL for hMenuShared. */ if (hMenuShared) { DestroyMenu(hMenuShared); hMenuShared = NULL; } } lpIPData->hMenuShared = hMenuShared; if (!(lpIPData->hOlemenu = OleCreateMenuDescriptor(hMenuShared, &lpIPData->menuGroupWidths))) return ResultFromScode(E_OUTOFMEMORY); return NOERROR; } void ServerDoc_DisassembleMenus(LPSERVERDOC lpServerDoc) { UINT uCount; UINT uGroup; UINT uDeleteAt; LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData; LONG FAR* lpWidths = lpIPData->menuGroupWidths.width; BOOL fNoError = TRUE; /* OLE2NOTE: even when hMenuShared is NULL (ie. the server has no ** Menu), there is still an hOleMenu created that must be destroyed. */ if (lpIPData->hOlemenu) { OleDestroyMenuDescriptor (lpIPData->hOlemenu); lpIPData->hOlemenu = NULL; } if (! lpIPData->hMenuShared) return; // no menus to be destroyed /* Remove server group menus. */ uDeleteAt = 0; for (uGroup = 0; uGroup < 6; uGroup++) { uDeleteAt += (UINT)lpWidths[uGroup++]; for (uCount = 0; uCount < (UINT)lpWidths[uGroup]; uCount++) fNoError &= RemoveMenu(lpIPData->hMenuShared, uDeleteAt, MF_BYPOSITION); } /* Remove container group menus */ fNoError &= (lpIPData->lpFrame->lpVtbl->RemoveMenus( lpIPData->lpFrame, lpIPData->hMenuShared) == NOERROR); OleDbgAssert(fNoError == TRUE); DestroyMenu(lpIPData->hMenuShared); lpIPData->hMenuShared = NULL; } /* ServerDoc_UpdateInPlaceWindowOnExtentChange ** ------------------------------------------- ** The size of the in-place window needs to be changed. ** calculate the size required in Client coordinates (taking into ** account the current scale factor imposed by the in-place ** container) and ask our in-place container to allow us to resize. ** our container must call us back via ** IOleInPlaceObject::SetObjectRects for the actual sizing to take ** place. ** ** OLE2NOTE: the rectangle that we ask for from our in-place ** container is always the rectangle required for the object display ** itself (in our case the size of the LineList contents). it does ** NOT include the space we require for object frame adornments. */ void ServerDoc_UpdateInPlaceWindowOnExtentChange(LPSERVERDOC lpServerDoc) { SIZEL sizelHim; SIZEL sizelPix; RECT rcPosRect; LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; LPLINELIST lpLL=(LPLINELIST)&lpOutlineDoc->m_LineList; HWND hWndLL = lpLL->m_hWndListBox; LPSCALEFACTOR lpscale = (LPSCALEFACTOR)&lpOutlineDoc->m_scale; if (!lpServerDoc->m_fInPlaceActive) return; OleDoc_GetExtent((LPOLEDOC)lpServerDoc, (LPSIZEL)&sizelHim); // apply current scale factor sizelHim.cx = sizelHim.cx * lpscale->dwSxN / lpscale->dwSxD; sizelHim.cy = sizelHim.cy * lpscale->dwSxN / lpscale->dwSxD; XformSizeInHimetricToPixels(NULL, (LPSIZEL)&sizelHim, (LPSIZEL)&sizelPix); GetWindowRect(hWndLL, (LPRECT)&rcPosRect); ScreenToClient(lpServerDoc->m_hWndParent, (POINT FAR *)&rcPosRect); rcPosRect.right = rcPosRect.left + (int) sizelPix.cx; rcPosRect.bottom = rcPosRect.top + (int) sizelPix.cy; OleDbgOutRect3("ServerDoc_UpdateInPlaceWindowOnExtentChange: (PosRect)", (LPRECT)&rcPosRect); OLEDBG_BEGIN2("IOleInPlaceSite::OnPosRectChange called\r\n"); lpServerDoc->m_lpIPData->lpSite->lpVtbl->OnPosRectChange( lpServerDoc->m_lpIPData->lpSite, (LPRECT) &rcPosRect ); OLEDBG_END2 } /* ServerDoc_CalcInPlaceWindowPos * ------------------------------ * * Move (and re-scale) the ServerDoc to the specified rectangle. * * Parameters: * lprcListBox - rect in client coordinate in which the listbox will fit * lprcDoc - corresponding size of the Doc in client coordinate * */ void ServerDoc_CalcInPlaceWindowPos( LPSERVERDOC lpServerDoc, LPRECT lprcListBox, LPRECT lprcDoc, LPSCALEFACTOR lpscale ) { SIZEL sizelHim; SIZEL sizelPix; LPLINELIST lpLL; LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; LPHEADING lphead; if (!lpServerDoc || !lprcListBox || !lprcDoc) return; lphead = (LPHEADING)&lpOutlineDoc->m_heading; lpLL = OutlineDoc_GetLineList(lpOutlineDoc); OleDoc_GetExtent((LPOLEDOC)lpServerDoc, (LPSIZEL)&sizelHim); XformSizeInHimetricToPixels(NULL, &sizelHim, &sizelPix); if (sizelHim.cx == 0 || sizelPix.cx == 0) { lpscale->dwSxN = 1; lpscale->dwSxD = 1; } else { lpscale->dwSxN = lprcListBox->right - lprcListBox->left; lpscale->dwSxD = sizelPix.cx; } if (sizelHim.cy == 0 || sizelPix.cy == 0) { lpscale->dwSyN = 1; lpscale->dwSyD = 1; } else { lpscale->dwSyN = lprcListBox->bottom - lprcListBox->top; lpscale->dwSyD = sizelPix.cy; } lprcDoc->left = lprcListBox->left - Heading_RH_GetWidth(lphead,lpscale); lprcDoc->right = lprcListBox->right; lprcDoc->top = lprcListBox->top - Heading_CH_GetHeight(lphead,lpscale); lprcDoc->bottom = lprcListBox->bottom; } /* ServerDoc_ResizeInPlaceWindow ** ----------------------------- ** Actually resize the in-place ServerDoc windows according to the ** PosRect and ClipRect allowed by our in-place container. ** ** OLE2NOTE: the PosRect rectangle that our in-place container tells ** us is always the rectangle required for the object display ** itself (in our case the size of the LineList contents). it does ** NOT include the space we require for object frame adornments. */ void ServerDoc_ResizeInPlaceWindow( LPSERVERDOC lpServerDoc, LPCRECT lprcPosRect, LPCRECT lprcClipRect ) { LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; LPLINELIST lpLL = (LPLINELIST)&lpOutlineDoc->m_LineList; SCALEFACTOR scale; RECT rcDoc; POINT ptOffset; /* OLE2NOTE: calculate the space needed for our object frame ** adornments. our in-place container tells us the size that our ** object should take in window client coordinates ** (lprcPosRect). the rectangle cooresponds to the size that our ** LineList ListBox should be. our Doc window must the correct ** amount larger to accomodate our row/column headings. ** then move all windows into position. */ ServerDoc_CalcInPlaceWindowPos( lpServerDoc, (LPRECT)lprcPosRect, (LPRECT)&rcDoc, (LPSCALEFACTOR)&scale ); /* OLE2NOTE: we need to honor the lprcClipRect specified by our ** in-place container. we must NOT draw outside of the ClipRect. ** in order to achieve this, we will size the hatch window to be ** exactly the size that should be visible (rcVisRect). the ** rcVisRect is defined as the intersection of the full size of ** the in-place server window and the lprcClipRect. ** the ClipRect could infact clip the HatchRect on the ** right/bottom and/or on the top/left. if it is clipped on the ** right/bottom then it is sufficient to simply resize the hatch ** window. but if the HatchRect is clipped on the top/left then ** we must "move" the ServerDoc window (child of HatchWindow) by ** the delta that was clipped. the window origin of the ** ServerDoc window will then have negative coordinates relative ** to its parent HatchWindow. */ SetHatchWindowSize( lpServerDoc->m_hWndHatch, (LPRECT)&rcDoc, (LPRECT)lprcClipRect, (LPPOINT)&ptOffset ); // shift Doc window to account for hatch frame being drawn OffsetRect((LPRECT)&rcDoc, ptOffset.x, ptOffset.y); // move/size/set scale factor of ServerDoc window. OutlineDoc_SetScaleFactor( lpOutlineDoc, (LPSCALEFACTOR)&scale, (LPRECT)&rcDoc); /* reset the horizontal extent of the listbox. this makes ** the listbox realize that a scroll bar is not needed. */ SendMessage( lpLL->m_hWndListBox, LB_SETHORIZONTALEXTENT, (int) 0, 0L ); SendMessage( lpLL->m_hWndListBox, LB_SETHORIZONTALEXTENT, (int) (lprcPosRect->right - lprcPosRect->left), 0L ); } /* ServerDoc_SetStatusText ** Tell the active in-place frame to display a status message. */ void ServerDoc_SetStatusText(LPSERVERDOC lpServerDoc, LPSTR lpszMessage) { if (lpServerDoc && lpServerDoc->m_fUIActive && lpServerDoc->m_lpIPData != NULL) { OLEDBG_BEGIN2("IOleInPlaceFrame::SetStatusText called\r\n") CallIOleInPlaceFrameSetStatusTextA (lpServerDoc->m_lpIPData->lpFrame, lpszMessage); OLEDBG_END2 } } /* ServerDoc_GetTopInPlaceFrame ** ---------------------------- ** returns NON-AddRef'ed pointer to Top In-Place Frame interface */ LPOLEINPLACEFRAME ServerDoc_GetTopInPlaceFrame(LPSERVERDOC lpServerDoc) { if (lpServerDoc->m_lpIPData) return lpServerDoc->m_lpIPData->lpFrame; else return NULL; } void ServerDoc_GetSharedMenuHandles( LPSERVERDOC lpServerDoc, HMENU FAR* lphSharedMenu, HOLEMENU FAR* lphOleMenu ) { if (lpServerDoc->m_lpIPData) { *lphSharedMenu = lpServerDoc->m_lpIPData->hMenuShared; *lphOleMenu = lpServerDoc->m_lpIPData->hOlemenu; } else { *lphSharedMenu = NULL; *lphOleMenu = NULL; } } void ServerDoc_AddFrameLevelUI(LPSERVERDOC lpServerDoc) { LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; LPOLEINPLACEFRAME lpTopIPFrame=ServerDoc_GetTopInPlaceFrame(lpServerDoc); HMENU hSharedMenu; // combined obj/cntr menu HOLEMENU hOleMenu; // returned by OleCreateMenuDesc. ServerDoc_GetSharedMenuHandles( lpServerDoc, &hSharedMenu, &hOleMenu ); lpTopIPFrame->lpVtbl->SetMenu( lpTopIPFrame, hSharedMenu, hOleMenu, lpOutlineDoc->m_hWndDoc ); // save normal accelerator table lpServerApp->m_hAccelBaseApp = lpOutlineApp->m_hAccelApp; // install accelerator table for UIActive server (w/ active editor cmds) lpOutlineApp->m_hAccel = lpServerApp->m_hAccelIPSvr; lpOutlineApp->m_hAccelApp = lpServerApp->m_hAccelIPSvr; lpOutlineApp->m_hWndAccelTarget = lpOutlineDoc->m_hWndDoc; #if defined( USE_FRAMETOOLS ) ServerDoc_AddFrameLevelTools(lpServerDoc); // update toolbar button enable states OutlineDoc_UpdateFrameToolButtons(lpOutlineDoc); #endif } void ServerDoc_AddFrameLevelTools(LPSERVERDOC lpServerDoc) { LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; LPOLEINPLACEFRAME lpTopIPFrame=ServerDoc_GetTopInPlaceFrame(lpServerDoc); #if defined( USE_FRAMETOOLS ) HWND hWndFrame; FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, TRUE); // if not in-place UI active, add our tools to our own frame. if (! lpServerDoc->m_fUIActive) { OutlineDoc_AddFrameLevelTools(lpOutlineDoc); return; } if ((hWndFrame = OutlineApp_GetFrameWindow(lpOutlineApp)) == NULL) { /* we could NOT get a valid frame window, so POP our tools up. */ /* OLE2NOTE: since we are poping up our tools, we MUST inform ** the top in-place frame window that we need NO tool space ** BUT that it should NOT put its own tools up. if we were ** to pass NULL instead of (0,0,0,0), then the container ** would have the option to leave its own tools up. */ lpTopIPFrame->lpVtbl->SetBorderSpace( lpTopIPFrame, (LPCBORDERWIDTHS)&g_rectNull ); FrameTools_PopupTools(lpOutlineDoc->m_lpFrameTools); } else { /* OLE2NOTE: we need to negotiate for space and attach our frame ** level tools to the top-level in-place container's frame window. */ FrameTools_AttachToFrame(lpOutlineDoc->m_lpFrameTools, hWndFrame); FrameTools_NegotiateForSpaceAndShow( lpOutlineDoc->m_lpFrameTools, NULL, lpTopIPFrame ); } #else // ! USE_FRAMETOOLS /* OLE2NOTE: if you do NOT use frame tools, you MUST inform the top ** in-place frame window so that it can put back its own tools. */ lpTopIPFrame->lpVtbl->SetBorderSpace(lpIPData->lpFrame, NULL); #endif // ! USE_FRAMETOOLS } #if defined( USE_FRAMETOOLS ) void ServerDoc_RemoveFrameLevelTools(LPSERVERDOC lpServerDoc) { LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; OleDbgAssert(lpOutlineDoc->m_lpFrameTools != NULL); // Reparent our tools back to one of our own windows FrameTools_AttachToFrame(lpOutlineDoc->m_lpFrameTools,g_lpApp->m_hWndApp); FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, FALSE); } #endif // USE_FRAMETOOLS void ServerDoc_UIActivate (LPSERVERDOC lpServerDoc) { if (lpServerDoc->m_fInPlaceActive && !lpServerDoc->m_fUIActive) { ServerDoc_DoInPlaceActivate(lpServerDoc, OLEIVERB_UIACTIVATE, NULL /*lpmsg*/, lpServerDoc->m_lpOleClientSite ); OutlineDoc_ShowWindow((LPOUTLINEDOC)lpServerDoc); } }