IIPSITE.CPP

/* 
* IIPSITE.CPP
* Patron Chapter 24
*
* IOleInPlaceSite interface implementation for Patron
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/


#include "patron.h"


BOOL g_fSwitchingActive=FALSE;

/*
* CImpIOleInPlaceSite::CImpIOleInPlaceSite
* CImpIOleInPlaceSite::~CImpIOleInPlaceSite
*
* Parameters (Constructor):
* pTen PCTenant of the tenant we're in.
* pUnkOuter LPUNKNOWN to which we delegate.
*/

CImpIOleInPlaceSite::CImpIOleInPlaceSite(PCTenant pTen
, LPUNKNOWN pUnkOuter)
{
m_cRef=0;
m_pTen=pTen;
m_pUnkOuter=pUnkOuter;
return;
}

CImpIOleInPlaceSite::~CImpIOleInPlaceSite(void)
{
return;
}



/*
* CImpIOleInPlaceSite::QueryInterface
* CImpIOleInPlaceSite::AddRef
* CImpIOleInPlaceSite::Release
*
* Purpose:
* IUnknown members for CImpIOleInPlaceSite object.
*/

STDMETHODIMP CImpIOleInPlaceSite::QueryInterface(REFIID riid
, PPVOID ppv)
{
return m_pUnkOuter->QueryInterface(riid, ppv);
}


STDMETHODIMP_(ULONG) CImpIOleInPlaceSite::AddRef(void)
{
++m_cRef;
return m_pUnkOuter->AddRef();
}

STDMETHODIMP_(ULONG) CImpIOleInPlaceSite::Release(void)
{
--m_cRef;
return m_pUnkOuter->Release();
}




/*
* CImpIOleInPlaceActiveObject::GetWindow
*
* Purpose:
* Retrieves the handle of the window associated with the object
* on which this interface is implemented.
*
* Parameters:
* phWnd HWND * in which to store the window handle.
*
* Return Value:
* HRESULT NOERROR if successful, E_FAIL if there is no
* window.
*/

STDMETHODIMP CImpIOleInPlaceSite::GetWindow(HWND *phWnd)
{
*phWnd=m_pTen->m_hWnd;
return NOERROR;
}




/*
* CImpIOleInPlaceActiveObject::ContextSensitiveHelp
*
* Purpose:
* Instructs the object on which this interface is implemented to
* enter or leave a context-sensitive help mode.
*
* Parameters:
* fEnterMode BOOL TRUE to enter the mode, FALSE otherwise.
*
* Return Value:
* HRESULT NOERROR
*/

STDMETHODIMP CImpIOleInPlaceSite::ContextSensitiveHelp
(BOOL fEnterMode)
{
return NOERROR;
}




/*
* CImpIOleInPlaceSite::CanInPlaceActivate
*
* Purpose:
* Answers the server whether or not we can currently in-place
* activate its object. By implementing this interface we say
* that we support in-place activation, but through this function
* we indicate whether the object can currently be activated
* in-place. Iconic aspects, for example, cannot, meaning we
* return S_FALSE.
*
* Parameters:
* None
*
* Return Value:
* HRESULT NOERROR if we can in-place activate the object
* in this site, S_FALSE if not.
*/

STDMETHODIMP CImpIOleInPlaceSite::CanInPlaceActivate(void)
{
if (DVASPECT_CONTENT!=m_pTen->m_fe.dwAspect)
return ResultFromScode(S_FALSE);

if (TENANTTYPE_EMBEDDEDOBJECT!=m_pTen->m_tType)
return ResultFromScode(S_FALSE);

//CHAPTER24MOD
if (m_pTen->m_pPG->m_fDesignMode)
return ResultFromScode(S_FALSE);
//End CHAPTER24MOD

return NOERROR;
}




/*
* CImpIOleInPlaceSite::OnInPlaceActivate
*
* Purpose:
* Informs the container that an object is being activated in-place
* such that the container can prepare appropriately. The
* container does not, however, make any user interface changes at
* this point. See OnUIActivate.
*
* Parameters:
* None
*
* Return Value:
* HRESULT NOERROR or an appropriate error code.
*/

STDMETHODIMP CImpIOleInPlaceSite::OnInPlaceActivate(void)
{
//CHAPTER24MOD
m_pTen->m_fPendingDeactivate=FALSE;
//End CHAPTER24MOD

//m_pIOleIPObject is our in-place flag.
m_pTen->m_pObj->QueryInterface(IID_IOleInPlaceObject
, (PPVOID)&m_pTen->m_pIOleIPObject);

return NOERROR;
}




/*
* CImpIOleInPlaceSite::OnInPlaceDeactivate
*
* Purpose:
* Notifies the container that the object has deactivated itself
* from an in-place state. Opposite of OnInPlaceActivate. The
* container does not change any UI at this point.
*
* Parameters:
* None
*
* Return Value:
* HRESULT NOERROR or an appropriate error code.
*/

STDMETHODIMP CImpIOleInPlaceSite::OnInPlaceDeactivate(void)
{
/*
* Since we don't have an Undo command, we can tell the object
* right away to discard its Undo state.
*/
m_pTen->Activate(OLEIVERB_DISCARDUNDOSTATE, NULL);
ReleaseInterface(m_pTen->m_pIOleIPObject);
return NOERROR;
}




/*
* CImpIOleInPlaceSite::OnUIActivate
*
* Purpose:
* Informs the container that the object is going to start munging
* around with user interface, like replacing the menu. The
* container should remove any relevant UI in preparation.
*
* Parameters:
* None
*
* Return Value:
* HRESULT NOERROR or an appropriate error code.
*/

STDMETHODIMP CImpIOleInPlaceSite::OnUIActivate(void)
{
PCPatronDoc pDoc;

m_pTen->m_pPG->m_fAddUI=FALSE;

//CHAPTER24MOD
m_pTen->m_fPendingDeactivate=FALSE;
//End CHAPTER24MOD

pDoc=(PCPatronDoc)SendMessage(GetParent(m_pTen->m_hWnd)
, DOCM_PDOCUMENT, 0, 0L);

/*
* Change the currently selected tenant in the page. This
* will UIDeactivate the currently UI Active tenant.
*/
g_fSwitchingActive=TRUE;
m_pTen->m_pPG->m_pPageCur->SwitchActiveTenant(m_pTen);
g_fSwitchingActive=FALSE;

//Hide the frame tools if necessary.
g_pFR->ShowUIAndTools(pDoc->NoObjectFrameTools(0, FALSE), FALSE);
return NOERROR;
}




/*
* CImpIOleInPlaceSite::OnUIDeactivate
*
* Purpose:
* Informs the container that the object is deactivating its
* in-place user interface at which time the container may
* reinstate its own. Opposite of OnUIActivate.
*
* Parameters:
* fUndoable BOOL indicating if the object will actually
* perform an Undo if the container calls
* ReactivateAndUndo.
*
* Return Value:
* HRESULT NOERROR or an appropriate error code.
*/

STDMETHODIMP CImpIOleInPlaceSite::OnUIDeactivate(BOOL fUndoable)
{
PCDocument pDoc;
MSG msg;

/*
* Ignore this notification if we're switching between
* multiple active objects.
*/
if (g_fSwitchingActive)
return NOERROR;

//If in shutdown (NULL storage), don't check messages.
if (NULL==m_pTen->m_pIStorage)
{
g_pFR->ReinstateUI();
return NOERROR;
}

pDoc=(PCDocument)SendMessage(GetParent(m_pTen->m_hWnd)
, DOCM_PDOCUMENT, 0, 0L);

//If there's a pending double-click, delay showing our UI
if (!PeekMessage(&msg, pDoc->Window(), WM_LBUTTONDBLCLK
, WM_LBUTTONDBLCLK, PM_NOREMOVE | PM_NOYIELD))
{
//Turn everything back on.
g_pFR->ReinstateUI();
}
else
m_pTen->m_pPG->m_fAddUI=TRUE;

SetFocus(pDoc->Window());
return NOERROR;
}




/*
* CImpIOleInPlaceSite::DeactivateAndUndo
*
* Purpose:
* If immediately after activation the object does an Undo, the
* action being undone is the activation itself, and this call
* informs the container that this is, in fact, what happened.
* The container should call IOleInPlaceObject::UIDeactivate.
*
* Parameters:
* None
*
* Return Value:
* HRESULT NOERROR or an appropriate error code.
*/

STDMETHODIMP CImpIOleInPlaceSite::DeactivateAndUndo(void)
{
//CHAPTER24MOD
/*
* Note that we don't pay attention to the locking
* from IOleControlSite::LockInPlaceActive since only
* the object calls this function and should know
* that it's going to be deactivated.
*/
//End CHAPTER24MOD

m_pTen->m_pIOleIPObject->InPlaceDeactivate();
return NOERROR;
}




/*
* CImpIOleInPlaceSite::DiscardUndoState
*
* Purpose:
* Informs the container that something happened in the object
* that means the container should discard any undo information
* it currently maintains for the object.
*
* Parameters:
* None
*
* Return Value:
* HRESULT NOERROR or an appropriate error code.
*/

STDMETHODIMP CImpIOleInPlaceSite::DiscardUndoState(void)
{
return ResultFromScode(E_NOTIMPL);
}




/*
* CImpIOleInPlaceSite::GetWindowContext
*
* Purpose:
* Provides an in-place object with pointers to the frame and
* document level in-place interfaces (IOleInPlaceFrame and
* IOleInPlaceUIWindow) such that the object can do border
* negotiation and so forth. Also requests the position and
* clipping rectangles of the object in the container and a
* pointer to an OLEINPLACEFRAME info structure which contains
* accelerator information.
*
* Note that the two interfaces this call returns are not
* available through QueryInterface on IOleInPlaceSite since they
* live with the frame and document, but not the site.
*
* Parameters:
* ppIIPFrame LPOLEINPLACEFRAME * in which to return the
* AddRef'd pointer to the container's
* IOleInPlaceFrame.
* ppIIPUIWindow LPOLEINPLACEUIWINDOW * in which to return
* the AddRef'd pointer to the container document's
* IOleInPlaceUIWindow.
* prcPos LPRECT in which to store the object's position.
* prcClip LPRECT in which to store the object's visible
* region.
* pFI LPOLEINPLACEFRAMEINFO to fill with accelerator
* stuff.
*
* Return Value:
* HRESULT NOERROR
*/

STDMETHODIMP CImpIOleInPlaceSite::GetWindowContext
(LPOLEINPLACEFRAME *ppIIPFrame, LPOLEINPLACEUIWINDOW
*ppIIPUIWindow, LPRECT prcPos, LPRECT prcClip
, LPOLEINPLACEFRAMEINFO pFI)
{
PCPatronDoc pDoc;
RECTL rcl;

*ppIIPUIWindow=NULL;

*ppIIPFrame=(LPOLEINPLACEFRAME)g_pFR;
g_pFR->AddRef();

pDoc=(PCPatronDoc)SendMessage(GetParent(m_pTen->m_hWnd)
, DOCM_PDOCUMENT, 0, 0L);

if (NULL!=pDoc)
{
pDoc->QueryInterface(IID_IOleInPlaceUIWindow
, (PPVOID)ppIIPUIWindow);
}

//Now get the rectangles and frame information.
m_pTen->RectGet(&rcl, TRUE);
RECTFROMRECTL(*prcPos, rcl);

//Include scroll position here.
OffsetRect(prcPos, -(int)m_pTen->m_pPG->m_xPos
, -(int)m_pTen->m_pPG->m_yPos);

SetRect(prcClip, 0, 0, 32767, 32767);

pFI->cb=sizeof(OLEINPLACEFRAMEINFO);
#ifdef MDI
pFI->fMDIApp=TRUE;
#else
pFI->fMDIApp=FALSE;
#endif

pFI->hwndFrame=g_pFR->Window();

pFI->haccel=g_pFR->m_hAccelIP;
pFI->cAccelEntries=CINPLACEACCELERATORS;

return NOERROR;
}




/*
* CImpIOleInPlaceSite::Scroll
*
* Purpose:
* Asks the container to scroll the document, and thus the object,
* by the given amounts in the sz parameter.
*
* Parameters:
* sz SIZE containing signed horizontal and vertical
* extents by which the container should scroll.
* These are in device units.
*
* Return Value:
* HRESULT NOERROR
*/

STDMETHODIMP CImpIOleInPlaceSite::Scroll(SIZE sz)
{
int x, y;

x=m_pTen->m_pPG->m_xPos+sz.cx;
y=m_pTen->m_pPG->m_yPos+sz.cy;

SendScrollPosition(m_pTen->m_hWnd, WM_HSCROLL, x);
SendScrollPosition(m_pTen->m_hWnd, WM_VSCROLL, y);
return NOERROR;
}




/*
* CImpIOleInPlaceSite::OnPosRectChange
*
* Purpose:
* Informs the container that the in-place object was resized.
* The container must call IOleInPlaceObject::SetObjectRects.
* This does not change the site's rectangle in any case.
*
* Parameters:
* prcPos LPCRECT containing the new size of the object.
*
* Return Value:
* HRESULT NOERROR
*/

STDMETHODIMP CImpIOleInPlaceSite::OnPosRectChange(LPCRECT prcPos)
{
if (NULL!=prcPos)
m_pTen->m_rcPos=*prcPos;

m_pTen->UpdateInPlaceObjectRects(prcPos, FALSE);
return NOERROR;
}