📄 olesvr2.cpp
字号:
if (lpRectStartDrag == NULL)
{
rectDrag.SetRect(lpItemRect->left, lpItemRect->top, lpItemRect->left,
lpItemRect->top);
lpRectStartDrag = &rectDrag;
}
// do drag drop operation
dropEffect = pDataSource->DoDragDrop(dwEffects, lpRectStartDrag);
pDataSource->InternalRelease();
}
CATCH_ALL(e)
{
if (pDataSource != NULL)
pDataSource->InternalRelease();
THROW_LAST();
}
END_CATCH_ALL
return dropEffect;
}
void COleServerItem::GetClipboardData(COleDataSource* pDataSource,
BOOL bIncludeLink, LPPOINT lpOffset, LPSIZE lpSize)
{
ASSERT_VALID(this);
ASSERT_VALID(pDataSource);
ASSERT(lpOffset == NULL ||
AfxIsValidAddress(lpOffset, sizeof(POINT), FALSE));
// add CF_EMBEDDEDOBJECT by creating memory storage copy of the object
STGMEDIUM stgMedium;
GetEmbedSourceData(&stgMedium);
pDataSource->CacheData((CLIPFORMAT)_oleData.cfEmbedSource, &stgMedium);
// add CF_OBJECTDESCRIPTOR
GetObjectDescriptorData(lpOffset, lpSize, &stgMedium);
pDataSource->CacheData((CLIPFORMAT)_oleData.cfObjectDescriptor,
&stgMedium);
// add any presentation entries/conversion formats that the item
// can produce.
AddOtherClipboardData(pDataSource);
// add CF_LINKSOURCE if supporting links to pseudo objects
if (bIncludeLink && GetLinkSourceData(&stgMedium))
{
pDataSource->CacheData((CLIPFORMAT)_oleData.cfLinkSource, &stgMedium);
// add CF_LINKSOURCEDESCRIPTOR
GetObjectDescriptorData(lpOffset, lpSize, &stgMedium);
pDataSource->CacheData((CLIPFORMAT)_oleData.cfLinkSourceDescriptor,
&stgMedium);
}
}
void COleServerItem::GetEmbedSourceData(LPSTGMEDIUM lpStgMedium)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
LPLOCKBYTES lpLockBytes;
SCODE sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
if (sc != S_OK)
AfxThrowOleException(sc);
ASSERT(lpLockBytes != NULL);
LPSTORAGE lpStorage;
sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,
STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &lpStorage);
if (sc != S_OK)
{
VERIFY(lpLockBytes->Release() == 0);
AfxThrowOleException(sc);
}
ASSERT(lpStorage != NULL);
// setup for save copy as
COleServerDoc* pDoc = GetDocument();
pDoc->m_bSameAsLoad = FALSE;
pDoc->m_bRemember = FALSE;
TRY
{
OnSaveEmbedding(lpStorage);
pDoc->CommitItems(FALSE);
}
CATCH_ALL(e)
{
// release storage and lock bytes
VERIFY(lpStorage->Release() == 0);
VERIFY(lpLockBytes->Release() == 0);
pDoc->m_bSameAsLoad = TRUE;
pDoc->m_bRemember = TRUE;
THROW_LAST();
}
END_CATCH_ALL
pDoc->m_bSameAsLoad = TRUE;
pDoc->m_bRemember = TRUE;
lpLockBytes->Release();
// add it to the data source
lpStgMedium->tymed = TYMED_ISTORAGE;
lpStgMedium->pstg = lpStorage;
lpStgMedium->pUnkForRelease = NULL;
}
void COleServerItem::AddOtherClipboardData(COleDataSource* pDataSource)
{
ASSERT_VALID(this);
ASSERT_VALID(pDataSource);
// get IEnumFORMATETC interface for the IDataObject
LPDATAOBJECT lpDataObject = GetDataObject();
LPENUMFORMATETC lpEnumFORMATETC;
if (lpDataObject->EnumFormatEtc(DATADIR_GET, &lpEnumFORMATETC) != S_OK)
return;
ASSERT(lpEnumFORMATETC != NULL);
// get all formats that the object will give us
FORMATETC formatEtc;
while (lpEnumFORMATETC->Next(1, &formatEtc, NULL) == S_OK)
{
STGMEDIUM stgMedium;
if (lpDataObject->GetData(&formatEtc, &stgMedium) != S_OK)
{
// data is not available
CoTaskMemFree(formatEtc.ptd);
}
else if (stgMedium.pUnkForRelease != NULL)
{
// don't cache data with pUnkForRelease != NULL
::ReleaseStgMedium(&stgMedium);
CoTaskMemFree(formatEtc.ptd);
}
else
{
// cache the data (now we own the stgMedium)
pDataSource->CacheData(0, &stgMedium, &formatEtc);
}
}
// cleanup
lpEnumFORMATETC->Release();
}
LPMONIKER COleServerItem::GetMoniker(OLEGETMONIKER nAssign)
{
// get IOleObject interface for this item
LPOLEOBJECT lpOleObject = GetOleObject();
ASSERT(lpOleObject != NULL);
// get moniker from OLE object
LPMONIKER lpMoniker = NULL;
lpOleObject->GetMoniker(nAssign, OLEWHICHMK_OBJFULL, &lpMoniker);
return lpMoniker;
}
BOOL COleServerItem::GetLinkSourceData(LPSTGMEDIUM lpStgMedium)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
LPOLEOBJECT lpOleObject = GetOleObject();
ASSERT(lpOleObject != NULL);
// get moniker from ole object
LPMONIKER lpMoniker;
SCODE sc = lpOleObject->GetMoniker(OLEGETMONIKER_TEMPFORUSER,
OLEWHICHMK_OBJFULL, &lpMoniker);
if (sc != S_OK)
{
TRACE0("Warning: unable to get moniker for object.\n");
return FALSE;
}
ASSERT(lpMoniker != NULL);
// create a memory based stream to write the moniker to
LPSTREAM lpStream;
if (::CreateStreamOnHGlobal(NULL, TRUE, &lpStream) != S_OK)
{
lpMoniker->Release();
AfxThrowMemoryException();
}
ASSERT(lpStream != NULL);
// write the moniker to the stream, and add it to the clipboard
sc = ::OleSaveToStream(lpMoniker, lpStream);
lpMoniker->Release();
if (sc != S_OK)
{
lpStream->Release();
AfxThrowOleException(sc);
}
// write the class ID of the document to the stream as well
COleLinkingDoc* pDoc = GetDocument();
ASSERT(pDoc->m_pFactory != NULL);
sc = WriteClassStm(lpStream, pDoc->m_pFactory->GetClassID());
if (sc != S_OK)
{
lpStream->Release();
AfxThrowOleException(sc);
}
// setup the STGMEDIUM
lpStgMedium->tymed = TYMED_ISTREAM;
lpStgMedium->pstm = lpStream;
lpStgMedium->pUnkForRelease = NULL;
return TRUE;
}
void COleServerItem::GetObjectDescriptorData(
LPPOINT lpOffset, LPSIZE lpSize, LPSTGMEDIUM lpStgMedium)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
ASSERT(lpOffset == NULL ||
AfxIsValidAddress(lpOffset, sizeof(POINT), FALSE));
LPOLEOBJECT lpOleObject = GetOleObject();
ASSERT(lpOleObject != NULL);
// get the object descriptor for the IOleObject
POINTL pointl = { 0, 0 };
if (lpOffset != NULL)
{
CSize ptOffset(lpOffset->x, lpOffset->y);
((CDC*)NULL)->DPtoHIMETRIC(&ptOffset);
pointl.x = ptOffset.cx;
pointl.y = ptOffset.cy;
}
SIZEL sizel;
if (lpSize != NULL)
{
sizel.cx = lpSize->cx;
sizel.cy = lpSize->cy;
((CDC*)NULL)->DPtoHIMETRIC(&sizel);
}
else
{
sizel.cx = 0;
sizel.cy = 0;
}
InterlockedIncrement(&m_dwRef); // protect against destruction during this call
HGLOBAL hGlobal = _AfxOleGetObjectDescriptorData(
lpOleObject, NULL, DVASPECT_CONTENT, pointl, &sizel);
InterlockedDecrement(&m_dwRef);
if (hGlobal == NULL)
AfxThrowMemoryException();
// setup the STGMEDIUM
lpStgMedium->tymed = TYMED_HGLOBAL;
lpStgMedium->hGlobal = hGlobal;
lpStgMedium->pUnkForRelease = NULL;
}
void COleServerItem::OnSaveEmbedding(LPSTORAGE lpStorage)
{
ASSERT(lpStorage != NULL);
// always (logically) a "File.Save Copy As" operation
COleServerDoc* pDoc = GetDocument();
LPSTORAGE lpOrigStg = pDoc->m_lpRootStg;
pDoc->m_lpRootStg = lpStorage;
TRY
{
ASSERT(pDoc->m_lpRootStg != NULL);
pDoc->SaveToStorage(this); // use helper to serialize to storage
}
CATCH_ALL(e)
{
// save as failed: re-attach original storage
pDoc->m_lpRootStg = lpOrigStg;
THROW_LAST();
}
END_CATCH_ALL
// re-attach original storage
pDoc->m_lpRootStg = lpOrigStg;
}
/////////////////////////////////////////////////////////////////////////////
// COleServerItem data-object callback default implementation
BOOL COleServerItem::OnRenderGlobalData(
LPFORMATETC /*lpFormatEtc*/, HGLOBAL* /*phGlobal*/)
{
ASSERT_VALID(this);
return FALSE; // default does nothing
}
BOOL COleServerItem::OnRenderFileData(
LPFORMATETC /*lpFormatEtc*/, CFile* /*pFile*/)
{
ASSERT_VALID(this);
return FALSE; // default does nothing
}
BOOL COleServerItem::OnRenderData(LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
// default implementation does not support extended layout
if (lpFormatEtc->lindex != -1)
return FALSE;
// default implementation supports both types of metafiles
if (lpFormatEtc->cfFormat == CF_METAFILEPICT)
return GetMetafileData(lpFormatEtc, lpStgMedium);
return FALSE; // cfFormat not supported
}
BOOL COleServerItem::OnSetData(
LPFORMATETC /*lpFormatEtc*/, LPSTGMEDIUM /*lpStgMedium*/, BOOL /*bRelease*/)
{
ASSERT_VALID(this);
return FALSE; // default does nothing
}
/////////////////////////////////////////////////////////////////////////////
// COleServerItem OLE interface implementation
BEGIN_INTERFACE_MAP(COleServerItem, CDocItem)
INTERFACE_PART(COleServerItem, IID_IOleObject, OleObject)
INTERFACE_PART(COleServerItem, IID_IDataObject, DataObject)
END_INTERFACE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COleServerItem::XOleObject
STDMETHODIMP_(ULONG) COleServerItem::XOleObject::AddRef()
{
METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) COleServerItem::XOleObject::Release()
{
METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
return pThis->ExternalRelease();
}
STDMETHODIMP COleServerItem::XOleObject::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
METHOD_PROLOGUE_EX_(COleServerItem, OleObject)
return pThis->ExternalQueryInterface(&iid, ppvObj);
}
// COleServerItem has special Release semantics. In particular, the item
// is only deleted from memory if m_bAutoDelete is TRUE.
// Also, it unlocks the document if the reference count reaches zero.
void COleServerItem::OnFinalRelease()
{
ASSERT_VALID(this);
COleServerDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDoc->InternalAddRef(); // make document stable
// if connected to a document -- remove external lock from it
if (m_bNeedUnlock)
{
pDoc->LockExternal(FALSE, TRUE);
m_bNeedUnlock = FALSE;
}
// delete this item if no longer needed
if (m_bAutoDelete)
delete this;
// release artificial reference (may destroy the document)
pDoc->InternalRelease();
}
STDMETHODIMP COleServerItem::XOleObject::SetClientSite(
LPOLECLIENTSITE /*pClientSite*/)
{
// linked objects do not support SetClientSite
return E_NOTIMPL;
}
STDMETHODIMP COleServerItem::XOleObject::GetClientSite(
LPOLECLIENTSITE* ppClientSite)
{
// linked objects do not support GetClientSite
*ppClientSite = NULL;
return E_NOTIMPL;
}
STDMETHODIMP COleServerItem::XOleObject::SetHostNames(
LPCOLESTR /*szContainerApp*/, LPCOLESTR /*szContainerObj*/)
{
// linked objects do not support SetHostNames
return E_NOTIMPL;
}
STDMETHODIMP COleServerItem::XOleObject::Close(DWORD /*dwSaveOption*/)
{
// linked objects do not support close
return E_NOTIMPL;
}
STDMETHODIMP COleServerItem::XOleObject::SetMoniker(
DWORD /*dwWhichMoniker*/, LPMONIKER /*pmk*/)
{
// linked objects do not support SetMoniker
return E_NOTIMPL;
}
STDMETHODIMP COleServerItem::XOleObject::GetMoniker(
DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER* ppMoniker)
{
USES_CONVERSION;
METHOD_PROLOGUE_EX(COleServerItem, OleObject)
ASSERT_VALID(pThis);
COleServerDoc* pDoc = pThis->GetDocument();
ASSERT_VALID(pDoc);
ASSERT_KINDOF(COleServerDoc, pDoc);
ASSERT(ppMoniker != NULL);
*ppMoniker = NULL;
switch (dwWhichMoniker)
{
case OLEWHICHMK_CONTAINER:
// simply return the moniker of the container document
*ppMoniker = pDoc->GetMoniker((OLEGETMONIKER)dwAssign);
break;
case OLEWHICHMK_OBJREL:
{
// no relative moniker if no item name
if (pThis->m_strItemName.IsEmpty())
break;
// don't return relative moniker if no document moniker
LPMONIKER lpMoniker = pDoc->GetMoniker((OLEGETMONIKER)dwAssign);
if (lpMoniker == NULL)
break;
lpMoniker->Release(); // don't need document moniker
// relative monikers have to handle assignment correctly
switch (dwAssign)
{
case OLEGETMONIKER_TEMPFORUSER:
case OLEGETMONIKER_ONLYIFTHERE:
case OLEGETMONIKER_FORCEASSIGN:
// create item moniker from name
CreateItemMoniker(OLESTDDELIMOLE, T2COLE(pThis->m_strItemName),
ppMoniker);
break;
case OLEGETMONIKER_UNASSIGN:
ASSERT(FALSE); // should never get UNASSIGN
break;
}
}
break;
case OLEWHICHMK_OBJFULL:
{
// get each sub-moniker: item & document
LPMONIKER lpMoniker1, lpMoniker2;
GetMoniker(dwAssign, OLEWHICHMK_CONTAINER, &lpMoniker1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -