1126 lines
25 KiB
C++
1126 lines
25 KiB
C++
|
// tOleHandler.cpp: implementation of the tOleHandler class.
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#include <ole2.h>
|
||
|
#include <assert.h>
|
||
|
|
||
|
#ifndef _OLE2_H_
|
||
|
#define _OLE2_H_
|
||
|
#endif
|
||
|
|
||
|
#include "tOleHandler.h"
|
||
|
#include "tDispatch.h"
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::tOleHandler
|
||
|
* tOleHandler::~tOleHandler
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
tOleHandler::tOleHandler()
|
||
|
{
|
||
|
natural_width = 0;
|
||
|
natural_height = 0;
|
||
|
|
||
|
m_hWnd=NULL;
|
||
|
m_pIStorage=NULL;
|
||
|
|
||
|
m_fInitialized=0;
|
||
|
m_cOpens=0;
|
||
|
|
||
|
m_pObj=NULL;
|
||
|
m_clsID=CLSID_NULL;
|
||
|
m_fSetExtent=FALSE;
|
||
|
|
||
|
m_cRef=0;
|
||
|
m_pIOleObject=NULL;
|
||
|
m_pIViewObject2=NULL;
|
||
|
m_grfMisc=0;
|
||
|
|
||
|
m_rcl.right = m_rcl.left = 0;
|
||
|
m_rcl.top = m_rcl.bottom = 0;
|
||
|
|
||
|
m_pImpIOleClientSite=NULL;
|
||
|
|
||
|
m_fRepaintEnabled=TRUE;
|
||
|
|
||
|
|
||
|
m_pImpIOleIPSite=NULL;
|
||
|
m_pIOleIPObject=NULL;
|
||
|
m_rcPos.left=-1;
|
||
|
m_fInRectSet=FALSE;
|
||
|
|
||
|
//CHAPTER24MOD
|
||
|
m_pImpIOleControlSite=NULL;
|
||
|
m_pImpIDispatch=NULL;
|
||
|
|
||
|
m_pIOleControl=NULL;
|
||
|
|
||
|
m_fHaveControlInfo=FALSE;
|
||
|
m_cLockInPlace=0;
|
||
|
m_fPendingDeactivate=FALSE;
|
||
|
//End CHAPTER24MOD
|
||
|
}
|
||
|
|
||
|
|
||
|
tOleHandler::~tOleHandler(void)
|
||
|
{
|
||
|
|
||
|
//Object pointers cleaned up in Close.
|
||
|
|
||
|
//CHAPTER24MOD
|
||
|
|
||
|
DeleteInterfaceImp(m_pImpIOleControlSite);
|
||
|
DeleteInterfaceImp(m_pImpIDispatch);
|
||
|
|
||
|
//End CHAPTER24MOD
|
||
|
|
||
|
DeleteInterfaceImp(m_pImpIOleIPSite);
|
||
|
DeleteInterfaceImp(m_pImpIOleClientSite);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::QueryInterface
|
||
|
* tOleHandler::AddRef
|
||
|
* tOleHandler::Release
|
||
|
*
|
||
|
* Purpose:
|
||
|
* IUnknown members for tOleHandler object.
|
||
|
*/
|
||
|
|
||
|
STDMETHODIMP tOleHandler::QueryInterface(REFIID riid, LPVOID *ppv)
|
||
|
{
|
||
|
*ppv=NULL;
|
||
|
|
||
|
if (IID_IUnknown==riid)
|
||
|
*ppv=this;
|
||
|
|
||
|
if (IID_IOleClientSite==riid)
|
||
|
*ppv=m_pImpIOleClientSite;
|
||
|
|
||
|
if (IID_IOleWindow==riid || IID_IOleInPlaceSite==riid)
|
||
|
*ppv=m_pImpIOleIPSite;
|
||
|
|
||
|
//CHAPTER24MOD
|
||
|
if (IID_IOleControlSite==riid)
|
||
|
*ppv=m_pImpIOleControlSite;
|
||
|
|
||
|
//Queries for IDispatch return the ambient properties interface
|
||
|
if (IID_IDispatch==riid)
|
||
|
*ppv=m_pImpIDispatch;
|
||
|
//End CHAPTER24MOD
|
||
|
|
||
|
if (NULL!=*ppv)
|
||
|
{
|
||
|
((LPUNKNOWN)*ppv)->AddRef();
|
||
|
return NOERROR;
|
||
|
}
|
||
|
|
||
|
return ResultFromScode(E_NOINTERFACE);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP_(ULONG) tOleHandler::AddRef(void)
|
||
|
{
|
||
|
return ++m_cRef;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) tOleHandler::Release(void)
|
||
|
{
|
||
|
if (0!=--m_cRef)
|
||
|
return m_cRef;
|
||
|
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::Create
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Creates a new tenant of the given CLSID, which can be either a
|
||
|
* static bitmap or metafile or any compound document object.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* tType TENANTTYPE to create, either a static metafile,
|
||
|
* bitmap, or some kind of compound document object
|
||
|
* This determines which OleCreate* call we use.
|
||
|
* pvType LPVOID providing the relevant pointer from which
|
||
|
* to create the tenant, depending on iType.
|
||
|
* pFE LPFORMATETC specifying the type of renderings
|
||
|
* to use.
|
||
|
* pptl PPOINTL in which we store offset coordinates.
|
||
|
* pszl LPSIZEL where this object should store its
|
||
|
* lometric extents.
|
||
|
* pIStorage LPSTORAGE of the page we live in. We have to
|
||
|
* create another storage in this for the tenant.
|
||
|
* ppo PPATRONOBJECT containing placement data.
|
||
|
* dwData DWORD with extra data, sensitive to iType.
|
||
|
*
|
||
|
* Return Value:
|
||
|
* UINT A CREATE_* value depending on what we
|
||
|
* actually do.
|
||
|
*/
|
||
|
|
||
|
UINT tOleHandler::Create(LPVOID pvType)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
LPUNKNOWN pObj;
|
||
|
UINT uRet=CREATE_GRAPHICONLY;
|
||
|
DWORD dwMode=STGM_READWRITE
|
||
|
| STGM_SHARE_EXCLUSIVE
|
||
|
| STGM_DELETEONRELEASE;
|
||
|
|
||
|
|
||
|
IPersistStorage *persist_storage = NULL;
|
||
|
|
||
|
StgCreateDocfile(NULL, dwMode, 0, &m_pIStorage);
|
||
|
|
||
|
if(m_pIStorage == NULL)
|
||
|
return CREATE_FAILED;
|
||
|
|
||
|
if (NULL==pvType)
|
||
|
return CREATE_FAILED;
|
||
|
|
||
|
hr=ResultFromScode(E_FAIL);
|
||
|
|
||
|
Open(NULL);
|
||
|
|
||
|
//CHAPTER24MOD
|
||
|
/*
|
||
|
* The OLE Control specifications mention that a
|
||
|
* a control might implement IPersistStream[Init]
|
||
|
* instead of IPersistStorage. In that case you
|
||
|
* cannot use OleCreate on a control but must rather
|
||
|
* use CoCreateInstance since OleCreate assumes
|
||
|
* that IPersistStorage is available. With a control,
|
||
|
* you would have to create the object first, then
|
||
|
* check if OLEMISC_SETCLIENTSITEFIRST is set, then
|
||
|
* send it your IOleClientSite first. Then you check
|
||
|
* for IPersistStorage and failing that, try
|
||
|
* IPersistStream[Init].
|
||
|
*
|
||
|
* For simplicity we'll assume storage-based
|
||
|
* controls in this sample.
|
||
|
*/
|
||
|
//End CHAPTER24MOD
|
||
|
|
||
|
hr = CoCreateInstance(*((LPCLSID)pvType), NULL,
|
||
|
CLSCTX_ALL, IID_IUnknown, (LPVOID *)&pObj);
|
||
|
|
||
|
if(FAILED(hr))
|
||
|
return CREATE_FAILED;
|
||
|
|
||
|
if(pObj->QueryInterface(IID_IPersistStorage, (void **) &persist_storage) != S_OK)
|
||
|
return CREATE_FAILED;
|
||
|
|
||
|
//We need an IOleObject most of the time, so get one here.
|
||
|
m_pIOleObject=NULL;
|
||
|
hr = pObj->QueryInterface(IID_IOleObject, (LPVOID*)&m_pIOleObject);
|
||
|
|
||
|
if(FAILED(hr))
|
||
|
return CREATE_FAILED;
|
||
|
|
||
|
// seta o client site
|
||
|
m_pIOleObject->SetClientSite(m_pImpIOleClientSite);
|
||
|
|
||
|
// inicializa o objeto
|
||
|
hr = persist_storage->InitNew(m_pIStorage);
|
||
|
|
||
|
if(FAILED(hr))
|
||
|
return CREATE_FAILED;
|
||
|
|
||
|
|
||
|
//We don't get the size if PatronObject data was seen already.
|
||
|
if (!ObjectInitialize(pObj))
|
||
|
{
|
||
|
return CREATE_FAILED;
|
||
|
}
|
||
|
|
||
|
SIZEL szl;
|
||
|
|
||
|
hr=ResultFromScode(E_FAIL);
|
||
|
|
||
|
CalcNaturalSize();
|
||
|
|
||
|
//CHAPTER24MOD
|
||
|
//Make sure this happens
|
||
|
/*if ((OLEMISC_ACTIVATEWHENVISIBLE & m_grfMisc))
|
||
|
Activate(OLEIVERB_INPLACEACTIVATE, NULL);*/
|
||
|
//End CHAPTER24MOD
|
||
|
|
||
|
return uRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::ObjectInitialize
|
||
|
* (Protected)
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Performs operations necessary after creating an object or
|
||
|
* reloading one from storage.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* pObj LPUNKNOWN of the object in this tenant.
|
||
|
* pFE LPFORMATETC describing the graphic here.
|
||
|
* dwData DWORD extra data. If pFE->dwAspect==
|
||
|
* DVASPECT_ICON then this is the iconic metafile.
|
||
|
*
|
||
|
* Return Value:
|
||
|
* BOOL TRUE if the function succeeded, FALSE otherwise.
|
||
|
*/
|
||
|
|
||
|
BOOL tOleHandler::ObjectInitialize(LPUNKNOWN pObj)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
FORMATETC fe;
|
||
|
|
||
|
SETDefFormatEtc(fe, 0, TYMED_NULL);
|
||
|
LPFORMATETC pFE = &fe;
|
||
|
|
||
|
|
||
|
if (NULL==pObj || NULL==pFE)
|
||
|
return FALSE;
|
||
|
|
||
|
m_pObj=pObj;
|
||
|
m_fe=*pFE;
|
||
|
m_fe.ptd=NULL;
|
||
|
m_dwState=TENANTSTATE_DEFAULT;
|
||
|
|
||
|
m_pIViewObject2=NULL;
|
||
|
hr=pObj->QueryInterface(IID_IViewObject2
|
||
|
, (LPVOID*)&m_pIViewObject2);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
return FALSE;
|
||
|
|
||
|
/*
|
||
|
* Get the MiscStatus bits and check for OLEMISC_ONLYICONIC.
|
||
|
* If set, force dwAspect in m_fe to DVASPECT_ICON so we
|
||
|
* remember to draw it properly and do extents right.
|
||
|
*/
|
||
|
m_pIOleObject->GetMiscStatus(m_fe.dwAspect, &m_grfMisc);
|
||
|
|
||
|
|
||
|
//CHAPTER24MOD
|
||
|
//Run the object if it says to do so
|
||
|
if (OLEMISC_ALWAYSRUN & m_grfMisc)
|
||
|
OleRun(pObj);
|
||
|
//End CHAPTER24MOD
|
||
|
|
||
|
|
||
|
|
||
|
//CHAPTER24MOD
|
||
|
//Go try initializing control-related things.
|
||
|
ControlInitialize();
|
||
|
//End CHAPTER24MOD
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::Open
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Retrieves the IStorage associated with this tenant. The
|
||
|
* IStorage is owned by the tenant and thus the tenant always
|
||
|
* holds a reference count.
|
||
|
*
|
||
|
* If the storage is already open for this tenant, then this
|
||
|
* function will AddRef it; therefore the caller must always
|
||
|
* match an Open with a Close.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* pIStorage LPSTORAGE above this tenant (which has its
|
||
|
* own storage).
|
||
|
*
|
||
|
* Return Value:
|
||
|
* BOOL TRUE if opening succeeds, FALSE otherwise.
|
||
|
*/
|
||
|
|
||
|
BOOL tOleHandler::Open(LPSTORAGE pIStorage)
|
||
|
{
|
||
|
HRESULT hr=NOERROR;
|
||
|
DWORD dwMode=STGM_TRANSACTED | STGM_READWRITE
|
||
|
| STGM_SHARE_EXCLUSIVE;
|
||
|
|
||
|
|
||
|
//Create these if we don't have them already.
|
||
|
if (NULL==m_pImpIOleClientSite)
|
||
|
{
|
||
|
m_pImpIOleClientSite=new tOleClientSite(this, this);
|
||
|
m_pImpIOleIPSite=new tOleInPlaceSite(this, this);
|
||
|
|
||
|
//CHAPTER24MOD
|
||
|
m_pImpIOleControlSite=new tOleControlSite(this, this);
|
||
|
m_pImpIDispatch=new tDispatch(this, this);
|
||
|
|
||
|
if (NULL==m_pImpIOleClientSite
|
||
|
|| NULL==m_pImpIOleIPSite || NULL==m_pImpIOleControlSite
|
||
|
|| NULL==m_pImpIDispatch)
|
||
|
return FALSE;
|
||
|
//End CHAPTER24MOD
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::Close
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Possibly commits the storage, then releases it reversing the
|
||
|
* reference count from Open. If the reference on the storage
|
||
|
* goes to zero, the storage is forgotten. However, the object we
|
||
|
* contain is still held and as long as it's active the storage
|
||
|
* remains alive.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* fCommit BOOL indicating if we're to commit.
|
||
|
*
|
||
|
* Return Value:
|
||
|
* None
|
||
|
*/
|
||
|
|
||
|
void tOleHandler::Close(BOOL fCommit)
|
||
|
{
|
||
|
/*
|
||
|
* We can't use a zero reference count to know when to NULL
|
||
|
* this since other things might have AddRef'd the storage.
|
||
|
*/
|
||
|
//OnInPlaceDeactivate releases this pointer.
|
||
|
if (NULL!=m_pIOleIPObject)
|
||
|
m_pIOleIPObject->InPlaceDeactivate();
|
||
|
|
||
|
//Close the object saving if necessary
|
||
|
if (NULL!=m_pIOleObject)
|
||
|
{
|
||
|
m_pIOleObject->Close(OLECLOSE_SAVEIFDIRTY);
|
||
|
ReleaseInterface(m_pIOleObject);
|
||
|
}
|
||
|
|
||
|
//Release all other held pointers
|
||
|
//CHAPTER24MOD
|
||
|
ReleaseInterface(m_pIOleControl);
|
||
|
|
||
|
//End CHAPTER24MOD
|
||
|
|
||
|
//Release all other held pointers
|
||
|
if (NULL!=m_pIViewObject2)
|
||
|
{
|
||
|
m_pIViewObject2->SetAdvise(m_fe.dwAspect, 0, NULL);
|
||
|
ReleaseInterface(m_pIViewObject2);
|
||
|
}
|
||
|
|
||
|
//We know we only hold one ref from Create or Load
|
||
|
ReleaseInterface(m_pObj);
|
||
|
|
||
|
if (NULL != m_pIStorage)
|
||
|
ReleaseInterface(m_pIStorage);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::Activate
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Activates a verb on the object living in the tenant. Does
|
||
|
* nothing for static objects.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* iVerb LONG of the verb to execute.
|
||
|
* pMSG LPMSG to the message causing the invocation.
|
||
|
*
|
||
|
* Return Value:
|
||
|
* BOOL TRUE if the object changed due to this verb
|
||
|
* execution.
|
||
|
*/
|
||
|
|
||
|
BOOL tOleHandler::Activate(LONG iVerb, LPMSG pMSG)
|
||
|
{
|
||
|
RECT rc, rcH;
|
||
|
SIZEL szl;
|
||
|
|
||
|
//Can't activate statics.
|
||
|
/* if (TENANTTYPE_STATIC==m_tType || NULL==m_pIOleObject)
|
||
|
{
|
||
|
MessageBeep(0);
|
||
|
return FALSE;
|
||
|
}*/
|
||
|
|
||
|
RECTFROMRECTL(rc, m_rcl);
|
||
|
RectConvertMappings(&rc, NULL, TRUE);
|
||
|
XformRectInPixelsToHimetric(NULL, &rc, &rcH);
|
||
|
|
||
|
//Get the server running first, then do a SetExtent, then show it
|
||
|
OleRun(m_pIOleObject);
|
||
|
|
||
|
if (m_fSetExtent)
|
||
|
{
|
||
|
SETSIZEL(szl, rcH.right-rcH.left, rcH.top-rcH.bottom);
|
||
|
m_pIOleObject->SetExtent(m_fe.dwAspect, &szl);
|
||
|
m_fSetExtent=FALSE;
|
||
|
}
|
||
|
|
||
|
//CHAPTER24MOD
|
||
|
/*
|
||
|
* If we have a pending deactivation, but we're activating
|
||
|
* again, clear the pending flag.
|
||
|
*/
|
||
|
if (OLEIVERB_UIACTIVATE==iVerb
|
||
|
|| OLEIVERB_INPLACEACTIVATE==iVerb)
|
||
|
m_fPendingDeactivate=FALSE;
|
||
|
//End CHAPTER24MOD
|
||
|
|
||
|
m_pIOleObject->DoVerb(iVerb, pMSG, m_pImpIOleClientSite, 0
|
||
|
, m_hWnd, &rcH);
|
||
|
|
||
|
//If object changes, IAdviseSink::OnViewChange will see it.
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::ObjectGet
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Retrieves the LPUNKNOWN of the object in use by this tenant
|
||
|
*
|
||
|
* Parameters:
|
||
|
* ppUnk LPUNKNOWN * in which to return the object
|
||
|
* pointer.
|
||
|
*
|
||
|
* Return Value:
|
||
|
* None
|
||
|
*/
|
||
|
|
||
|
void tOleHandler::ObjectGet(LPUNKNOWN *ppUnk)
|
||
|
{
|
||
|
if (NULL!=ppUnk)
|
||
|
{
|
||
|
*ppUnk=m_pObj;
|
||
|
m_pObj->AddRef();
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::SizeGet
|
||
|
* tOleHandler::SizeSet
|
||
|
* tOleHandler::RectGet
|
||
|
* tOleHandler::RectSet
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Returns or sets the size/position of the object contained here.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* pszl/prcl LPSIZEL (Size) or LPRECTL (Rect) with the
|
||
|
* extents of interest. In Get situations,
|
||
|
* this will receive the extents; in Set it
|
||
|
* contains the extents.
|
||
|
* fDevice BOOL indicating that pszl/prcl is expressed
|
||
|
* in device units. Otherwise it's LOMETRIC.
|
||
|
* fInformObj (Set Only) BOOL indicating if we need to inform
|
||
|
* the object all.
|
||
|
*
|
||
|
* Return Value:
|
||
|
* None
|
||
|
*/
|
||
|
|
||
|
void tOleHandler::SizeGet(LPSIZEL pszl, BOOL fDevice)
|
||
|
{
|
||
|
if (!fDevice)
|
||
|
{
|
||
|
pszl->cx=m_rcl.right-m_rcl.left;
|
||
|
pszl->cy=m_rcl.bottom-m_rcl.top;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RECT rc;
|
||
|
|
||
|
SetRect(&rc, (int)(m_rcl.right-m_rcl.left)
|
||
|
, (int)(m_rcl.bottom-m_rcl.top), 0, 0);
|
||
|
|
||
|
RectConvertMappings(&rc, NULL, TRUE);
|
||
|
|
||
|
pszl->cx=(long)rc.left;
|
||
|
pszl->cy=(long)rc.top;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void tOleHandler::SizeSet(LPSIZEL pszl, BOOL fDevice, BOOL fInformObj)
|
||
|
{
|
||
|
SIZEL szl;
|
||
|
|
||
|
if (!fDevice)
|
||
|
{
|
||
|
szl=*pszl;
|
||
|
m_rcl.right =pszl->cx+m_rcl.left;
|
||
|
m_rcl.bottom=pszl->cy+m_rcl.top;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RECT rc;
|
||
|
|
||
|
SetRect(&rc, (int)pszl->cx, (int)pszl->cy, 0, 0);
|
||
|
RectConvertMappings(&rc, NULL, FALSE);
|
||
|
|
||
|
m_rcl.right =(long)rc.left+m_rcl.left;
|
||
|
m_rcl.bottom=(long)rc.top+m_rcl.top;
|
||
|
|
||
|
SETSIZEL(szl, (long)rc.left, (long)rc.top);
|
||
|
}
|
||
|
|
||
|
//Tell OLE that this object was resized.
|
||
|
if (NULL!=m_pIOleObject && fInformObj)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
BOOL fRun=FALSE;
|
||
|
|
||
|
//Convert our LOMETRIC into HIMETRIC by *=10
|
||
|
szl.cx*=10;
|
||
|
szl.cy*=-10; //Our size is stored negative.
|
||
|
|
||
|
/*
|
||
|
* If the MiscStatus bit of OLEMISC_RECOMPOSEONRESIZE
|
||
|
* is set, then we need to run the object before calling
|
||
|
* SetExtent to make sure it has a real chance to
|
||
|
* re-render the object. We have to update and close
|
||
|
* the object as well after this happens.
|
||
|
*/
|
||
|
|
||
|
if (OLEMISC_RECOMPOSEONRESIZE & m_grfMisc)
|
||
|
{
|
||
|
if (!OleIsRunning(m_pIOleObject))
|
||
|
{
|
||
|
OleRun(m_pIOleObject);
|
||
|
fRun=TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hr=m_pIOleObject->SetExtent(m_fe.dwAspect, &szl);
|
||
|
|
||
|
/*
|
||
|
* If the object is not running and it does not have
|
||
|
* RECOMPOSEONRESIZE, then SetExtent fails. Make
|
||
|
* sure that we call SetExtent again (by just calling
|
||
|
* SizeSet here again) when we next run the object.
|
||
|
*/
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
m_fSetExtent=FALSE;
|
||
|
|
||
|
if (fRun)
|
||
|
{
|
||
|
m_pIOleObject->Update();
|
||
|
m_pIOleObject->Close(OLECLOSE_SAVEIFDIRTY);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (OLE_E_NOTRUNNING==GetScode(hr))
|
||
|
m_fSetExtent=TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void tOleHandler::RectGet(LPRECTL prcl, BOOL fDevice)
|
||
|
{
|
||
|
if (!fDevice)
|
||
|
*prcl=m_rcl;
|
||
|
else
|
||
|
{
|
||
|
RECT rc;
|
||
|
|
||
|
RECTFROMRECTL(rc, m_rcl);
|
||
|
RectConvertMappings(&rc, NULL, TRUE);
|
||
|
RECTLFROMRECT(*prcl, rc);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void tOleHandler::RectSet(LPRECTL prcl, BOOL fDevice, BOOL fInformObj)
|
||
|
{
|
||
|
SIZEL szl;
|
||
|
LONG cx, cy;
|
||
|
|
||
|
/*
|
||
|
* Prevent reentrant calls that may come from calling
|
||
|
* UpdateInPlaceObjectRects here and elsewhere.
|
||
|
*/
|
||
|
if (m_fInRectSet)
|
||
|
return;
|
||
|
|
||
|
m_fInRectSet=TRUE;
|
||
|
|
||
|
cx=m_rcl.right-m_rcl.left;
|
||
|
cy=m_rcl.bottom-m_rcl.top;
|
||
|
|
||
|
if (!fDevice)
|
||
|
m_rcl=*prcl;
|
||
|
else
|
||
|
{
|
||
|
RECT rc;
|
||
|
|
||
|
RECTFROMRECTL(rc, *prcl);
|
||
|
RectConvertMappings(&rc, NULL, FALSE);
|
||
|
RECTLFROMRECT(m_rcl, rc);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Tell ourselves that the size changed, if it did. SizeSet
|
||
|
* will call IOleObject::SetExtent for us.
|
||
|
*/
|
||
|
if ((m_rcl.right-m_rcl.left)!=cx || (m_rcl.bottom-m_rcl.top)!=cy)
|
||
|
{
|
||
|
SETSIZEL(szl, m_rcl.right-m_rcl.left, m_rcl.bottom-m_rcl.top);
|
||
|
SizeSet(&szl, FALSE, fInformObj);
|
||
|
}
|
||
|
|
||
|
//Tell an in-place active object it moved too
|
||
|
UpdateInPlaceObjectRects(NULL, TRUE);
|
||
|
m_fInRectSet=FALSE;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::DeactivateInPlaceObject
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Deactivates an in-place object if there is one in this tenant.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* fFull BOOL indicating full deactivation of UI
|
||
|
* deactivate only.
|
||
|
*
|
||
|
* Return Value:
|
||
|
* None
|
||
|
*/
|
||
|
|
||
|
void tOleHandler::DeactivateInPlaceObject(BOOL fFull)
|
||
|
{
|
||
|
if (NULL!=m_pIOleIPObject)
|
||
|
{
|
||
|
/*
|
||
|
* Activate-when-visible objects only UI deactivate
|
||
|
* unless we're fully deactivating on purpose.
|
||
|
*/
|
||
|
if ((OLEMISC_ACTIVATEWHENVISIBLE & m_grfMisc) && !fFull)
|
||
|
m_pIOleIPObject->UIDeactivate();
|
||
|
else
|
||
|
{
|
||
|
//CHAPTER24MOD
|
||
|
/*
|
||
|
* Only deactivate when there's no locks. If there
|
||
|
* is a lock, then remember that we need to deactivate
|
||
|
* when all the locks go away.
|
||
|
*/
|
||
|
if (0==m_cLockInPlace)
|
||
|
m_pIOleIPObject->InPlaceDeactivate();
|
||
|
else
|
||
|
m_fPendingDeactivate=TRUE;
|
||
|
//End CHAPTER24MOD
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::UpdateInPlaceObjectRects
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Generates a call to IOleInPlaceObject::SetObjectRects to allow
|
||
|
* it to show it's shading and its object adornments properly.
|
||
|
* This function deals in HIMETRIC units.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* prcPos LPCRECT to the size the object wants. Ignored
|
||
|
* if NULL in which case we use the size of the
|
||
|
* tenant. This rect is in client coordinates of
|
||
|
* the pages window.
|
||
|
* fUseTenantRect BOOL indicating if we need to use the tenant
|
||
|
* rectangle offset for scrolling regardless.
|
||
|
*
|
||
|
* Return Value:
|
||
|
* None
|
||
|
*/
|
||
|
|
||
|
void tOleHandler::UpdateInPlaceObjectRects(LPCRECT prcPos
|
||
|
, BOOL fUseTenantRect)
|
||
|
{
|
||
|
RECTL rcl;
|
||
|
RECT rc;
|
||
|
RECT rcClip;
|
||
|
BOOL fResizeTenant=TRUE;
|
||
|
|
||
|
//We don't clip special anywhere in our window.
|
||
|
SetRect(&rcClip, 0, 0, 32767, 32767);
|
||
|
|
||
|
/*
|
||
|
* Note that if the object here is activate-when-visible
|
||
|
* we'll always have this pointer.
|
||
|
*/
|
||
|
if (NULL!=m_pIOleIPObject)
|
||
|
{
|
||
|
/*
|
||
|
* This uses the last position rectangle from
|
||
|
* IOleInPlaceSite::OnPosRectChange if it's been
|
||
|
* initialized
|
||
|
*/
|
||
|
if (NULL==prcPos && -1!=m_rcPos.left && !fUseTenantRect)
|
||
|
prcPos=&m_rcPos;
|
||
|
|
||
|
//This code is normally called from OnPosRectChange direct.
|
||
|
if (NULL!=prcPos && !fUseTenantRect)
|
||
|
{
|
||
|
rc=*prcPos;
|
||
|
|
||
|
//Calculate the boundaries of the full page
|
||
|
//m_pPG->CalcBoundingRect(&rcClip, FALSE);
|
||
|
|
||
|
//Make sure we limit object to page boundaries.
|
||
|
IntersectRect(&rc, &rc, &rcClip);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*
|
||
|
* We have no rectangle of the object on which to
|
||
|
* base the position, so just use the tenant rectangle.
|
||
|
* This code is also used when scrolling objects.
|
||
|
*/
|
||
|
RectGet(&rcl, TRUE);
|
||
|
RECTFROMRECTL(rc, rcl);
|
||
|
|
||
|
//Account for scrolling
|
||
|
// OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos);
|
||
|
fResizeTenant=FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* NOTE: The rectangles to SetObjectRects is in client
|
||
|
* coordinates of the pages window.
|
||
|
*/
|
||
|
if (NULL!=m_pIOleIPObject)
|
||
|
m_pIOleIPObject->SetObjectRects(&rc, &rcClip);
|
||
|
|
||
|
if (fResizeTenant)
|
||
|
{
|
||
|
//Need to tell the tenant to change position too
|
||
|
RECTLFROMRECT(rcl, rc);
|
||
|
RectSet(&rcl, TRUE, FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::ObjectWindow
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Returns the window handle of the in-place object.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* None
|
||
|
*
|
||
|
* Return Value:
|
||
|
* HWND Handle of the object window.
|
||
|
*/
|
||
|
|
||
|
HWND tOleHandler::ObjectWindow(void)
|
||
|
{
|
||
|
HWND hWnd=NULL;
|
||
|
|
||
|
if (NULL!=m_pIOleIPObject)
|
||
|
m_pIOleIPObject->GetWindow(&hWnd);
|
||
|
|
||
|
return hWnd;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::ControlInitialize
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Initializes the control if that's the type of object we have
|
||
|
* in the site.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* None
|
||
|
*
|
||
|
* Return Value:
|
||
|
* BOOL TRUE if initialization worked, FALSE otherwise.
|
||
|
*/
|
||
|
|
||
|
BOOL tOleHandler::ControlInitialize(void)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
BOOL fEvents;
|
||
|
|
||
|
if (NULL==m_pObj)
|
||
|
return FALSE;
|
||
|
|
||
|
hr=m_pObj->QueryInterface(IID_IOleControl
|
||
|
, (PPVOID)&m_pIOleControl);
|
||
|
|
||
|
//Failure means not a control.
|
||
|
if (FAILED(hr))
|
||
|
return FALSE;
|
||
|
|
||
|
m_ambientProp.setControl(m_pIOleControl);
|
||
|
|
||
|
m_dwState |= TENANTSTATE_CONTROL;
|
||
|
|
||
|
if (OLEMISC_ACTSLIKEBUTTON & m_grfMisc)
|
||
|
m_dwState |= TENANTSTATE_BUTTON;
|
||
|
|
||
|
//We don't use this, but might as well store it.
|
||
|
if (OLEMISC_ACTSLIKELABEL & m_grfMisc)
|
||
|
m_dwState |= TENANTSTATE_LABEL;
|
||
|
|
||
|
/*
|
||
|
* Call IOleControl::GetControlInfo to retrieve the keyboard
|
||
|
* information for this control. We have to reload this
|
||
|
* information in IOleControlSite::OnControlInfoChanged.
|
||
|
*/
|
||
|
/*m_fHaveControlInfo=SUCCEEDED(m_pIOleControl
|
||
|
->GetControlInfo(&m_ctrlInfo));*/ //!!!
|
||
|
|
||
|
|
||
|
/*
|
||
|
* If you wanted to receive IPropertyNotifySink notifications
|
||
|
* for a control, establish that advisory connection here
|
||
|
* through the object's IConnectionPointContainer and
|
||
|
* IConnectionPoint.
|
||
|
*/
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::GetControlFlags
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Requests flags describing the control inside this tenant
|
||
|
* if there is, in fact a control.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* None
|
||
|
*
|
||
|
* Return Value:
|
||
|
* DWORD Flags describing the control from the
|
||
|
* TENANT
|
||
|
*/
|
||
|
|
||
|
DWORD tOleHandler::GetControlFlags(void)
|
||
|
{
|
||
|
return m_dwState & STATEMASK_CONTROLS;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::TryMnemonic
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Asks the tenant to check the given keyboard message against
|
||
|
* one that its control might want, passing it to
|
||
|
* IOleControl::OnMnemonic if there is a match.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* pMsg LPMSG containing the message to check.
|
||
|
*
|
||
|
* Return Value:
|
||
|
* BOOL TRUE if the mnemonic was a match,
|
||
|
* FALSE otherwise.
|
||
|
*/
|
||
|
|
||
|
BOOL tOleHandler::TryMnemonic(LPMSG pMsg)
|
||
|
{
|
||
|
UINT i;
|
||
|
BOOL fRet=FALSE;
|
||
|
LPACCEL pACC;
|
||
|
BYTE fVirt=FVIRTKEY;
|
||
|
|
||
|
if (!m_fHaveControlInfo) //False for non-controls
|
||
|
return FALSE;
|
||
|
|
||
|
if (0==m_ctrlInfo.cAccel)
|
||
|
return FALSE;
|
||
|
|
||
|
pACC=(LPACCEL)GlobalLock(m_ctrlInfo.hAccel);
|
||
|
|
||
|
if (NULL==pACC)
|
||
|
return FALSE;
|
||
|
|
||
|
/*
|
||
|
* We'll come here on WM_KEYDOWN messages and WM_SYSKEYDOWN
|
||
|
* messages. The control's accelerator table will contain
|
||
|
* entries that each have the desired key and the various
|
||
|
* modifier flags. We the create the current modifier flags
|
||
|
* then look for entries that match those flags and the key
|
||
|
* that is in the message itself.
|
||
|
*/
|
||
|
|
||
|
fVirt |= (WM_SYSKEYDOWN==pMsg->message) ? FALT : 0;
|
||
|
|
||
|
//GetKeyState works on the last message
|
||
|
fVirt |= (0x8000 & GetKeyState(VK_CONTROL)) ? FCONTROL : 0;
|
||
|
fVirt |= (0x8000 & GetKeyState(VK_SHIFT)) ? FSHIFT : 0;
|
||
|
|
||
|
for (i=0; i < m_ctrlInfo.cAccel; i++)
|
||
|
{
|
||
|
if (pACC[i].key==pMsg->wParam && pACC[i].fVirt==fVirt)
|
||
|
{
|
||
|
m_pIOleControl->OnMnemonic(pMsg);
|
||
|
fRet=TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
GlobalUnlock(m_ctrlInfo.hAccel);
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* tOleHandler::AmbientChange
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Notifes a control that an ambient property has changed in
|
||
|
* the control site.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* dispID DISPID of the property that changed.
|
||
|
*
|
||
|
* Return Value:
|
||
|
* None
|
||
|
*/
|
||
|
|
||
|
void tOleHandler::AmbientChange(DISPID dispID)
|
||
|
{
|
||
|
if (NULL!=m_pIOleControl)
|
||
|
m_pIOleControl->OnAmbientPropertyChange(dispID);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//End CHAPTER24MOD
|
||
|
|
||
|
void tOleHandler::OnShow()
|
||
|
{
|
||
|
// Se objeto ja' tive sido ativado, ignora chamada
|
||
|
// Alguns controles reagem mal quando ativados
|
||
|
// mais de uma vez
|
||
|
if(m_pIOleIPObject != NULL)
|
||
|
return;
|
||
|
|
||
|
if ((OLEMISC_ACTIVATEWHENVISIBLE & m_grfMisc))
|
||
|
Activate(OLEIVERB_INPLACEACTIVATE, NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
void tOleHandler::GetNaturalSize(long *pWidth, long *pHeight)
|
||
|
{
|
||
|
assert(pWidth && pHeight);
|
||
|
if(!pWidth || !pHeight)
|
||
|
return;
|
||
|
|
||
|
*pWidth = natural_width;
|
||
|
*pHeight = natural_height;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* CalcNaturalSize
|
||
|
* Obtem o tamanho desejado pelo objeto
|
||
|
*/
|
||
|
|
||
|
void tOleHandler::CalcNaturalSize()
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
SIZEL sizel;
|
||
|
RECTL rcl;
|
||
|
|
||
|
assert(m_pIViewObject2 != NULL);
|
||
|
|
||
|
if(!m_pIViewObject2)
|
||
|
return;
|
||
|
|
||
|
hr = m_pIViewObject2->GetExtent(m_fe.dwAspect, -1, NULL, &sizel);
|
||
|
|
||
|
if(FAILED(hr))
|
||
|
return;
|
||
|
|
||
|
SETRECTL(rcl, 0, 0, sizel.cx/10, -sizel.cy/10);
|
||
|
RectSet(&rcl, FALSE, TRUE);
|
||
|
|
||
|
// Obtem medidas ja' convertidas para pixels
|
||
|
SizeGet(&sizel, TRUE);
|
||
|
|
||
|
natural_width = sizel.cx;
|
||
|
natural_height = sizel.cy;
|
||
|
}
|
||
|
|