📄 olecli1.cpp
字号:
// user is also in control of the application, when a file-based
// document becomes visible.
AfxOleSetUserCtrl(TRUE);
}
}
/////////////////////////////////////////////////////////////////////////////
// COleClientItem - attributes
void COleClientItem::GetClassID(CLSID* pClassID) const
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
ASSERT(AfxIsValidAddress(pClassID, sizeof(CLSID)));
if (m_lpObject->GetUserClassID(pClassID) != S_OK)
*pClassID = CLSID_NULL;
}
BOOL COleClientItem::GetExtent(LPSIZE lpSize, DVASPECT nDrawAspect)
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
ASSERT(AfxIsValidAddress(lpSize, sizeof(CSize)));
// use current default aspect if specific one not specified
if (nDrawAspect == -1)
nDrawAspect = m_nDrawAspect;
// get the extent
m_scLast = m_lpObject->GetExtent(nDrawAspect, lpSize);
return m_scLast == S_OK;
}
BOOL COleClientItem::GetCachedExtent(LPSIZE lpSize, DVASPECT nDrawAspect)
{
ASSERT_VALID(this);
ASSERT(m_lpViewObject != NULL);
ASSERT(AfxIsValidAddress(lpSize, sizeof(CSize)));
// use current default aspect if specific one not specified
if (nDrawAspect == -1)
nDrawAspect = m_nDrawAspect;
COleDocument* pDoc = (COleDocument*)GetDocument();
ASSERT_VALID(pDoc);
// get the extent
m_scLast = m_lpViewObject->GetExtent(nDrawAspect, -1, pDoc->m_ptd, lpSize);
return m_scLast == S_OK;
}
BOOL COleClientItem::SetIconicMetafile(HGLOBAL hMetaPict)
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
// get IOleCache interface
LPOLECACHE lpOleCache = QUERYINTERFACE(m_lpObject, IOleCache);
if (lpOleCache == NULL)
{
TRACE0("Warning: object does not support IOleCache interface.\n");
return FALSE;
}
ASSERT(lpOleCache != NULL);
// new cache is for CF_METAFILEPICT, DVASPECT_ICON
FORMATETC formatEtc;
formatEtc.cfFormat = CF_METAFILEPICT;
formatEtc.ptd = NULL;
formatEtc.dwAspect = DVASPECT_ICON;
formatEtc.lindex = -1;
formatEtc.tymed = TYMED_MFPICT;
// setup the cache so iconic aspect is now included
DWORD dwConnection;
SCODE sc = lpOleCache->Cache(&formatEtc,
ADVF_NODATA|ADVF_PRIMEFIRST|ADVF_ONLYONCE, &dwConnection);
if (FAILED(sc))
{
lpOleCache->Release();
return FALSE;
}
// set data if iconic image provided
if (hMetaPict != NULL)
{
STGMEDIUM stgMedium;
stgMedium.tymed = TYMED_MFPICT;
stgMedium.hGlobal = hMetaPict;
stgMedium.pUnkForRelease = NULL;
sc = lpOleCache->SetData(&formatEtc, &stgMedium, FALSE);
if (FAILED(sc))
{
lpOleCache->Release();
return FALSE;
}
}
lpOleCache->Release();
return TRUE;
}
HGLOBAL COleClientItem::GetIconicMetafile()
{
USES_CONVERSION;
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
// get IDataObject interface
LPDATAOBJECT lpDataObject = QUERYINTERFACE(m_lpObject, IDataObject);
ASSERT(lpDataObject != NULL);
// cache is for CF_METAFILEPICT, DVASPECT_ICON
FORMATETC formatEtc;
formatEtc.cfFormat = CF_METAFILEPICT;
formatEtc.ptd = NULL;
formatEtc.dwAspect = DVASPECT_ICON;
formatEtc.lindex = -1;
formatEtc.tymed = TYMED_MFPICT;
// attempt to get the icon picture
STGMEDIUM stgMedium;
if (lpDataObject->GetData(&formatEtc, &stgMedium) != S_OK)
{
lpDataObject->Release();
// no current picture, attempt to get from class ID
CLSID clsid;
if (m_lpObject->GetUserClassID(&clsid) != S_OK)
return NULL;
TCHAR szTemp[_MAX_PATH];
LPTSTR lpszLabel = NULL;
if (GetType() == OT_LINK)
{
// it is a link, attempt to get link name
LPOLELINK lpOleLink = QUERYINTERFACE(m_lpObject, IOleLink);
if (lpOleLink != NULL)
{
LPOLESTR lpszDisplayName = NULL;
lpOleLink->GetSourceDisplayName(&lpszDisplayName);
if (lpszDisplayName != NULL)
{
szTemp[0] = 0;
AfxGetFileTitle(OLE2CT(lpszDisplayName), szTemp, _countof(szTemp));
if (szTemp[0] != '\0')
lpszLabel = szTemp;
CoTaskMemFree(lpszDisplayName);
}
lpOleLink->Release();
}
}
HGLOBAL hMetaPict = OleGetIconOfClass(clsid, T2OLE(lpszLabel), lpszLabel == NULL);
if (hMetaPict != NULL)
{
// cache it for later GetData (or drawing)
SetIconicMetafile(hMetaPict);
return hMetaPict;
}
return NULL;
}
lpDataObject->Release();
// can't handle data where punkForRelease is set
if (stgMedium.pUnkForRelease != NULL)
{
::ReleaseStgMedium(&stgMedium);
return NULL;
}
ASSERT(stgMedium.tymed == TYMED_MFPICT);
ASSERT(stgMedium.hGlobal != NULL);
return stgMedium.hGlobal; // return HGLOBAL to METAFILEPICT
}
void COleClientItem::SetDrawAspect(DVASPECT nDrawAspect)
{
ASSERT_VALID(this);
// prime iconic cache (in case object has never displayed iconic)
if (nDrawAspect == DVASPECT_ICON)
{
SetIconicMetafile(NULL); // allow object to provide own icon
HGLOBAL hMetaPict = GetIconicMetafile();
_AfxDeleteMetafilePict(hMetaPict);
}
// Note: the aspect you are setting may be uncached and therefore blank.
// To make sure it is cached use SetIconPicture or use IOleCache to
// set the cache yourself.
m_nDrawAspect = nDrawAspect;
// mark document as dirty (m_nDrawAspect is part of persistent state)
ASSERT_VALID(m_pDocument);
m_pDocument->SetModifiedFlag();
}
// Helper used to get the DVTARGETDEVICE pointer for the first printer.
BOOL COleClientItem::GetPrintDeviceInfo(
LPOLECACHE* plpOleCache, DVTARGETDEVICE** pptd, DWORD* pdwConnection)
{
*plpOleCache = NULL;
*pptd = NULL;
// get IOleCache interface
LPOLECACHE lpOleCache = QUERYINTERFACE(m_lpObject, IOleCache);
if (lpOleCache == NULL)
{
TRACE0("Warning: object does not support IOleCache interface.\n");
return FALSE; // no cache -- no possible print device
}
ASSERT(lpOleCache != NULL);
// get enumerator for the cache
LPENUMSTATDATA lpEnumSTATDATA;
if (lpOleCache->EnumCache(&lpEnumSTATDATA) != S_OK || lpEnumSTATDATA == NULL)
{
lpOleCache->Release();
return FALSE;
}
// enumerate entries in the cache (look for one with ptd != NULL)
STATDATA statData;
while (lpEnumSTATDATA->Next(1, &statData, NULL) == S_OK)
{
ASSERT(statData.pAdvSink == NULL);
// return first non-NULL ptd (we assume this is a printer cache)
if (statData.formatetc.ptd != NULL)
{
if (pdwConnection != NULL)
*pdwConnection = statData.dwConnection;
*pptd = statData.formatetc.ptd;
lpEnumSTATDATA->Release();
*plpOleCache = lpOleCache;
return TRUE; // Note: lpOleCache pointer is still alive
}
}
// release interfaces
lpEnumSTATDATA->Release();
lpOleCache->Release();
return FALSE; // data not found
}
void COleClientItem::AttachDataObject(COleDataObject& rDataObject) const
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
// get the IDataObject interface for the item
LPDATAOBJECT lpDataObject = QUERYINTERFACE(m_lpObject, IDataObject);
ASSERT(lpDataObject != NULL);
// return it by attaching it
rDataObject.Attach(lpDataObject, TRUE);
}
/////////////////////////////////////////////////////////////////////////////
// COleClientItem - general operations
BOOL COleClientItem::Draw(CDC* pDC, LPCRECT lpBounds, DVASPECT nDrawAspect)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(lpBounds, sizeof(RECT), FALSE));
ASSERT_VALID(pDC);
if (m_lpObject == NULL || m_lpViewObject == NULL)
return FALSE; // partially created COleClientItem object
// use current draw aspect if aspect is -1 (default)
if (nDrawAspect == -1)
nDrawAspect = m_nDrawAspect;
// convert RECT lpBounds to RECTL rclBounds
RECTL rclBounds;
rclBounds.left = lpBounds->left;
rclBounds.top = lpBounds->top;
rclBounds.right = lpBounds->right;
rclBounds.bottom = lpBounds->bottom;
// get RECTL describing window extents and origin
RECTL rclWBounds;
CPoint ptOrg = pDC->GetWindowOrg();
CSize sizeExt = pDC->GetWindowExt();
rclWBounds.left = ptOrg.x;
rclWBounds.top = ptOrg.y;
rclWBounds.right = sizeExt.cx;
rclWBounds.bottom = sizeExt.cy;
// get target device to use for draw
COleDocument* pDoc = GetDocument();
const DVTARGETDEVICE* ptd = NULL;
HDC hdcTarget = NULL;
if (pDC->IsPrinting() && pDoc->m_ptd != NULL)
{
ptd = pDoc->m_ptd;
hdcTarget = pDC->m_hAttribDC;
}
// attempt draw with target device
SCODE sc = m_lpViewObject->Draw(nDrawAspect, -1, NULL,
(DVTARGETDEVICE*)ptd, hdcTarget, pDC->m_hDC,
&rclBounds, &rclWBounds, NULL, 0);
if (ptd != NULL && sc == OLE_E_BLANK)
{
// attempt draw without target device
sc = m_lpViewObject->Draw(nDrawAspect, -1, NULL,
NULL, NULL, pDC->m_hDC,
&rclBounds, &rclWBounds, NULL, 0);
}
if (sc != S_OK && sc == OLE_E_BLANK)
return FALSE; // return FALSE if the object is blank
CheckGeneral(sc); // otherwise, may throw exception on error
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// COleClientItem clipboard helpers
void COleClientItem::GetEmbeddedItemData(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);
lpLockBytes->Release();
// save the object into the storage
LPPERSISTSTORAGE lpPersistStorage =
QUERYINTERFACE(m_lpObject, IPersistStorage);
ASSERT(lpPersistStorage != NULL);
sc = ::OleSave(lpPersistStorage, lpStorage, FALSE);
lpPersistStorage->SaveCompleted(NULL);
lpPersistStorage->Release();
if (sc != S_OK)
{
VERIFY(lpStorage->Release() == 0);
AfxThrowOleException(sc);
}
// add it to the data source
lpStgMedium->tymed = TYMED_ISTORAGE;
lpStgMedium->pstg = lpStorage;
lpStgMedium->pUnkForRelease = NULL;
}
void COleClientItem::AddCachedData(COleDataSource* pDataSource)
{
ASSERT_VALID(this);
ASSERT_VALID(pDataSource);
// get IOleCache interface
LPOLECACHE lpOleCache = QUERYINTERFACE(m_lpObject, IOleCache);
if (lpOleCache == NULL)
{
TRACE0("Warning: object does not support IOleCache interface.\n");
return;
}
ASSERT(lpOleCache != NULL);
// Get IEnumSTATDATA interface for IOleCache
LPENUMSTATDATA lpEnumSTATDATA;
if (lpOleCache->EnumCache(&lpEnumSTATDATA) != S_OK || lpEnumSTATDATA == NULL)
{
lpOleCache->Release();
return;
}
// get IDataObject interface
LPDATAOBJECT lpDataObject = QUERYINTERFACE(m_lpObject, IDataObject);
ASSERT(lpDataObject != NULL);
// enumerate all of the cached formats
STATDATA statData;
while (lpEnumSTATDATA->Next(1, &statData, NULL) == S_OK)
{
ASSERT(statData.pAdvSink == NULL);
// for each format supported, attempt to get copy of the data
STGMEDIUM stgMedium;
if (lpDataObject->GetData(&statData.formatetc, &stgMedium) != S_OK)
{
// data is not available
CoTaskMemFree(statData.formatetc.ptd);
}
else if (stgMedium.pUnkForRelease != NULL)
{
// don't cache data with pUnkForRelease != NULL
::ReleaseStgMedium(&stgMedium);
CoTaskMemFree(statData.formatetc.ptd);
}
else
{
// format was acceptable -- add it to the clipboard
pDataSource->CacheData(0, &stgMedium, &statData.formatetc);
}
}
// release interfaces
lpEnumSTATDATA->Release();
lpDataObject->Release();
lpOleCache->Release();
}
BOOL COleClientItem::GetLinkSourceData(LPSTGMEDIUM lpStgMedium)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
LPMONIKER lpMoniker = NULL;
LPOLELINK lpOleLink = QUERYINTERFACE(m_lpObject, IOleLink);
if (lpOleLink == NULL)
{
// get moniker from client site
LPOLECLIENTSITE lpClientSite = GetClientSite();
ASSERT(lpClientSite != NULL);
SCODE sc = lpClientSite->GetMoniker(OLEGETMONIKER_TEMPFORUSER,
OLEWHICHMK_OBJFULL, &lpMoniker);
if (sc != S_OK)
{
TRACE0("Warning: unable to get moniker from client site.\n");
return FALSE;
}
ASSERT(lpMoniker != NULL);
}
else
{
// get moniker from the link object itself
SCODE sc = lpOleLink->GetSourceMoniker(&lpMoniker);
lpOleLink->Release();
if (sc != S_OK)
{
TRACE0("Warning: unable to get moniker from link source.\n");
return FALSE;
}
ASSERT(lpMoniker != NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -