You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
502 lines
11 KiB
502 lines
11 KiB
/*++
|
|
|
|
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(
|
|
IN LPFORMATETC pFE,
|
|
OUT LPSTGMEDIUM pSTM
|
|
)
|
|
{
|
|
CLIPFORMAT cf;
|
|
IStream *pIStream = NULL;
|
|
HDC hDevDC = NULL;
|
|
HRESULT hr = DATA_E_FORMATETC;
|
|
|
|
if (pFE == NULL || pSTM == NULL) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
try {
|
|
cf = pFE->cfFormat;
|
|
|
|
//
|
|
// Use do{}while(0) to act like a switch statement
|
|
//
|
|
do {
|
|
//
|
|
//Check the aspects we support.
|
|
//
|
|
if (!(DVASPECT_CONTENT & pFE->dwAspect)) {
|
|
hr = DATA_E_FORMATETC;
|
|
break;
|
|
}
|
|
|
|
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);
|
|
}
|
|
else {
|
|
hr = E_FAIL;
|
|
}
|
|
break;
|
|
|
|
case CF_BITMAP:
|
|
pSTM->tymed=TYMED_GDI;
|
|
hDevDC = CreateTargetDC (NULL, pFE->ptd );
|
|
if (hDevDC) {
|
|
hr = m_pObj->RenderBitmap((HBITMAP *)&pSTM->hGlobal, hDevDC);
|
|
}
|
|
else {
|
|
hr = E_FAIL;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (cf == m_pObj->m_cf)
|
|
{
|
|
hr = CreateStreamOnHGlobal(NULL, TRUE, &pIStream);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_pObj->m_pCtrl->SaveToStream(pIStream);
|
|
if (FAILED(hr)) {
|
|
pIStream->Release();
|
|
}
|
|
}
|
|
else {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
pSTM->tymed = TYMED_ISTREAM;
|
|
pSTM->pstm = pIStream;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
} while (0);
|
|
|
|
} catch (...) {
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
if (hDevDC) {
|
|
::DeleteDC(hDevDC);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* 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(
|
|
IN LPFORMATETC pFE,
|
|
IN OUT LPSTGMEDIUM pSTM
|
|
)
|
|
{
|
|
CLIPFORMAT cf;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pFE == NULL || pSTM == NULL) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
/*
|
|
* 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);
|
|
|
|
try {
|
|
//Aspect is not important 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);
|
|
}
|
|
else {
|
|
hr = DATA_E_FORMATETC;
|
|
}
|
|
} catch (...) {
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* 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(
|
|
IN LPFORMATETC pFE
|
|
)
|
|
{
|
|
CLIPFORMAT cf;
|
|
BOOL fRet = FALSE;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pFE == NULL) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
try {
|
|
cf = pFE->cfFormat;
|
|
|
|
//
|
|
//Check the aspects we support.
|
|
//
|
|
if (!(DVASPECT_CONTENT & pFE->dwAspect)) {
|
|
hr = DATA_E_FORMATETC;
|
|
}
|
|
else {
|
|
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;
|
|
}
|
|
if (fRet == FALSE) {
|
|
hr = DATA_E_FORMATETC;
|
|
}
|
|
}
|
|
} catch (...) {
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*
|
|
* 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 E_POINTER;
|
|
}
|
|
|
|
try {
|
|
pFEOut->ptd = NULL;
|
|
} catch (...) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
return 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;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pFE == NULL || pSTM == NULL) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
try {
|
|
cf = pFE->cfFormat;
|
|
|
|
do {
|
|
//
|
|
//Check for our own clipboard format and DVASPECT_CONTENT
|
|
//
|
|
if ((cf != m_pObj->m_cf) || !(DVASPECT_CONTENT & pFE->dwAspect)) {
|
|
hr = DATA_E_FORMATETC;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// The medium must be a stream
|
|
//
|
|
if (TYMED_ISTREAM != pSTM->tymed) {
|
|
hr = DATA_E_FORMATETC;
|
|
break;
|
|
}
|
|
|
|
hr = m_pObj->m_pCtrl->LoadFromStream(pSTM->pstm);
|
|
} while (0);
|
|
|
|
if (fRelease)
|
|
ReleaseStgMedium(pSTM);
|
|
|
|
} catch (...) {
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
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
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (ppEnum == NULL) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
try {
|
|
hr = m_pObj->m_pDefIDataObject->EnumFormatEtc(dwDir, ppEnum);
|
|
} catch (...) {
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CImpIDataObject::DAdvise
|
|
* CImpIDataObject::DUnadvise
|
|
* CImpIDataObject::EnumDAdvise
|
|
*/
|
|
|
|
STDMETHODIMP
|
|
CImpIDataObject::DAdvise(
|
|
LPFORMATETC pFE,
|
|
DWORD dwFlags,
|
|
LPADVISESINK pIAdviseSink,
|
|
LPDWORD pdwConn
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
do {
|
|
// Check if requested format is supported
|
|
hr = QueryGetData(pFE);
|
|
if (FAILED(hr)) {
|
|
break;
|
|
}
|
|
|
|
if (NULL == m_pObj->m_pIDataAdviseHolder) {
|
|
hr = CreateDataAdviseHolder(&m_pObj->m_pIDataAdviseHolder);
|
|
|
|
if (FAILED(hr)) {
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
}
|
|
|
|
hr = m_pObj->m_pIDataAdviseHolder->Advise(this,
|
|
pFE,
|
|
dwFlags,
|
|
pIAdviseSink,
|
|
pdwConn);
|
|
} while (0);
|
|
|
|
} catch (...) {
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CImpIDataObject::DUnadvise(
|
|
IN DWORD dwConn
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == m_pObj->m_pIDataAdviseHolder) {
|
|
return E_FAIL;
|
|
}
|
|
|
|
hr = m_pObj->m_pIDataAdviseHolder->Unadvise(dwConn);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CImpIDataObject::EnumDAdvise(
|
|
OUT LPENUMSTATDATA *ppEnum
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (ppEnum == NULL) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
try {
|
|
*ppEnum = NULL;
|
|
|
|
if (m_pObj->m_pIDataAdviseHolder != NULL) {
|
|
hr = m_pObj->m_pIDataAdviseHolder->EnumAdvise(ppEnum);
|
|
}
|
|
else {
|
|
hr = E_FAIL;
|
|
}
|
|
} catch (...) {
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
return hr;
|
|
}
|