⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oledobj2.cpp

📁 vc6.0完整版
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"

#ifdef AFX_OLE3_SEG
#pragma code_seg(AFX_OLE3_SEG)
#endif

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define new DEBUG_NEW

/////////////////////////////////////////////////////////////////////////////
// COleDataSource implementation

struct AFX_DATACACHE_ENTRY
{
	FORMATETC m_formatEtc;
	STGMEDIUM m_stgMedium;
	DATADIR m_nDataDir;
};

/////////////////////////////////////////////////////////////////////////////
// COleDataSource construction & destruction

COleDataSource::COleDataSource()
{
	m_pDataCache = NULL;
	m_nMaxSize = 0;
	m_nSize = 0;
	m_nGrowBy = 10;
}

COleDataSource::~COleDataSource()
{
	// clear clipboard source if this object was on the clipboard
	_AFX_OLE_STATE* pOleState = _afxOleState;
	if (this == pOleState->m_pClipboardSource)
		pOleState->m_pClipboardSource = NULL;

	// free the clipboard data cache
	Empty();
}

void COleDataSource::Empty()
{
	if (m_pDataCache != NULL)
	{
		ASSERT(m_nMaxSize != 0);
		ASSERT(m_nSize != 0);

		// release all of the STGMEDIUMs and FORMATETCs
		for (UINT nIndex = 0; nIndex < m_nSize; nIndex++)
		{
			CoTaskMemFree(m_pDataCache[nIndex].m_formatEtc.ptd);
			::ReleaseStgMedium(&m_pDataCache[nIndex].m_stgMedium);
		}

		// delete the cache
		delete[] m_pDataCache;
		m_pDataCache = NULL;
		m_nMaxSize = 0;
		m_nSize = 0;
	}
	ASSERT(m_pDataCache == NULL);
	ASSERT(m_nMaxSize == 0);
	ASSERT(m_nSize == 0);
}

/////////////////////////////////////////////////////////////////////////////
// COleDataSource clipboard API wrappers

void COleDataSource::SetClipboard()
{
	ASSERT_VALID(this);

	// attempt OLE set clipboard operation
	LPDATAOBJECT lpDataObject = (LPDATAOBJECT)GetInterface(&IID_IDataObject);
	SCODE sc = ::OleSetClipboard(lpDataObject);
	if (sc != S_OK)
		AfxThrowOleException(sc);

	// success - set as current clipboard source
	_afxOleState->m_pClipboardSource = this;
	ASSERT(::OleIsCurrentClipboard(lpDataObject) == S_OK);
	InternalRelease();
}

void PASCAL COleDataSource::FlushClipboard()
{
	if (GetClipboardOwner() != NULL)
	{
		// active clipboard source and it is on the clipboard - flush it
		::OleFlushClipboard();

		// shouldn't be clipboard owner any more...
		ASSERT(GetClipboardOwner() == NULL);
	}
}

COleDataSource* PASCAL COleDataSource::GetClipboardOwner()
{
	_AFX_OLE_STATE* pOleState = _afxOleState;
	if (pOleState->m_pClipboardSource == NULL)
		return NULL;    // can't own the clipboard if pClipboardSource isn't set

	ASSERT_VALID(pOleState->m_pClipboardSource);
	LPDATAOBJECT lpDataObject = (LPDATAOBJECT)
		pOleState->m_pClipboardSource->GetInterface(&IID_IDataObject);
	if (::OleIsCurrentClipboard(lpDataObject) != S_OK)
	{
		pOleState->m_pClipboardSource = NULL;
		return NULL;    // don't own the clipboard anymore
	}

	// return current clipboard source
	return pOleState->m_pClipboardSource;
}

/////////////////////////////////////////////////////////////////////////////
// COleDataSource cache allocation

AFX_DATACACHE_ENTRY* COleDataSource::GetCacheEntry(
	LPFORMATETC lpFormatEtc, DATADIR nDataDir)
{
	AFX_DATACACHE_ENTRY* pEntry = Lookup(lpFormatEtc, nDataDir);
	if (pEntry != NULL)
	{
		// cleanup current entry and return it
		CoTaskMemFree(pEntry->m_formatEtc.ptd);
		::ReleaseStgMedium(&pEntry->m_stgMedium);
	}
	else
	{
		// allocate space for item at m_nSize (at least room for 1 item)
		if (m_pDataCache == NULL || m_nSize == m_nMaxSize)
		{
			ASSERT(m_nGrowBy != 0);
			AFX_DATACACHE_ENTRY* pCache = new AFX_DATACACHE_ENTRY[m_nMaxSize+m_nGrowBy];
			m_nMaxSize += m_nGrowBy;
			if (m_pDataCache != NULL)
			{
				memcpy(pCache, m_pDataCache, m_nSize * sizeof(AFX_DATACACHE_ENTRY));
				delete[] m_pDataCache;
			}
			m_pDataCache = pCache;
		}
		ASSERT(m_pDataCache != NULL);
		ASSERT(m_nMaxSize != 0);

		pEntry = &m_pDataCache[m_nSize++];
	}

	// fill the cache entry with the format and data direction and return it
	pEntry->m_nDataDir = nDataDir;
	pEntry->m_formatEtc = *lpFormatEtc;
	return pEntry;
}

/////////////////////////////////////////////////////////////////////////////
// COleDataSource operations

// for HGLOBAL based cached render
void COleDataSource::CacheGlobalData(CLIPFORMAT cfFormat, HGLOBAL hGlobal,
	LPFORMATETC lpFormatEtc)
{
	ASSERT(hGlobal != NULL);
	ASSERT(lpFormatEtc == NULL ||
		AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));

	// fill in FORMATETC struct
	FORMATETC formatEtc;
	lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
	lpFormatEtc->tymed = TYMED_HGLOBAL;

	// add it to the cache
	AFX_DATACACHE_ENTRY* pEntry = GetCacheEntry(lpFormatEtc, DATADIR_GET);
	pEntry->m_stgMedium.tymed = TYMED_HGLOBAL;
	pEntry->m_stgMedium.hGlobal = hGlobal;
	pEntry->m_stgMedium.pUnkForRelease = NULL;
}

// for raw LPSTGMEDIUM cached render
void COleDataSource::CacheData(CLIPFORMAT cfFormat, LPSTGMEDIUM lpStgMedium,
	LPFORMATETC lpFormatEtc)
{
	ASSERT(lpStgMedium == NULL || lpStgMedium->tymed != TYMED_NULL);
	ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM), FALSE));
	ASSERT(lpFormatEtc == NULL ||
		AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));

	// fill in FORMATETC struct
	FORMATETC formatEtc;
	lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);

	// Only these TYMED_GDI formats can be copied, so can't serve as
	//  cache content (you must use DelayRenderData instead)
	// When using COleServerItem::CopyToClipboard this means providing an
	//  override of COleServerItem::OnGetClipboardData to provide a custom
	//  delayed rendering clipboard object.
	ASSERT(lpStgMedium->tymed != TYMED_GDI ||
		lpFormatEtc->cfFormat == CF_METAFILEPICT ||
		lpFormatEtc->cfFormat == CF_PALETTE ||
		lpFormatEtc->cfFormat == CF_BITMAP);
	lpFormatEtc->tymed = lpStgMedium->tymed;

	// add it to the cache
	AFX_DATACACHE_ENTRY* pEntry = GetCacheEntry(lpFormatEtc, DATADIR_GET);
	pEntry->m_stgMedium = *lpStgMedium;
}

// for CFile* based delayed render
void COleDataSource::DelayRenderFileData(CLIPFORMAT cfFormat,
	LPFORMATETC lpFormatEtc)
{
	ASSERT(lpFormatEtc == NULL ||
		AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));

	// fill in FORMATETC struct
	FORMATETC formatEtc;
	lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
	lpFormatEtc->tymed |= TYMED_ISTREAM|TYMED_HGLOBAL;

	// add it to the cache
	AFX_DATACACHE_ENTRY* pEntry = GetCacheEntry(lpFormatEtc, DATADIR_GET);
	pEntry->m_stgMedium.tymed = TYMED_NULL;
	pEntry->m_stgMedium.hGlobal = NULL;
	pEntry->m_stgMedium.pUnkForRelease = NULL;
}

// for LPSTGMEDIUM or HGLOBAL based delayed render
void COleDataSource::DelayRenderData(CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
{
	ASSERT(lpFormatEtc == NULL ||
		AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));

	// fill in FORMATETC struct
	FORMATETC formatEtc;
	if (lpFormatEtc == NULL)
	{
		lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
		lpFormatEtc->tymed = TYMED_HGLOBAL;
	}
	// insure that cfFormat member is set
	if (cfFormat != 0)
		lpFormatEtc->cfFormat = cfFormat;

	// add it to the cache
	AFX_DATACACHE_ENTRY* pEntry = GetCacheEntry(lpFormatEtc, DATADIR_GET);
	memset(&pEntry->m_stgMedium, 0, sizeof pEntry->m_stgMedium);
}

// DelaySetData -- used to allow SetData on given LPFORMATETC
void COleDataSource::DelaySetData(CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
{
	ASSERT(lpFormatEtc == NULL ||
		AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));

	// fill in FORMATETC struct
	FORMATETC formatEtc;
	lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);

	// add it to the cache
	AFX_DATACACHE_ENTRY* pEntry = GetCacheEntry(lpFormatEtc, DATADIR_SET);
	pEntry->m_stgMedium.tymed = TYMED_NULL;
	pEntry->m_stgMedium.hGlobal = NULL;
	pEntry->m_stgMedium.pUnkForRelease = NULL;
}

/////////////////////////////////////////////////////////////////////////////
// COleDataSource cache implementation

AFX_DATACACHE_ENTRY* COleDataSource::Lookup(
	LPFORMATETC lpFormatEtc, DATADIR nDataDir) const
{
	AFX_DATACACHE_ENTRY* pLast = NULL;

	// look for suitable match to lpFormatEtc in cache
	for (UINT nIndex = 0; nIndex < m_nSize; nIndex++)
	{
		// get entry from cache at nIndex
		AFX_DATACACHE_ENTRY* pCache = &m_pDataCache[nIndex];
		FORMATETC *pCacheFormat = &pCache->m_formatEtc;

		// check for match
		if (pCacheFormat->cfFormat == lpFormatEtc->cfFormat &&
			(pCacheFormat->tymed & lpFormatEtc->tymed) != 0 &&
			(pCache->m_stgMedium.tymed == TYMED_NULL ||
				pCacheFormat->lindex == lpFormatEtc->lindex) &&
			pCacheFormat->dwAspect == lpFormatEtc->dwAspect &&
			pCache->m_nDataDir == nDataDir)
		{
			// for backward compatibility we match even if we never
			// find an exact match for the DVTARGETDEVICE
			pLast = pCache;
			DVTARGETDEVICE* ptd1 = pCacheFormat->ptd;
			DVTARGETDEVICE* ptd2 = lpFormatEtc->ptd;

			if (ptd1 == NULL && ptd2 == NULL)
			{
				// both target devices are NULL (exact match), so return it
				break;
			}
			if (ptd1 != NULL && ptd2 != NULL &&
				ptd1->tdSize == ptd2->tdSize &&
				memcmp(ptd1, ptd2, ptd1->tdSize) == 0)
			{
				// exact match, so return it
				break;
			}
			// continue looking for better match
		}
	}

	return pLast;    // not found
}

/////////////////////////////////////////////////////////////////////////////
// COleDataSource overidable default implementation

BOOL COleDataSource::OnRenderGlobalData(
	LPFORMATETC /*lpFormatEtc*/, HGLOBAL* /*phGlobal*/)
{
	return FALSE;   // default does nothing
}

BOOL COleDataSource::OnRenderFileData(
	LPFORMATETC /*lpFormatEtc*/, CFile* /*pFile*/)
{
	return FALSE;   // default does nothing
}

BOOL COleDataSource::OnRenderData(
	LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
{
	// attempt TYMED_HGLOBAL as prefered format
	if (lpFormatEtc->tymed & TYMED_HGLOBAL)
	{
		// attempt HGLOBAL delay render hook
		HGLOBAL hGlobal = lpStgMedium->hGlobal;
		if (OnRenderGlobalData(lpFormatEtc, &hGlobal))
		{
			ASSERT(lpStgMedium->tymed != TYMED_HGLOBAL ||
				(lpStgMedium->hGlobal == hGlobal));
			ASSERT(hGlobal != NULL);
			lpStgMedium->tymed = TYMED_HGLOBAL;
			lpStgMedium->hGlobal = hGlobal;
			return TRUE;
		}

		// attempt CFile* based delay render hook
		CSharedFile file;
		if (lpStgMedium->tymed == TYMED_HGLOBAL)
		{
			ASSERT(lpStgMedium->hGlobal != NULL);
			file.SetHandle(lpStgMedium->hGlobal, FALSE);
		}
		if (OnRenderFileData(lpFormatEtc, &file))
		{
			lpStgMedium->tymed = TYMED_HGLOBAL;
			lpStgMedium->hGlobal = file.Detach();
			ASSERT(lpStgMedium->hGlobal != NULL);
			return TRUE;
		}
		if (lpStgMedium->tymed == TYMED_HGLOBAL)
			file.Detach();
	}

	// attempt TYMED_ISTREAM format

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -