/*++ Copyright (C) 1993-1999 Microsoft Corporation Module Name: idataobj.cpp Abstract: Implementation of the IDataObject interface. --*/ #include "polyline.h" #include "unkhlpr.h" // CImpIDataObject interface implmentation IMPLEMENT_CONTAINED_INTERFACE(CPolyline, CImpIDataObject) /* * 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) { CLIPFORMAT cf=pFE->cfFormat; IStream *pIStream; HRESULT hr; HDC hDevDC = NULL; //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; hDevDC = CreateTargetDC (NULL, pFE->ptd ); if (hDevDC) { hr = m_pObj->RenderMetafilePict(&pSTM->hGlobal, hDevDC); ::DeleteDC(hDevDC); } else { hr = ResultFromScode(E_FAIL); } return hr; case CF_BITMAP: pSTM->tymed=TYMED_GDI; hDevDC = CreateTargetDC (NULL, pFE->ptd ); if (hDevDC) { hr = m_pObj->RenderBitmap((HBITMAP *)&pSTM->hGlobal, hDevDC); ::DeleteDC(hDevDC); } else { hr = ResultFromScode(E_FAIL); } return hr; default: if (cf == m_pObj->m_cf) { hr = CreateStreamOnHGlobal(NULL, TRUE, &pIStream); if (FAILED(hr)) return ResultFromScode(E_OUTOFMEMORY); hr = m_pObj->m_pCtrl->SaveToStream(pIStream); if (FAILED(hr)) { pIStream->Release(); return hr; } pSTM->tymed = TYMED_ISTREAM; pSTM->pstm = pIStream; return NOERROR; } 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) { CLIPFORMAT 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=(CLIPFORMAT)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) { CLIPFORMAT 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_ISTREAM) )); break; } return fRet ? NOERROR : ResultFromScode(DATA_E_FORMATETC); } /* * 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 ) { CLIPFORMAT cf=pFE->cfFormat; HRESULT hr; //Check for our own clipboard format and DVASPECT_CONTENT if ((cf!=m_pObj->m_cf) || !(DVASPECT_CONTENT & pFE->dwAspect)) return ResultFromScode(DATA_E_FORMATETC); // The medium must be a stream if (TYMED_ISTREAM != pSTM->tymed) return ResultFromScode(DATA_E_FORMATETC); hr = m_pObj->m_pCtrl->LoadFromStream(pSTM->pstm); if (fRelease) ReleaseStgMedium(pSTM); return hr; } /* * 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; // Check if requested format is supported hr = QueryGetData(pFE); if (FAILED(hr)) return 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; }