//=--------------------------------------------------------------------------=
// CDocObj.Cpp
//=--------------------------------------------------------------------------=
// Copyright 1995 - 1998 Microsoft Corporation. All Rights Reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//=--------------------------------------------------------------------------=
//
// implementation of CDocumentObject, which provides basic DocObject server
// support. This file contains overrides of basic inplace editing support.
// See iodoc.cpp and iodocvw.cpp for implementations of required interfaces
// for DocObject server support.
//
#include <IPServer.H>
#include <Globals.H>
#include "CDocObj.H"
// for ASSERT and FAIL
//
SZTHISFILE
//=--------------------------------------------------------------------------=
// CDocumentObject::CDocumentObject
//=--------------------------------------------------------------------------=
//
// Parameters:
// IUnknown* - [in]
// int - [in]
// void* - [in]
//
// Notes:
//
CDocumentObject::CDocumentObject(IUnknown* pUnkOuter, int iPrimaryDispatch,
void* pMainInterface)
: BASECLASS(pUnkOuter, iPrimaryDispatch, pMainInterface)
{
m_fDocObj = FALSE;
m_pDocSite = NULL;
m_pViewSite = NULL;
}
//=--------------------------------------------------------------------------=
// CDocumentObject::~CDocumentObject
//=--------------------------------------------------------------------------=
//
// Notes:
//
CDocumentObject::~CDocumentObject()
{
ASSERT(m_pDocSite == NULL, "CDocumentObject::m_pDocSite not properly released");
ASSERT(m_pViewSite == NULL, "CDocumentObject::m_pViewSite not properly released");
}
//=--------------------------------------------------------------------------=
// CDocumentObject::InternalQueryInterface
//=--------------------------------------------------------------------------=
// qi for things only we support.
//
// Parameters:
// Parameters:
// REFIID - [in] interface they want
// void** - [out] where they want to put the resulting object ptr.
//
// Output:
// HRESULT - S_OK, E_NOINTERFACE
//
// Notes:
//
HRESULT CDocumentObject::InternalQueryInterface(REFIID riid, void** ppvObjOut)
{
// Check for interfaces we implement
if (DO_GUIDS_MATCH(riid, IID_IOleDocument))
*ppvObjOut = (void *)(IOleDocument*)this;
else if (DO_GUIDS_MATCH(riid, IID_IOleDocumentView))
*ppvObjOut = (void *)(IOleDocumentView*)this;
else
// delegate to super-class for automation interfaces, etc ...
//
return BASECLASS::InternalQueryInterface(riid, ppvObjOut);
// we like the interface, so addref and return
//
((IUnknown *)(*ppvObjOut))->AddRef();
return S_OK;
}
//=--------------------------------------------------------------------------=
// CDocumentObject::SetClientSite
//=--------------------------------------------------------------------------=
// determines whether object can and should activate as a DocObject
//
// Parameters:
// IOleClientSite* - [in] pointer to client site.
//
// Output:
// HRESULT - S_OK
//
// Notes:
//
HRESULT CDocumentObject::SetClientSite(IOleClientSite* pClientSite)
{
TRACE("\nCDocumentObject::SetClientSite");
// perform regular SetClientSite processing
HRESULT hr = BASECLASS::SetClientSite(pClientSite);
if (FAILED(hr))
return hr;
// If we have a document site pointer,
// release it and set docobj flag FALSE
RELEASE_OBJECT(m_pDocSite);
m_fDocObj = FALSE;
// If we got a client site,
if (pClientSite != NULL)
{
// If the client site supports IID_IOleDocumentSite,
// save the document site pointer
// and set docobj flag TRUE
hr = pClientSite->QueryInterface(IID_IOleDocumentSite,
(void**)&m_pDocSite);
if (SUCCEEDED(hr))
m_fDocObj = TRUE;
}
return S_OK;
}
//=--------------------------------------------------------------------------=
// CDocumentObject::DoVerb [IOleObject]
//=--------------------------------------------------------------------------=
// Requests an object to perform an action in response to an end-user's
// action.
//
// Parameters:
// LONG - [in] verb to be performed
// LPMSG - [in] event that invoked the verb
// IOleClientSite * - [in] the controls active client site
// LONG - [in] reserved
// HWND - [in] handle of window containing the object.
// LPCRECT - [in] pointer to objects's display rectangle
//
// Output:
// HRESULT - S_OK, OLE_E_NOTINPLACEACTIVE, OLE_E_CANT_BINDTOSOURCE,
// DV_E_LINK, OLEOBJ_S_CANNOT_DOVERB_NOW, OLEOBJ_S_INVALIDHWND,
// OLEOBJ_E_NOVERBS, OLEOBJ_S_INVALIDVERB, MK_E_CONNECT,
// OLE_CLASSDIFF, E_NOTIMPL
//
// Notes:
//
STDMETHODIMP CDocumentObject::DoVerb
(
LONG lVerb,
LPMSG pMsg,
IOleClientSite *pActiveSite,
LONG lIndex,
HWND hwndParent,
LPCRECT prcPosRect
)
{
TRACE("\nCDocumentObject::DoVerb");
// if we're acting as a docobj
if (m_fDocObj)
{
switch (lVerb)
{
// call IOleDocumentSite::ActivateMe for Show, Open, InPlaceActivate and UIActivate Verbs
case OLEIVERB_SHOW:
case OLEIVERB_UIACTIVATE:
case OLEIVERB_OPEN:
case OLEIVERB_INPLACEACTIVATE:
return m_pDocSite->ActivateMe(NULL);
// return E_INVALIDARG for Hide Verb
case OLEIVERB_HIDE:
return E_INVALIDARG;
// otherwise, just do normal processing
default:
break;
}
}
// if we're not acting as a docobj, just do normal processing
return BASECLASS::DoVerb(lVerb, pMsg, pActiveSite, lIndex,
hwndParent, prcPosRect);
}
//=--------------------------------------------------------------------------=
// CDocumentObject::SetExtent [IOleObject]
//=--------------------------------------------------------------------------=
// Informs the control of how much display space its container has assigned it.
//
// Parameters:
// DWORD - [in] which form or 'aspect' is to be displayed.
// SIZEL * - [in] size limit for the control.
//
// Output:
// HRESULT - S_OK, E_FAIL, OLE_E_NOTRUNNING
//
// Notes:
//
STDMETHODIMP CDocumentObject::SetExtent(DWORD dwDrawAspect, SIZEL *psizel)
{
TRACE("\nCDocumentObject::SetExtent");
// ignore SetExtent calls if we are a docobj
if (m_fDocObj)
return S_OK;
// otherwise do normal processing
return BASECLASS::SetExtent(dwDrawAspect, psizel);
}
//=--------------------------------------------------------------------------=
// CDocumentObject::Unadvise [IOleObject]
//=--------------------------------------------------------------------------=
// Deletes a previously established advisory connection.
//
// Parameters:
// DWORD - [in] connection cookie
//
// Output:
// HRESULT - S_OK, E_FAIL, OLE_E_NOCONNECTION
//
// Notes:
// This override is included to work around a problem observed
// interacting with Office Binder. When activated as a docobj,
// IOleObject::Advise is not getting called. However, when deactivated,
// IOleObject::Unadvise *is* called. Since no advise holder was ever
// created, the base class method asserts.
//
// All this function does is prevent the assert from getting hit.
//
STDMETHODIMP CDocumentObject::Unadvise(DWORD dwConnection)
{
if (!dwConnection) {
TRACE("\nSomebody called Unadvise on IOleObject without calling Advise!");
return OLE_E_NOCONNECTION;
}
return BASECLASS::Unadvise(dwConnection);
}
//=--------------------------------------------------------------------------=
// CDocumentObject::ActivateAsDocObject
//=--------------------------------------------------------------------------=
// activates a document object, and depending on the verb, optionally
// ui activates it as well.
//
// Parameters:
// LONG - [in] the verb that caused us to activate
//
// Output:
// HRESULT - S_OK, E_UNEXPECTED
//
// Notes:
// This implementation is based on COleControl::InPlaceActivate.
// COleControl::InPlaceActivate is called when a CDocumentObject
// is being used as a control or normal embedding, not this function.
//
HRESULT CDocumentObject::ActivateAsDocObject(LONG lVerb)
{
TRACE("\nEntering CDocumentObject::ActivateAsDocObject");
HRESULT hr = S_OK;
// if our view site has not been set, report an error
if (!m_pViewSite)
{
hr = E_UNEXPECTED;
goto LeaveMethod;
}
// if we don't have a client site, then there's not much to do.
//
if (!m_pClientSite)
goto LeaveMethod;
// get an InPlaceSite pointer
//
if (!m_pInPlaceSite) {
hr = m_pClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_pInPlaceSite);
if (FAILED(hr))
goto LeaveMethod;
}
// if we're not already active, go and do it.
//
if (!m_fInPlaceActive) {
OLEINPLACEFRAMEINFO InPlaceFrameInfo;
RECT rcPos, rcClip;
// ask for permission and notify the container we're going active.
//
hr = m_pInPlaceSite->CanInPlaceActivate();
if (hr != S_OK)
{
if (FAILED(hr))
hr = E_FAIL;
goto LeaveMethod;
}
hr = m_pInPlaceSite->OnInPlaceActivate();
if (FAILED(hr))
goto LeaveMethod;
m_fInPlaceActive = TRUE;
InPlaceFrameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
// get our parent window
//
hr = m_pInPlaceSite->GetWindow(&m_hwndParent);
if (!FAILED(hr))
// get our display and clipping rectangles
//
hr = m_pInPlaceSite->GetWindowContext(&m_pInPlaceFrame, &m_pInPlaceUIWindow,
&rcPos, &rcClip, &InPlaceFrameInfo);
if (FAILED(hr)) {
InPlaceDeactivate();
goto LeaveMethod;
}
// make sure we'll display ourselves in the correct location with the correct size
// SetObjectRects expects object extent to be set, but
// DocObjects ignore SetExtent. Set m_Size to the size
// specified for the view.
m_Size.cx = rcPos.right - rcPos.left;
m_Size.cy = rcPos.bottom - rcPos.top;
SetObjectRects(&rcPos, &rcClip);
// create the window, and display it.
//
CreateInPlaceWindow(rcPos.left, rcPos.top, TRUE);
}
if (!m_fInPlaceVisible)
SetInPlaceVisible(TRUE);
// if we weren't asked to UIActivate, then we're done.
//
if (lVerb != OLEIVERB_PRIMARY && lVerb != OLEIVERB_UIACTIVATE)
goto LeaveMethod;
// if we're not already UI active, do sow now.
//
if (!m_fUIActive) {
m_fUIActive = TRUE;
// inform the container of our intent
//
m_pInPlaceSite->OnUIActivate();
// take the focus [which is what UI Activation is all about !]
//
SetFocus(TRUE);
// set up the active object [us] with the container.
//
m_pInPlaceFrame->SetActiveObject((IOleInPlaceActiveObject *)this, NULL);
if (m_pInPlaceUIWindow)
m_pInPlaceUIWindow->SetActiveObject((IOleInPlaceActiveObject *)this, NULL);
// we have to explicitly say we don't wany any border space.
//
m_pInPlaceFrame->SetBorderSpace(NULL);
if (m_pInPlaceUIWindow)
m_pInPlaceUIWindow->SetBorderSpace(NULL);
}
LeaveMethod:
TRACE("\nLeaving CDocumentObject::ActivateAsDocObject");
return hr;
}