IDATAOBJ.CPP

/* 
* IDATAOBJ.CPP
* Polyline Component Chapter 23
*
* Implementation of the IDataObject interface.
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/


#include "polyline.h"


/*
* CImpIDataObject::CImpIDataObject
* CImpIDataObject::~CImpIDataObject
*
* Parameters (Constructor):
* pObj PCPolyline of the object we're in.
* pUnkOuter LPUNKNOWN to which we delegate.
*/

CImpIDataObject::CImpIDataObject(PCPolyline pObj
, LPUNKNOWN pUnkOuter)
{
m_cRef=0;
m_pObj=pObj;
m_pUnkOuter=pUnkOuter;
return;
}

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




/*
* CImpIDataObject::QueryInterface
* CImpIDataObject::AddRef
* CImpIDataObject::Release
*/

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


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

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





/*
* CImpIDataObject::GetData
*
* Purpose:
* Retrieves data described by a specific FormatEtc into a StgMedium
* allocated by this function. Used like GetClipboardData.
*
* Parameters:
* pFE LPFORMATETC describing the desired data.
* pSTM LPSTGMEDIUM in which to return the data.
*
* Return Value:
* HRESULT NOERROR or a general error value.
*/

STDMETHODIMP CImpIDataObject::GetData(LPFORMATETC pFE
, LPSTGMEDIUM pSTM)
{
UINT cf=pFE->cfFormat;

//Check the aspects we support.
if (!(DVASPECT_CONTENT & pFE->dwAspect))
return ResultFromScode(DATA_E_FORMATETC);

pSTM->pUnkForRelease=NULL;

//Run creates the window to use as a basis for extents
m_pObj->m_pImpIRunnableObject->Run(NULL);

//Go render the appropriate data for the format.
switch (cf)
{
case CF_METAFILEPICT:
pSTM->tymed=TYMED_MFPICT;
return m_pObj->RenderMetafilePict(&pSTM->hGlobal);

case CF_BITMAP:
pSTM->tymed=TYMED_GDI;
return m_pObj->RenderBitmap((HBITMAP *)&pSTM->hGlobal);

default:
if (cf==m_pObj->m_cf)
{
pSTM->tymed=TYMED_HGLOBAL;
return m_pObj->RenderNative(&pSTM->hGlobal);
}

break;
}

return ResultFromScode(DATA_E_FORMATETC);
}




/*
* CImpIDataObject::GetDataHere
*
* Purpose:
* Renders the specific FormatEtc into caller-allocated medium
* provided in pSTM.
*
* Parameters:
* pFE LPFORMATETC describing the desired data.
* pSTM LPSTGMEDIUM providing the medium into which
* wer render the data.
*
* Return Value:
* HRESULT NOERROR or a general error value.
*/

STDMETHODIMP CImpIDataObject::GetDataHere(LPFORMATETC pFE
, LPSTGMEDIUM pSTM)
{
UINT cf;
HRESULT hr;

/*
* The only reasonable time this is called is for
* CFSTR_EMBEDSOURCE and TYMED_ISTORAGE (and later for
* CFSTR_LINKSOURCE). This means the same as
* IPersistStorage::Save.
*/

cf=RegisterClipboardFormat(CFSTR_EMBEDSOURCE);

//Aspect is unimportant to us here, as is lindex and ptd.
if (cf==pFE->cfFormat && (TYMED_ISTORAGE & pFE->tymed))
{
//We have an IStorage we can write into.
pSTM->tymed=TYMED_ISTORAGE;
pSTM->pUnkForRelease=NULL;

hr=m_pObj->m_pImpIPersistStorage->Save(pSTM->pstg, FALSE);
m_pObj->m_pImpIPersistStorage->SaveCompleted(NULL);
return hr;
}

return ResultFromScode(DATA_E_FORMATETC);
}






/*
* CImpIDataObject::QueryGetData
*
* Purpose:
* Tests if a call to GetData with this FormatEtc will provide
* any rendering; used like IsClipboardFormatAvailable.
*
* Parameters:
* pFE LPFORMATETC describing the desired data.
*
* Return Value:
* HRESULT NOERROR or a general error value.
*/

STDMETHODIMP CImpIDataObject::QueryGetData(LPFORMATETC pFE)
{
UINT cf=pFE->cfFormat;
BOOL fRet=FALSE;

//Check the aspects we support.
if (!(DVASPECT_CONTENT & pFE->dwAspect))
return ResultFromScode(DATA_E_FORMATETC);

switch (cf)
{
case CF_METAFILEPICT:
fRet=(BOOL)(pFE->tymed & TYMED_MFPICT);
break;

case CF_BITMAP:
fRet=(BOOL)(pFE->tymed & TYMED_GDI);
break;

default:
//Check our own format.
fRet=((cf==m_pObj->m_cf)
&& (BOOL)(pFE->tymed & TYMED_HGLOBAL));
break;
}

return fRet ? NOERROR : ResultFromScode(S_FALSE);
}






/*
* CImpIDataObject::GetCanonicalFormatEtc
*
* Purpose:
* Provides the caller with an equivalent FormatEtc to the one
* provided when different FormatEtcs will produce exactly the
* same renderings.
*
* Parameters:
* pFEIn LPFORMATETC of the first description.
* pFEOut LPFORMATETC of the equal description.
*
* Return Value:
* HRESULT NOERROR or a general error value.
*/

STDMETHODIMP CImpIDataObject::GetCanonicalFormatEtc
(LPFORMATETC pFEIn, LPFORMATETC pFEOut)
{
if (NULL==pFEOut)
return ResultFromScode(E_INVALIDARG);

pFEOut->ptd=NULL;
return ResultFromScode(DATA_S_SAMEFORMATETC);
}






/*
* CImpIDataObject::SetData
*
* Purpose:
* Places data described by a FormatEtc and living in a StgMedium
* into the object. The object may be responsible to clean up the
* StgMedium before exiting.
*
* Parameters:
* pFE LPFORMATETC describing the data to set.
* pSTM LPSTGMEDIUM containing the data.
* fRelease BOOL indicating if this function is responsible
* for freeing the data.
*
* Return Value:
* HRESULT NOERROR or a general error value.
*/

STDMETHODIMP CImpIDataObject::SetData(LPFORMATETC pFE
, LPSTGMEDIUM pSTM, BOOL fRelease)
{
UINT cf=pFE->cfFormat;
BOOL fRet=FALSE;
PPOLYLINEDATA ppl;

//Check for our own clipboard format and DVASPECT_CONTENT
if ((cf!=m_pObj->m_cf) || !(DVASPECT_CONTENT & pFE->dwAspect))
return ResultFromScode(DATA_E_FORMATETC);

/*
* Data can only come from global memory containing a
* POLYLINEDATA structure that we send to the Polyline's
* DataSet, a now internal function used from here and
* from IPersistStorage::Load.
*/

if (TYMED_HGLOBAL!=pSTM->tymed)
return ResultFromScode(DATA_E_FORMATETC);

ppl=(PPOLYLINEDATA)GlobalLock(pSTM->hGlobal);

if (NULL!=ppl)
{
m_pObj->DataSet(ppl, TRUE, TRUE);
GlobalUnlock(pSTM->hGlobal);
fRet=TRUE;
}

if (fRelease)
ReleaseStgMedium(pSTM);

return fRet ? NOERROR : ResultFromScode(DATA_E_FORMATETC);
}






/*
* CImpIDataObject::EnumFormatEtc
*
* Purpose:
* Returns an IEnumFORMATETC object through which the caller can
* iterate to learn about all the data formats this object can
* provide through either GetData[Here] or SetData.
*
* Parameters:
* dwDir DWORD describing a data direction, either
* DATADIR_SET or DATADIR_GET.
* ppEnum LPENUMFORMATETC * in which to return the
* pointer to the enumerator.
*
* Return Value:
* HRESULT NOERROR or a general error value.
*/

STDMETHODIMP CImpIDataObject::EnumFormatEtc(DWORD dwDir
, LPENUMFORMATETC *ppEnum)
{
return m_pObj->m_pDefIDataObject->EnumFormatEtc(dwDir, ppEnum);
}




/*
* CImpIDataObject::DAdvise
* CImpIDataObject::DUnadvise
* CImpIDataObject::EnumDAdvise
*/

STDMETHODIMP CImpIDataObject::DAdvise(LPFORMATETC pFE, DWORD dwFlags
, LPADVISESINK pIAdviseSink, LPDWORD pdwConn)
{
HRESULT hr;

if (NULL==m_pObj->m_pIDataAdviseHolder)
{
hr=CreateDataAdviseHolder(&m_pObj->m_pIDataAdviseHolder);

if (FAILED(hr))
return ResultFromScode(E_OUTOFMEMORY);
}

hr=m_pObj->m_pIDataAdviseHolder->Advise(this, pFE
, dwFlags, pIAdviseSink, pdwConn);

return hr;
}


STDMETHODIMP CImpIDataObject::DUnadvise(DWORD dwConn)
{
HRESULT hr;

if (NULL==m_pObj->m_pIDataAdviseHolder)
return ResultFromScode(E_FAIL);

hr=m_pObj->m_pIDataAdviseHolder->Unadvise(dwConn);

return hr;
}



STDMETHODIMP CImpIDataObject::EnumDAdvise(LPENUMSTATDATA *ppEnum)
{
HRESULT hr;

if (NULL==m_pObj->m_pIDataAdviseHolder)
return ResultFromScode(E_FAIL);

hr=m_pObj->m_pIDataAdviseHolder->EnumAdvise(ppEnum);
return hr;
}