📄 tenant.cpp
字号:
/*
* TENANT.CPP
* Patron Chapter 24
*
* Implementation of the CTentant class which holds information
* for a single object on a page. It maintains position, references
* to data, and a storage.
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include "patron.h"
/*
* CTenant::CTenant
* CTenant::~CTenant
*
* Constructor Parameters:
* dwID DWORD identifier for this page.
* hWnd HWND of the pages window.
* pPG PCPages to the parent structure.
*/
CTenant::CTenant(DWORD dwID, HWND hWnd, PCPages pPG)
{
m_hWnd=hWnd;
m_dwID=dwID;
m_fInitialized=0;
m_pIStorage=NULL;
m_cOpens=0;
m_pObj=NULL;
m_pPG =pPG;
m_clsID=CLSID_NULL;
m_fSetExtent=FALSE;
m_cRef=0;
m_pIOleObject=NULL;
m_pIViewObject2=NULL;
m_grfMisc=0;
m_pImpIOleClientSite=NULL;
m_pImpIAdviseSink=NULL;
m_fRepaintEnabled=TRUE;
m_pmkFile=NULL;
m_fLinkAvail=TRUE; //Checked on Load
m_pmk=NULL;
m_pImpIOleIPSite=NULL;
m_pIOleIPObject=NULL;
m_rcPos.left=-1;
m_fInRectSet=FALSE;
//CHAPTER24MOD
m_pImpIOleControlSite=NULL;
m_pImpIDispatch=NULL;
m_pDispEvents=NULL;
m_dwConnEvents=0L;
m_iidEvents=GUID_NULL;
m_pEventMap=NULL;
m_pIOleControl=NULL;
m_pIDispatchControl=NULL;
//0x80000000 in OLE_COLOR indicates low byte is color index.
m_clrBack=0x80000000+COLOR_WINDOW;
m_clrFore=0x80000000+COLOR_WINDOWTEXT;
m_pIFont=m_pPG->m_pIFont;
m_lcid=LOCALE_USER_DEFAULT;
m_fDesignMode=m_pPG->m_fDesignMode;
m_fUIDead=m_pPG->m_fUIDead;
m_fHatchHandles=m_pPG->m_fHatchHandles;
m_fHaveControlInfo=FALSE;
m_cLockInPlace=0;
m_fPendingDeactivate=FALSE;
//End CHAPTER24MOD
return;
}
CTenant::~CTenant(void)
{
ReleaseInterface(m_pmk);
ReleaseInterface(m_pmkFile);
//Object pointers cleaned up in Close.
//CHAPTER24MOD
if (NULL!=m_pEventMap)
delete m_pEventMap;
DeleteInterfaceImp(m_pImpIOleControlSite);
DeleteInterfaceImp(m_pImpIDispatch);
if (NULL!=m_pDispEvents)
delete m_pDispEvents;
//End CHAPTER24MOD
DeleteInterfaceImp(m_pImpIOleIPSite);
DeleteInterfaceImp(m_pImpIAdviseSink);
DeleteInterfaceImp(m_pImpIOleClientSite);
return;
}
/*
* CTenant::QueryInterface
* CTenant::AddRef
* CTenant::Release
*
* Purpose:
* IUnknown members for CTenant object.
*/
STDMETHODIMP CTenant::QueryInterface(REFIID riid, PPVOID ppv)
{
*ppv=NULL;
if (IID_IUnknown==riid)
*ppv=this;
if (IID_IOleClientSite==riid)
*ppv=m_pImpIOleClientSite;
if (IID_IAdviseSink==riid)
*ppv=m_pImpIAdviseSink;
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) CTenant::AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CTenant::Release(void)
{
if (0!=--m_cRef)
return m_cRef;
delete this;
return 0;
}
/*
* CTenant::GetID
*
* Return Value:
* DWORD dwID field in this tenant.
*/
DWORD CTenant::GetID(void)
{
return m_dwID;
}
/*
* CTenant::GetStorageName
*
* Parameters:
* pszName LPOLESTR to a buffer in which to store the storage
* name for this tenant.
*
* Return Value:
* UINT Number of characters stored.
*/
UINT CTenant::GetStorageName(LPOLESTR pszName)
{
#ifdef WIN32ANSI
char szTemp[32];
UINT cch;
cch=wsprintf(szTemp, "Tenant %lu", m_dwID);
MultiByteToWideChar(CP_ACP, 0, szTemp, -1, pszName, 32);
return cch;
#else
return wsprintf(pszName, TEXT("Tenant %lu"), m_dwID);
#endif
}
/*
* CTenant::StorageGet
*
* Purpose:
* Returns the IStorage pointer maintained by this tenant,
* AddRef'd of course.
*
* Parameters:
* ppStg LPSTORAGE * in which to return the pointer.
*
* Return Value:
* None
*/
void CTenant::StorageGet(LPSTORAGE *ppStg)
{
if (NULL==ppStg)
return;
*ppStg=m_pIStorage;
if (NULL!=*ppStg)
(*ppStg)->AddRef();
return;
}
/*
* CTenant::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 CTenant::Create(TENANTTYPE tType, LPVOID pvType
, LPFORMATETC pFE, PPOINTL pptl, LPSIZEL pszl
, LPSTORAGE pIStorage, PPATRONOBJECT ppo, DWORD dwData)
{
HRESULT hr;
LPUNKNOWN pObj;
UINT uRet=CREATE_GRAPHICONLY;
if (NULL==pvType || NULL==pIStorage)
return CREATE_FAILED;
//Fail if this is called for an already living tenant.
if (m_fInitialized)
return CREATE_FAILED;
m_fInitialized=TRUE;
//Create a new storage for this tenant.
if (!Open(pIStorage))
return CREATE_FAILED;
/*
* Get the placement info if it's here. We either have a non-
* NULL PPATRONOBJECT in ppo or we have to use default
* placement and retrieve the size from the object itself.
*/
pszl->cx=0;
pszl->cy=0;
if (NULL!=ppo)
{
*pFE=ppo->fe;
*pptl=ppo->ptl;
*pszl=ppo->szl; //Could be 0,0 , so we ask object
uRet=CREATE_PLACEDOBJECT;
}
hr=ResultFromScode(E_FAIL);
//Now create an object based specifically for the type.
switch (tType)
{
case TENANTTYPE_NULL:
break;
case TENANTTYPE_STATIC:
/*
* We could use OleCreateStaticFromData here which does
* pretty much what we're doing below. However, it does
* not allow us to control whether we paste a bitmap or
* a metafile--it uses metafile first, bitmap second.
* For this reason we'll use code developed in Chapter
* 11's FreeLoader to affect the paste.
*/
hr=CreateStatic((LPDATAOBJECT)pvType, pFE, &pObj);
break;
case TENANTTYPE_EMBEDDEDOBJECT:
//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=OleCreate(*((LPCLSID)pvType), IID_IUnknown
, OLERENDER_DRAW, NULL, NULL, m_pIStorage
, (PPVOID)&pObj);
break;
case TENANTTYPE_EMBEDDEDFILE:
hr=OleCreateFromFile(CLSID_NULL, (LPTSTR)pvType
, IID_IUnknown, OLERENDER_DRAW, NULL, NULL
, m_pIStorage, (PPVOID)&pObj);
break;
case TENANTTYPE_EMBEDDEDOBJECTFROMDATA:
hr=OleCreateFromData((LPDATAOBJECT)pvType, IID_IUnknown
, OLERENDER_DRAW, NULL, NULL, m_pIStorage
, (PPVOID)&pObj);
break;
case TENANTTYPE_LINKEDFILE:
hr=OleCreateLinkToFile((LPTSTR)pvType, IID_IUnknown
, OLERENDER_DRAW, NULL, NULL, m_pIStorage
, (PPVOID)&pObj);
break;
case TENANTTYPE_LINKEDOBJECTFROMDATA:
hr=OleCreateLinkFromData((LPDATAOBJECT)pvType
, IID_IUnknown, OLERENDER_DRAW, NULL, NULL
, m_pIStorage, (PPVOID)&pObj);
break;
default:
break;
}
//If creation didn't work, get rid of the element Open created.
if (FAILED(hr))
{
Destroy(pIStorage);
return CREATE_FAILED;
}
//We don't get the size if PatronObject data was seen already.
if (!ObjectInitialize(pObj, pFE, dwData))
{
Destroy(pIStorage);
return CREATE_FAILED;
}
if (0==pszl->cx && 0==pszl->cy)
{
SIZEL szl;
//Try to get the real size of the object, default to 2"*2"
SETSIZEL((*pszl), 2*LOMETRIC_PER_INCH, 2*LOMETRIC_PER_INCH);
hr=ResultFromScode(E_FAIL);
//Try IViewObject2 first, then IOleObject as a backup.
if (NULL!=m_pIViewObject2)
{
hr=m_pIViewObject2->GetExtent(m_fe.dwAspect, -1, NULL
, &szl);
}
else
{
if (NULL!=m_pIOleObject)
hr=m_pIOleObject->GetExtent(m_fe.dwAspect, &szl);
}
if (SUCCEEDED(hr))
{
//Convert HIMETRIC to our LOMETRIC mapping
SETSIZEL((*pszl), szl.cx/10, szl.cy/10);
}
}
//CHAPTER24MOD
//Make sure this happens
if ((OLEMISC_ACTIVATEWHENVISIBLE & m_grfMisc) && !m_fDesignMode)
Activate(OLEIVERB_INPLACEACTIVATE, NULL);
//End CHAPTER24MOD
return uRet;
}
/*
* CTenant::Load
*
* Purpose:
* Recreates the object living in this tenant in place of calling
* FCreate. This is used in loading as opposed to new creation.
*
* Parameters:
* pIStorage LPSTORAGE of the page we live in.
* pti PTENTANTINFO containing persistent information.
* The ID value in this structure is ignored.
*
* Return Value:
* BOOL TRUE if successful, FALSE otherwise.
*/
BOOL CTenant::Load(LPSTORAGE pIStorage, PTENANTINFO pti)
{
HRESULT hr;
LPUNKNOWN pObj;
DWORD dwState=TENANTSTATE_DEFAULT;
if (NULL==pIStorage || NULL==pti)
return FALSE;
/*
* If we already initialized once, clean up, releasing
* everything before we attempt to reload. This happens
* when using the Convert Dialog.
*/
if (m_fInitialized)
{
//Preserve all states except open
dwState=(m_dwState & ~TENANTSTATE_OPEN);
m_cRef++; //Prevent accidental closure
//This should release all holds on our IStorage as well.
if (NULL!=m_pIViewObject2)
{
m_pIViewObject2->SetAdvise(m_fe.dwAspect, 0, NULL);
ReleaseInterface(m_pIViewObject2);
}
ReleaseInterface(m_pIOleObject);
ReleaseInterface(m_pObj);
m_pIStorage=NULL; //We'll have already released this.
m_cRef--; //Match safety increment above.
}
m_fInitialized=TRUE;
//Open the storage for this tenant.
if (!Open(pIStorage))
return FALSE;
/*
* NOTE: If you do not pass an IOleClientSite to OleLoad
* it will not automatically reconnect a linked object to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -