mirror of https://github.com/lianthony/NT4.0
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.
683 lines
17 KiB
683 lines
17 KiB
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 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_OLE_SEG
|
|
#pragma code_seg(AFX_OLE_SEG)
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleClientItem activation
|
|
|
|
// helper to get client site -- this is called from a number of places
|
|
LPOLECLIENTSITE COleClientItem::GetClientSite()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
LPOLECLIENTSITE lpClientSite =
|
|
(LPOLECLIENTSITE)GetInterface(&IID_IOleClientSite);
|
|
ASSERT(lpClientSite != NULL);
|
|
return lpClientSite;
|
|
}
|
|
|
|
void COleClientItem::Activate(LONG nVerb, CView* pView, LPMSG lpMsg)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_lpObject != NULL);
|
|
if (pView != NULL)
|
|
ASSERT_VALID(pView);
|
|
if (lpMsg != NULL)
|
|
ASSERT(AfxIsValidAddress(lpMsg, sizeof(MSG), FALSE));
|
|
|
|
// store the container HWND for in place activation then do the verb
|
|
if (m_pView == NULL)
|
|
m_pView = pView;
|
|
|
|
_AFX_OLE_STATE* pOleState = _afxOleState;
|
|
CView* pViewSave = pOleState->m_pActivateView;
|
|
pOleState->m_pActivateView = NULL;
|
|
|
|
// get item rectangle for in-place players
|
|
// (that may not support in-place activation)
|
|
LPCRECT lpPosRect = NULL;
|
|
CRect rectPos;
|
|
if (pView != NULL)
|
|
{
|
|
ASSERT_VALID(pView);
|
|
rectPos.SetRectEmpty();
|
|
OnGetItemPosition(rectPos);
|
|
if (!rectPos.IsRectEmpty())
|
|
{
|
|
lpPosRect = &rectPos;
|
|
pOleState->m_pActivateView = pView;
|
|
}
|
|
}
|
|
|
|
// prepare DoVerb parameters and call into the server
|
|
LPOLECLIENTSITE lpClientSite = GetClientSite();
|
|
HWND hWnd = pView->GetSafeHwnd();
|
|
SCODE sc = m_lpObject->DoVerb(nVerb, lpMsg, lpClientSite, -1,
|
|
hWnd, lpPosRect);
|
|
|
|
pOleState->m_pActivateView = pViewSave;
|
|
|
|
// clear out m_pView in case in-place activation only partially worked
|
|
if (!IsInPlaceActive())
|
|
m_pView = NULL;
|
|
|
|
// update available status based on the results of DoVerb
|
|
// (this is used in the links dialog).
|
|
m_bLinkUnavail = (BYTE)FAILED(sc);
|
|
|
|
CheckGeneral(sc);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Create error handling
|
|
|
|
void COleClientItem::CheckGeneral(SCODE sc)
|
|
// set 'm_scLast'
|
|
// throw exception if not ok to continue
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
m_scLast = S_OK; // assume things are ok
|
|
|
|
// then, check for error
|
|
if (sc != S_OK)
|
|
{
|
|
m_scLast = sc;
|
|
if (!FAILED(sc))
|
|
{
|
|
#ifdef _DEBUG
|
|
// warn about non-NULL success codes
|
|
TRACE1("Warning: operation returned scode = %s.\n",
|
|
AfxGetFullScodeString(m_scLast));
|
|
#endif
|
|
return;
|
|
}
|
|
// this error wasn't expected, so throw an exception
|
|
AfxThrowOleException(sc);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleClientItem clipboard support
|
|
|
|
void COleClientItem::CopyToClipboard(BOOL bIncludeLink)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_lpObject != NULL);
|
|
|
|
// get clipboard data for this item
|
|
COleDataSource* pDataSource = OnGetClipboardData(bIncludeLink, NULL, NULL);
|
|
TRY
|
|
{
|
|
// put it on the clipboard
|
|
pDataSource->SetClipboard();
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
delete pDataSource;
|
|
THROW_LAST();
|
|
}
|
|
END_CATCH_ALL
|
|
}
|
|
|
|
COleDataSource* COleClientItem::OnGetClipboardData(
|
|
BOOL bIncludeLink, LPPOINT lpOffset, LPSIZE lpSize)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
COleDataSource* pDataSource = new COleDataSource;
|
|
TRY
|
|
{
|
|
GetClipboardData(pDataSource, bIncludeLink, lpOffset, lpSize);
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
delete pDataSource;
|
|
THROW_LAST();
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
ASSERT_VALID(pDataSource);
|
|
return pDataSource;
|
|
}
|
|
|
|
|
|
DROPEFFECT COleClientItem::DoDragDrop(LPCRECT lpItemRect, CPoint ptOffset,
|
|
BOOL bIncludeLink, DWORD dwEffects, LPCRECT lpRectStartDrag)
|
|
{
|
|
ASSERT(AfxIsValidAddress(lpItemRect, sizeof(RECT)));
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_lpObject != NULL);
|
|
|
|
DROPEFFECT dropEffect = DROPEFFECT_NONE;
|
|
COleDataSource *pDataSource = NULL;
|
|
TRY
|
|
{
|
|
// get clipboard data object for the item
|
|
CSize sizeItem(
|
|
lpItemRect->right - lpItemRect->left,
|
|
lpItemRect->bottom - lpItemRect->top);
|
|
pDataSource = OnGetClipboardData(bIncludeLink, &ptOffset, &sizeItem);
|
|
|
|
// add DROPEFFECT_LINK only if link source is available
|
|
LPDATAOBJECT lpDataObject = (LPDATAOBJECT)
|
|
pDataSource->GetInterface(&IID_IDataObject);
|
|
ASSERT(lpDataObject != NULL);
|
|
FORMATETC formatEtc;
|
|
formatEtc.cfFormat = (CLIPFORMAT)_oleData.cfLinkSource;
|
|
formatEtc.ptd = NULL;
|
|
formatEtc.dwAspect = DVASPECT_CONTENT;
|
|
formatEtc.lindex = -1;
|
|
formatEtc.tymed = (TYMED)-1;
|
|
if (lpDataObject->QueryGetData(&formatEtc) == S_OK)
|
|
dwEffects |= DROPEFFECT_LINK;
|
|
|
|
// calculate default sensitivity rectangle
|
|
CRect rectDrag;
|
|
if (lpRectStartDrag == NULL)
|
|
{
|
|
rectDrag.SetRect(lpItemRect->left, lpItemRect->bottom,
|
|
lpItemRect->left, lpItemRect->bottom);
|
|
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 COleClientItem::GetClipboardData(COleDataSource* pDataSource,
|
|
BOOL bIncludeLink, LPPOINT lpOffset, LPSIZE lpSize)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_lpObject != NULL);
|
|
ASSERT_VALID(pDataSource);
|
|
|
|
// add CF_EMBEDDEDOBJECT by creating memory storage copy of the object
|
|
STGMEDIUM stgMedium;
|
|
GetEmbeddedItemData(&stgMedium);
|
|
pDataSource->CacheData((CLIPFORMAT)_oleData.cfEmbeddedObject, &stgMedium);
|
|
|
|
// add CF_OBJECTDESCRIPTOR
|
|
GetObjectDescriptorData(lpOffset, lpSize, &stgMedium);
|
|
pDataSource->CacheData((CLIPFORMAT)_oleData.cfObjectDescriptor,
|
|
&stgMedium);
|
|
|
|
// add any presentation entries in the object's cache
|
|
AddCachedData(pDataSource);
|
|
|
|
// add CF_LINKSOURCE if supporting links to embeddings
|
|
if (bIncludeLink && GetLinkSourceData(&stgMedium))
|
|
{
|
|
pDataSource->CacheData((CLIPFORMAT)_oleData.cfLinkSource, &stgMedium);
|
|
|
|
// add CF_LINKSOURCEDESCRIPTOR
|
|
GetObjectDescriptorData(lpOffset, lpSize, &stgMedium);
|
|
pDataSource->CacheData((CLIPFORMAT)_oleData.cfLinkSourceDescriptor,
|
|
&stgMedium);
|
|
}
|
|
}
|
|
|
|
BOOL PASCAL COleClientItem::CanPaste()
|
|
{
|
|
if (afxData.bWin31)
|
|
{
|
|
// We must use OleQueryCreateFromData on Win32s
|
|
BOOL bCanPaste = FALSE;
|
|
LPDATAOBJECT lpDataObject;
|
|
if (::OleGetClipboard(&lpDataObject) == S_OK)
|
|
{
|
|
ASSERT(lpDataObject != NULL);
|
|
SCODE sc = GetScode(::OleQueryCreateFromData(lpDataObject));
|
|
bCanPaste = !FAILED(sc) && sc != S_FALSE;
|
|
lpDataObject->Release();
|
|
}
|
|
return bCanPaste;
|
|
}
|
|
else
|
|
{
|
|
// it is faster and more reliable to use the Windows clipboard
|
|
// APIs instead of OleQueryCreateFromData.
|
|
return IsClipboardFormatAvailable(_oleData.cfEmbedSource) ||
|
|
IsClipboardFormatAvailable(_oleData.cfEmbeddedObject) ||
|
|
IsClipboardFormatAvailable(_oleData.cfFileName) ||
|
|
IsClipboardFormatAvailable(_oleData.cfFileNameW) ||
|
|
IsClipboardFormatAvailable(CF_METAFILEPICT) ||
|
|
IsClipboardFormatAvailable(CF_DIB) ||
|
|
IsClipboardFormatAvailable(CF_BITMAP) ||
|
|
(IsClipboardFormatAvailable(_oleData.cfOwnerLink) &&
|
|
IsClipboardFormatAvailable(_oleData.cfNative));
|
|
}
|
|
}
|
|
|
|
BOOL PASCAL COleClientItem::CanPasteLink()
|
|
{
|
|
if (afxData.bWin31)
|
|
{
|
|
// We must use OleQueryLinkFromData on Win32s
|
|
BOOL bCanPasteLink = FALSE;
|
|
LPDATAOBJECT lpDataObject;
|
|
if (::OleGetClipboard(&lpDataObject) == S_OK)
|
|
{
|
|
ASSERT(lpDataObject != NULL);
|
|
SCODE sc = GetScode(::OleQueryLinkFromData(lpDataObject));
|
|
bCanPasteLink = !FAILED(sc) && sc != S_FALSE;
|
|
lpDataObject->Release();
|
|
}
|
|
return bCanPasteLink;
|
|
}
|
|
else
|
|
{
|
|
// it is faster and more reliable to use the Windows clipboard
|
|
// APIs instead of OleQueryCreateFromData.
|
|
return IsClipboardFormatAvailable(_oleData.cfLinkSource) ||
|
|
IsClipboardFormatAvailable(_oleData.cfFileName) ||
|
|
IsClipboardFormatAvailable(_oleData.cfFileNameW) ||
|
|
IsClipboardFormatAvailable(_oleData.cfObjectLink);
|
|
}
|
|
}
|
|
|
|
BOOL PASCAL
|
|
COleClientItem::CanCreateFromData(const COleDataObject* pDataObject)
|
|
{
|
|
if (!afxData.bWin31 && pDataObject->m_bClipboard)
|
|
return COleClientItem::CanPaste();
|
|
|
|
((COleDataObject*)pDataObject)->EnsureClipboardObject();
|
|
if (pDataObject->m_lpDataObject == NULL)
|
|
return FALSE;
|
|
|
|
SCODE sc = ::OleQueryCreateFromData(pDataObject->m_lpDataObject);
|
|
return !FAILED(sc) && sc != S_FALSE;
|
|
}
|
|
|
|
BOOL PASCAL
|
|
COleClientItem::CanCreateLinkFromData(const COleDataObject* pDataObject)
|
|
{
|
|
if (!afxData.bWin31 && pDataObject->m_bClipboard)
|
|
return COleClientItem::CanPasteLink();
|
|
|
|
((COleDataObject*)pDataObject)->EnsureClipboardObject();
|
|
if (pDataObject->m_lpDataObject == NULL)
|
|
return FALSE;
|
|
|
|
SCODE sc = ::OleQueryLinkFromData(pDataObject->m_lpDataObject);
|
|
return !FAILED(sc) && sc != S_FALSE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Conversion & Activate As support
|
|
|
|
BOOL COleClientItem::ConvertTo(REFCLSID clsidNew)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_lpObject != NULL);
|
|
|
|
// first, close the object
|
|
Close();
|
|
|
|
// convert it
|
|
m_scLast = _AfxOleDoConvert(m_lpStorage, clsidNew);
|
|
if (FAILED(m_scLast))
|
|
return FALSE;
|
|
|
|
// save IOleObject and IViewObject2 pointers
|
|
LPOLEOBJECT lpObject = m_lpObject;
|
|
LPVIEWOBJECT2 lpViewObject = m_lpViewObject;
|
|
DWORD dwConnection = m_dwConnection;
|
|
|
|
// NULL out IOleObject and IViewObject2 cached pointers
|
|
m_lpObject = NULL;
|
|
m_lpViewObject = NULL;
|
|
m_dwConnection = 0;
|
|
|
|
// then load the new object from the new storage
|
|
BOOL bResult = FinishCreate(::OleLoad(m_lpStorage, IID_IUnknown,
|
|
NULL, (LPLP)&m_lpObject));
|
|
|
|
if (bResult)
|
|
{
|
|
RELEASE(lpObject);
|
|
RELEASE(lpViewObject);
|
|
}
|
|
else
|
|
{
|
|
m_lpObject = lpObject;
|
|
m_lpViewObject = lpViewObject;
|
|
m_dwConnection = dwConnection;
|
|
UpdateItemType();
|
|
}
|
|
ASSERT_VALID(this);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
BOOL COleClientItem::Reload()
|
|
{
|
|
// first, close the object
|
|
Close();
|
|
|
|
// release any pointers we have to the object
|
|
RELEASE(m_lpObject);
|
|
RELEASE(m_lpViewObject);
|
|
|
|
// then reload the object with OleLoad and finish creation process
|
|
BOOL bResult = FinishCreate(::OleLoad(m_lpStorage, IID_IUnknown,
|
|
NULL, (LPLP)&m_lpObject));
|
|
|
|
ASSERT_VALID(this);
|
|
return bResult;
|
|
}
|
|
|
|
BOOL COleClientItem::ActivateAs(LPCTSTR lpszUserType,
|
|
REFCLSID clsidOld, REFCLSID clsidNew)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(lpszUserType == NULL || AfxIsValidString(lpszUserType));
|
|
ASSERT(m_lpObject != NULL);
|
|
|
|
// enable activate as
|
|
m_scLast = _AfxOleDoTreatAsClass(lpszUserType, clsidOld, clsidNew);
|
|
if (FAILED(m_scLast))
|
|
return FALSE;
|
|
|
|
// reload all items in this doucment
|
|
COleDocument* pDoc = GetDocument();
|
|
ASSERT_VALID(pDoc);
|
|
POSITION pos = pDoc->GetStartPosition();
|
|
COleClientItem* pItem;
|
|
while ((pItem = pDoc->GetNextClientItem(pos)) != NULL)
|
|
{
|
|
// reload it, so activate as works as appropriate
|
|
pItem->Reload();
|
|
}
|
|
|
|
ASSERT_VALID(this);
|
|
return TRUE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleClientItem printing support
|
|
|
|
BOOL COleClientItem::SetPrintDevice(const DVTARGETDEVICE* ptd)
|
|
{
|
|
ASSERT(ptd == NULL ||
|
|
AfxIsValidAddress(ptd, sizeof(DVTARGETDEVICE), FALSE));
|
|
|
|
// get printer device information from cache
|
|
LPOLECACHE lpOleCache;
|
|
DVTARGETDEVICE* ptdCur = NULL;
|
|
DWORD dwConnection;
|
|
if (!GetPrintDeviceInfo(&lpOleCache, &ptdCur, &dwConnection))
|
|
{
|
|
lpOleCache = QUERYINTERFACE(m_lpObject, IOleCache);
|
|
if (lpOleCache == NULL)
|
|
return FALSE; // no print device info available
|
|
}
|
|
ASSERT(lpOleCache != NULL);
|
|
|
|
// both may have no target device (considered equal)
|
|
if (ptd == NULL && ptdCur == NULL)
|
|
{
|
|
lpOleCache->Release();
|
|
CoTaskMemFree(ptdCur);
|
|
return TRUE;
|
|
}
|
|
|
|
if (ptd != NULL && ptdCur != NULL)
|
|
{
|
|
// should be non-NULL and valid addresses
|
|
ASSERT(AfxIsValidAddress(ptd, (size_t)ptd->tdSize));
|
|
ASSERT(AfxIsValidAddress(ptdCur, (size_t)ptdCur->tdSize));
|
|
// see if they compare equal
|
|
if (ptdCur->tdSize == ptd->tdSize &&
|
|
memcmp(ptdCur, ptd, (size_t)ptd->tdSize) == 0)
|
|
{
|
|
lpOleCache->Release();
|
|
CoTaskMemFree(ptdCur);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
// calling this with NULL will just remove the prevous printer cache
|
|
if (ptd != NULL)
|
|
{
|
|
// new cache is for CF_METAFILEPICT, DVASPECT_CONTENT
|
|
FORMATETC formatEtc;
|
|
formatEtc.cfFormat = CF_METAFILEPICT;
|
|
formatEtc.ptd = (DVTARGETDEVICE*)ptd;
|
|
formatEtc.dwAspect = DVASPECT_CONTENT;
|
|
formatEtc.lindex = -1;
|
|
formatEtc.tymed = TYMED_MFPICT;
|
|
|
|
// attempt to cache new format
|
|
DWORD dwNewConnection;
|
|
if (lpOleCache->Cache(&formatEtc, ADVFCACHE_ONSAVE,
|
|
&dwNewConnection) != S_OK)
|
|
{
|
|
lpOleCache->Release();
|
|
CoTaskMemFree(ptdCur);
|
|
return FALSE;
|
|
}
|
|
}
|
|
// new format is cached successfully, uncache old format
|
|
if (ptdCur != NULL)
|
|
{
|
|
lpOleCache->Uncache(dwConnection);
|
|
CoTaskMemFree(ptdCur);
|
|
}
|
|
// cleanup & return
|
|
lpOleCache->Release();
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL COleClientItem::SetPrintDevice(const PRINTDLG* ppd)
|
|
{
|
|
ASSERT(ppd == NULL || AfxIsValidAddress(ppd, sizeof(*ppd), FALSE));
|
|
DVTARGETDEVICE* ptd = NULL;
|
|
if (ppd != NULL)
|
|
ptd = _AfxOleCreateTargetDevice((PRINTDLG*)ppd);
|
|
|
|
BOOL bResult = SetPrintDevice(ptd);
|
|
CoTaskMemFree(ptd);
|
|
return bResult;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// other advanced COleClientItem support
|
|
|
|
void COleClientItem::GetUserType(
|
|
USERCLASSTYPE nUserClassType, CString& rString)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_lpObject != NULL);
|
|
|
|
LPOLESTR lpszUserType;
|
|
CheckGeneral(m_lpObject->GetUserType(nUserClassType, &lpszUserType));
|
|
ASSERT(lpszUserType != NULL);
|
|
ASSERT(AfxIsValidString(lpszUserType));
|
|
rString = lpszUserType;
|
|
CoTaskMemFree(lpszUserType);
|
|
}
|
|
|
|
void COleClientItem::Run()
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_lpObject != NULL);
|
|
|
|
// is object already in running state?
|
|
if (::OleIsRunning(m_lpObject))
|
|
return;
|
|
|
|
// run the object -- throw exception on errors
|
|
SCODE sc = ::OleRun(m_lpObject);
|
|
CheckGeneral(sc);
|
|
|
|
// should be running now
|
|
ASSERT(::OleIsRunning(m_lpObject));
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Linked COleClientItem operations
|
|
|
|
BOOL COleClientItem::UpdateLink()
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_lpObject != NULL);
|
|
|
|
m_scLast = S_OK;
|
|
if (!IsLinkUpToDate())
|
|
{
|
|
m_scLast = m_lpObject->Update();
|
|
ASSERT_VALID(m_pDocument);
|
|
m_pDocument->SetModifiedFlag();
|
|
}
|
|
return m_scLast == S_OK;
|
|
}
|
|
|
|
BOOL COleClientItem::FreezeLink()
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_lpObject != NULL);
|
|
ASSERT(m_pDocument != NULL);
|
|
ASSERT(GetType() == OT_LINK);
|
|
|
|
// first save & close the item
|
|
Close();
|
|
|
|
// get IDataObject interface
|
|
LPDATAOBJECT lpDataObject = QUERYINTERFACE(m_lpObject, IDataObject);
|
|
ASSERT(lpDataObject != NULL);
|
|
COleDataObject dataObject;
|
|
dataObject.Attach(lpDataObject, TRUE);
|
|
|
|
// save important state of original item
|
|
LPOLEOBJECT lpObject = m_lpObject;
|
|
LPSTORAGE lpStorage = m_lpStorage;
|
|
LPLOCKBYTES lpLockBytes = m_lpLockBytes;
|
|
LPVIEWOBJECT2 lpViewObject = m_lpViewObject;
|
|
DWORD dwConnection = m_dwConnection;
|
|
DWORD dwItemNumber = m_dwItemNumber;
|
|
m_lpObject = NULL;
|
|
m_lpStorage = NULL;
|
|
m_lpLockBytes = NULL;
|
|
m_lpViewObject = NULL;
|
|
m_dwConnection = 0;
|
|
|
|
// attempt to create new object from data
|
|
if (!CreateStaticFromData(&dataObject))
|
|
{
|
|
m_lpObject = lpObject;
|
|
m_lpStorage = lpStorage;
|
|
m_lpLockBytes = lpLockBytes;
|
|
m_lpViewObject = lpViewObject;
|
|
m_dwConnection = dwConnection;
|
|
return FALSE;
|
|
}
|
|
#ifdef _DEBUG
|
|
UpdateItemType();
|
|
ASSERT(GetType() == OT_STATIC);
|
|
#endif
|
|
|
|
// save new state of that item
|
|
LPOLEOBJECT lpNewObject = m_lpObject;
|
|
LPSTORAGE lpNewStorage = m_lpStorage;
|
|
LPLOCKBYTES lpNewLockBytes = m_lpLockBytes;
|
|
LPVIEWOBJECT2 lpNewViewObject = m_lpViewObject;
|
|
DWORD dwNewConnection = m_dwConnection;
|
|
DWORD dwNewItemNumber = m_dwItemNumber;
|
|
|
|
// shut down old item
|
|
m_lpObject = lpObject;
|
|
m_lpStorage = lpStorage;
|
|
m_lpLockBytes = lpLockBytes;
|
|
m_lpViewObject = lpViewObject;
|
|
m_dwConnection = dwConnection;
|
|
m_dwItemNumber = dwItemNumber;
|
|
#ifdef _DEBUG
|
|
UpdateItemType();
|
|
ASSERT(GetType() == OT_LINK);
|
|
#endif
|
|
Delete(FALSE); // revokes item & removes storage
|
|
|
|
// switch to new item
|
|
m_lpObject = lpNewObject;
|
|
m_lpStorage = lpNewStorage;
|
|
m_lpLockBytes = lpNewLockBytes;
|
|
m_lpViewObject = lpNewViewObject;
|
|
m_dwConnection = dwNewConnection;
|
|
m_dwItemNumber = dwNewItemNumber;
|
|
UpdateItemType();
|
|
ASSERT(GetType() == OT_STATIC);
|
|
|
|
// send an on changed with same state to invalidate the item
|
|
OnChange(OLE_CHANGED_STATE, (DWORD)GetItemState());
|
|
ASSERT_VALID(m_pDocument);
|
|
m_pDocument->SetModifiedFlag();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Special link attributes
|
|
|
|
OLEUPDATE COleClientItem::GetLinkUpdateOptions()
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_lpObject != NULL);
|
|
|
|
LPOLELINK lpOleLink = QUERYINTERFACE(m_lpObject, IOleLink);
|
|
ASSERT(lpOleLink != NULL); // perhaps not a link?
|
|
|
|
DWORD dwUpdateOpt;
|
|
SCODE sc = lpOleLink->GetUpdateOptions(&dwUpdateOpt);
|
|
lpOleLink->Release();
|
|
CheckGeneral(sc); // may throw an exception
|
|
|
|
return (OLEUPDATE)dwUpdateOpt;
|
|
}
|
|
|
|
void COleClientItem::SetLinkUpdateOptions(OLEUPDATE dwUpdateOpt)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_lpObject != NULL);
|
|
|
|
LPOLELINK lpOleLink = QUERYINTERFACE(m_lpObject, IOleLink);
|
|
ASSERT(lpOleLink != NULL); // perhaps not a link?
|
|
|
|
SCODE sc = lpOleLink->SetUpdateOptions(dwUpdateOpt);
|
|
lpOleLink->Release();
|
|
CheckGeneral(sc);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|