1452 lines
41 KiB
C
1452 lines
41 KiB
C
/*************************************************************************
|
|
**
|
|
** 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:
|
|
** <application name> - <object short type name>
|
|
** SDI containers can use the string directly to display in the
|
|
** frame window title. the container would concatenate the string
|
|
** " in <container doc name>".
|
|
** 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 <container doc name>" 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);
|
|
}
|
|
}
|