📄 oledobj2.cpp
字号:
if (lpFormatEtc->tymed & TYMED_ISTREAM)
{
COleStreamFile file;
if (lpStgMedium->tymed == TYMED_ISTREAM)
{
ASSERT(lpStgMedium->pstm != NULL);
file.Attach(lpStgMedium->pstm);
}
else
{
if (!file.CreateMemoryStream())
AfxThrowMemoryException();
}
// get data into the stream
if (OnRenderFileData(lpFormatEtc, &file))
{
lpStgMedium->tymed = TYMED_ISTREAM;
lpStgMedium->pstm = file.Detach();
return TRUE;
}
if (lpStgMedium->tymed == TYMED_ISTREAM)
file.Detach();
}
return FALSE; // default does nothing
}
BOOL COleDataSource::OnSetData(
LPFORMATETC /*lpFormatEtc*/, LPSTGMEDIUM /*lpStgMedium*/, BOOL /*bRelease*/)
{
return FALSE; // default does nothing
}
/////////////////////////////////////////////////////////////////////////////
// CEnumFormatEtc - enumerator for array for FORMATETC structures
class CEnumFormatEtc : public CEnumArray
{
// Constructors
public:
CEnumFormatEtc();
// Operations
void AddFormat(const FORMATETC* lpFormatEtc);
// Implementation
public:
virtual ~CEnumFormatEtc();
protected:
virtual BOOL OnNext(void* pv);
UINT m_nMaxSize; // number of items allocated (>= m_nSize)
DECLARE_INTERFACE_MAP()
};
BEGIN_INTERFACE_MAP(CEnumFormatEtc, CEnumArray)
INTERFACE_PART(CEnumFormatEtc, IID_IEnumFORMATETC, EnumVOID)
END_INTERFACE_MAP()
CEnumFormatEtc::CEnumFormatEtc()
: CEnumArray(sizeof(FORMATETC), NULL, 0, TRUE)
{
m_nMaxSize = 0;
}
CEnumFormatEtc::~CEnumFormatEtc()
{
if (m_pClonedFrom == NULL)
{
// release all of the pointers to DVTARGETDEVICE
LPFORMATETC lpFormatEtc = (LPFORMATETC)m_pvEnum;
for (UINT nIndex = 0; nIndex < m_nSize; nIndex++)
CoTaskMemFree(lpFormatEtc[nIndex].ptd);
}
// destructor will free the actual array (if it was not a clone)
}
BOOL CEnumFormatEtc::OnNext(void* pv)
{
if (!CEnumArray::OnNext(pv))
return FALSE;
// any outgoing formatEtc may require the DVTARGETDEVICE to
// be copied (the caller has responsibility to free it)
LPFORMATETC lpFormatEtc = (LPFORMATETC)pv;
if (lpFormatEtc->ptd != NULL)
{
lpFormatEtc->ptd = _AfxOleCopyTargetDevice(lpFormatEtc->ptd);
if (lpFormatEtc->ptd == NULL)
AfxThrowMemoryException();
}
// otherwise, copying worked...
return TRUE;
}
void CEnumFormatEtc::AddFormat(const FORMATETC* lpFormatEtc)
{
ASSERT(m_nSize <= m_nMaxSize);
if (m_nSize == m_nMaxSize)
{
// not enough space for new item -- allocate more
FORMATETC* pListNew = new FORMATETC[m_nSize+10];
m_nMaxSize += 10;
memcpy(pListNew, m_pvEnum, m_nSize*sizeof(FORMATETC));
delete m_pvEnum;
m_pvEnum = (BYTE*)pListNew;
}
// add this item to the list
ASSERT(m_nSize < m_nMaxSize);
FORMATETC* pFormat = &((FORMATETC*)m_pvEnum)[m_nSize];
pFormat->cfFormat = lpFormatEtc->cfFormat;
pFormat->ptd = lpFormatEtc->ptd;
// Note: ownership of lpFormatEtc->ptd is transfered with this call.
pFormat->dwAspect = lpFormatEtc->dwAspect;
pFormat->lindex = lpFormatEtc->lindex;
pFormat->tymed = lpFormatEtc->tymed;
++m_nSize;
}
/////////////////////////////////////////////////////////////////////////////
// COleDataSource::XDataObject
BEGIN_INTERFACE_MAP(COleDataSource, CCmdTarget)
INTERFACE_PART(COleDataSource, IID_IDataObject, DataObject)
END_INTERFACE_MAP()
STDMETHODIMP_(ULONG) COleDataSource::XDataObject::AddRef()
{
METHOD_PROLOGUE_EX_(COleDataSource, DataObject)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) COleDataSource::XDataObject::Release()
{
METHOD_PROLOGUE_EX_(COleDataSource, DataObject)
return pThis->ExternalRelease();
}
STDMETHODIMP COleDataSource::XDataObject::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
METHOD_PROLOGUE_EX_(COleDataSource, DataObject)
return pThis->ExternalQueryInterface(&iid, ppvObj);
}
STDMETHODIMP COleDataSource::XDataObject::GetData(
LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
{
METHOD_PROLOGUE_EX(COleDataSource, DataObject)
ASSERT_VALID(pThis);
// attempt to find match in the cache
AFX_DATACACHE_ENTRY* pCache = pThis->Lookup(lpFormatEtc, DATADIR_GET);
if (pCache == NULL)
return DATA_E_FORMATETC;
// use cache if entry is not delay render
memset(lpStgMedium, 0, sizeof(STGMEDIUM));
if (pCache->m_stgMedium.tymed != TYMED_NULL)
{
// Copy the cached medium into the lpStgMedium provided by caller.
if (!_AfxCopyStgMedium(lpFormatEtc->cfFormat, lpStgMedium,
&pCache->m_stgMedium))
return DATA_E_FORMATETC;
// format was supported for copying
return S_OK;
}
SCODE sc = DATA_E_FORMATETC;
TRY
{
// attempt LPSTGMEDIUM based delay render
if (pThis->OnRenderData(lpFormatEtc, lpStgMedium))
sc = S_OK;
}
CATCH_ALL(e)
{
sc = COleException::Process(e);
DELETE_EXCEPTION(e);
}
END_CATCH_ALL
return sc;
}
STDMETHODIMP COleDataSource::XDataObject::GetDataHere(
LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
{
METHOD_PROLOGUE_EX(COleDataSource, DataObject)
ASSERT_VALID(pThis);
// these two must be the same
ASSERT(lpFormatEtc->tymed == lpStgMedium->tymed);
lpFormatEtc->tymed = lpStgMedium->tymed; // but just in case...
// attempt to find match in the cache
AFX_DATACACHE_ENTRY* pCache = pThis->Lookup(lpFormatEtc, DATADIR_GET);
if (pCache == NULL)
return DATA_E_FORMATETC;
// handle cached medium and copy
if (pCache->m_stgMedium.tymed != TYMED_NULL)
{
// found a cached format -- copy it to dest medium
ASSERT(pCache->m_stgMedium.tymed == lpStgMedium->tymed);
if (!_AfxCopyStgMedium(lpFormatEtc->cfFormat, lpStgMedium,
&pCache->m_stgMedium))
return DATA_E_FORMATETC;
// format was supported for copying
return S_OK;
}
SCODE sc = DATA_E_FORMATETC;
TRY
{
// attempt LPSTGMEDIUM based delay render
if (pThis->OnRenderData(lpFormatEtc, lpStgMedium))
sc = S_OK;
}
CATCH_ALL(e)
{
sc = COleException::Process(e);
DELETE_EXCEPTION(e);
}
END_CATCH_ALL
return sc;
}
STDMETHODIMP COleDataSource::XDataObject::QueryGetData(LPFORMATETC lpFormatEtc)
{
METHOD_PROLOGUE_EX_(COleDataSource, DataObject)
// attempt to find match in the cache
AFX_DATACACHE_ENTRY* pCache = pThis->Lookup(lpFormatEtc, DATADIR_GET);
if (pCache == NULL)
return DATA_E_FORMATETC;
// it was found in the cache or can be rendered -- success
return S_OK;
}
STDMETHODIMP COleDataSource::XDataObject::GetCanonicalFormatEtc(
LPFORMATETC /*lpFormatEtcIn*/, LPFORMATETC /*lpFormatEtcOut*/)
{
// because we support the target-device (ptd) for server metafile format,
// all members of the FORMATETC are significant.
return DATA_S_SAMEFORMATETC;
}
STDMETHODIMP COleDataSource::XDataObject::SetData(
LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium, BOOL bRelease)
{
METHOD_PROLOGUE_EX(COleDataSource, DataObject)
ASSERT_VALID(pThis);
ASSERT(lpFormatEtc->tymed == lpStgMedium->tymed);
// attempt to find match in the cache
AFX_DATACACHE_ENTRY* pCache = pThis->Lookup(lpFormatEtc, DATADIR_SET);
if (pCache == NULL)
return DATA_E_FORMATETC;
ASSERT(pCache->m_stgMedium.tymed == TYMED_NULL);
SCODE sc = E_UNEXPECTED;
TRY
{
// attempt LPSTGMEDIUM based SetData
if (pThis->OnSetData(lpFormatEtc, lpStgMedium, bRelease))
sc = S_OK;
}
CATCH_ALL(e)
{
sc = COleException::Process(e);
DELETE_EXCEPTION(e);
}
END_CATCH_ALL
return sc;
}
STDMETHODIMP COleDataSource::XDataObject::EnumFormatEtc(
DWORD dwDirection, LPENUMFORMATETC* ppenumFormatEtc)
{
METHOD_PROLOGUE_EX_(COleDataSource, DataObject)
*ppenumFormatEtc = NULL;
CEnumFormatEtc* pFormatList = NULL;
SCODE sc = E_OUTOFMEMORY;
TRY
{
// generate a format list from the cache
pFormatList = new CEnumFormatEtc;
for (UINT nIndex = 0; nIndex < pThis->m_nSize; nIndex++)
{
AFX_DATACACHE_ENTRY* pCache = &pThis->m_pDataCache[nIndex];
if ((DWORD)pCache->m_nDataDir & dwDirection)
{
// entry should be enumerated -- add it to the list
FORMATETC formatEtc;
_AfxOleCopyFormatEtc(&formatEtc, &pCache->m_formatEtc);
pFormatList->AddFormat(&formatEtc);
}
}
// give it away to OLE (ref count is already 1)
*ppenumFormatEtc = (LPENUMFORMATETC)&pFormatList->m_xEnumVOID;
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP COleDataSource::XDataObject::DAdvise(
FORMATETC* /*pFormatetc*/, DWORD /*advf*/,
LPADVISESINK /*pAdvSink*/, DWORD* pdwConnection)
{
*pdwConnection = 0;
return OLE_E_ADVISENOTSUPPORTED;
}
STDMETHODIMP COleDataSource::XDataObject::DUnadvise(DWORD /*dwConnection*/)
{
return OLE_E_ADVISENOTSUPPORTED;
}
STDMETHODIMP COleDataSource::XDataObject::EnumDAdvise(
LPENUMSTATDATA* ppenumAdvise)
{
*ppenumAdvise = NULL;
return OLE_E_ADVISENOTSUPPORTED;
}
/////////////////////////////////////////////////////////////////////////////
// COleDataSource diagnostics
#ifdef _DEBUG
void COleDataSource::AssertValid() const
{
CCmdTarget::AssertValid();
ASSERT(m_nSize <= m_nMaxSize);
ASSERT(m_nMaxSize != 0 || m_pDataCache == NULL);
}
void COleDataSource::Dump(CDumpContext& dc) const
{
CCmdTarget::Dump(dc);
dc << "m_nMaxSize = " << m_nMaxSize;
dc << "\nm_nSize = " << m_nSize;
dc << "\nm_pDataCache = " << m_pDataCache;
for (UINT n = 0; n < m_nSize; n++)
{
dc << "\n\tentry [" << n << "] = {";
AFX_DATACACHE_ENTRY& rEntry = m_pDataCache[n];
dc << "\n\t m_formatEtc.cfFormat = " << rEntry.m_formatEtc.cfFormat;
dc << "\n\t m_formatEtc.pdt = " << rEntry.m_formatEtc.ptd;
dc << "\n\t m_formatEtc.dwAspect = " << rEntry.m_formatEtc.dwAspect;
dc << "\n\t m_formatEtc.lindex = " << rEntry.m_formatEtc.lindex;
dc << "\n\t m_formatEtc.tymed = " << rEntry.m_formatEtc.tymed;
dc << "\n\t m_stgMedium.tymed = " << rEntry.m_stgMedium.tymed;
dc << "\n\t m_nDataDir = " << (UINT)rEntry.m_nDataDir;
dc << "\n\t}";
}
dc << "\n";
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -