|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1999 - 1999
//
// File: copypast.cpp
//
//--------------------------------------------------------------------------
#include "stdafx.h"
#include "objfmts.h"
#include "copypast.h"
#include "multisel.h"
#include "dbg.h"
#include "rsltitem.h"
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/***************************************************************************\
| | NOTE: DataObject Cleanup works by these rules (see CNode::CDataObjectCleanup): | | 1. Data object created for cut , copy or dragdrop registers every node added to it | 2. Nodes are registered in the static multimap, mapping node to the data object it belongs to. | 3. Node destructor checks the map and triggers cleanup for all affected data objects. | 4. Data Object cleanup is: a) unregistering its nodes, | b) release contained data objects | b) entering invalid state (allowing only removal of cut objects to succeed) | c) revoking itself from clipboard if it is on the clipboard. | It will not do any of following: a) release references to IComponents as long as is alive | b) prevent MMCN_CUTORMOVE to be send by invoking RemoveCutItems() | \***************************************************************************/
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject~CMMCClipBoardDataObject * * PURPOSE: Destructor. Informs CNode's that they are no longer on clipboard * \***************************************************************************/ CMMCClipBoardDataObject::~CMMCClipBoardDataObject() { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::~CMMCClipBoardDataObject"));
// inform all nodes put to clipboard about being removed from there
// but do not ask to force clenup on itself - it is not needed (we are in desrtuctor)
// and it is harmfull to cleanup ole in such a case (see bug #164789)
sc = CNode::CDataObjectCleanup::ScUnadviseDataObject( this , false/*bForceDataObjectCleanup*/); if (sc) sc.TraceAndClear(); }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::GetSourceProcessId * * PURPOSE: returns process id of the source data object * * PARAMETERS: * DWORD *pdwProcID - [out] id of source process * * RETURNS: * HRESULT - result code * \***************************************************************************/ STDMETHODIMP CMMCClipBoardDataObject::GetSourceProcessId( DWORD *pdwProcID ) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetSourceProcessID"));
// should not be called on this object (too late)
if ( !m_bObjectValid ) return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(pdwProcID); if (sc) return sc.ToHr();
// return the id
*pdwProcID = ::GetCurrentProcessId();
return sc.ToHr(); }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::GetAction * * PURPOSE: returns ction which created the data object * * PARAMETERS: * DATA_SOURCE_ACTION *peAction [out] - action * * RETURNS: * HRESULT - result code. * \***************************************************************************/ STDMETHODIMP CMMCClipBoardDataObject::GetAction( DATA_SOURCE_ACTION *peAction ) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::IsCreatedForCopy"));
// should not be called on this object (too late)
if ( !m_bObjectValid ) return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(peAction); if (sc) return sc.ToHr();
// return the action
*peAction = m_eOperation;
return sc.ToHr(); }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::GetCount * * PURPOSE: Retuns the count of contined snapin data objects * * PARAMETERS: * DWORD *pdwCount [out] - count of objects * * RETURNS: * HRESULT - result code. S_OK, or error code * \***************************************************************************/ STDMETHODIMP CMMCClipBoardDataObject::GetCount( DWORD *pdwCount ) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetCount"));
// should not be called on this object (too late)
if ( !m_bObjectValid ) return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(pdwCount); if (sc) return sc.ToHr();
*pdwCount = m_SelectionObjects.size();
return sc.ToHr(); }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::GetDataObject * * PURPOSE: Returns one of contained snapin data objects * * PARAMETERS: * DWORD dwIndex [in] - index of reqested object * IDataObject **ppObject [out] - requested object * DWORD *pdwFlags [out] - object flags * * RETURNS: * HRESULT - result code. S_OK, or error code * \***************************************************************************/ STDMETHODIMP CMMCClipBoardDataObject::GetDataObject( DWORD dwIdx, IDataObject **ppObject, DWORD *pdwFlags ) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetDataObject"));
// should not be called on this object (too late)
if ( !m_bObjectValid ) return (sc = E_UNEXPECTED).ToHr();
// check out param
sc = ScCheckPointers(ppObject, pdwFlags); if (sc) return sc.ToHr();
// init out param
*ppObject = NULL; *pdwFlags = 0;
// more parameter check
if ( dwIdx >= m_SelectionObjects.size() ) return (sc = E_INVALIDARG).ToHr();
// return the object
IDataObjectPtr spObject = m_SelectionObjects[dwIdx].spDataObject; *ppObject = spObject.Detach(); *pdwFlags = m_SelectionObjects[dwIdx].dwSnapinOptions;
return sc.ToHr(); }
///////////////////////////////////////////////////////////////////////////////
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::ScGetSingleSnapinObject * * PURPOSE: Returns interface to data object created by the source snapin * NOTE: returns S_FALSE (and NULL ptr) when snapin count is not * equal to one * * PARAMETERS: * IDataObject **ppDataObject [out] - interface to data object * * RETURNS: * HRESULT - result code. S_OK, or error code * \***************************************************************************/ SC CMMCClipBoardDataObject::ScGetSingleSnapinObject( IDataObject **ppDataObject ) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetContainedSnapinObject"));
// should not be called on this object (too late)
if ( !m_bObjectValid ) return sc = E_UNEXPECTED;
// parameter check
sc = ScCheckPointers( ppDataObject ); if (sc) return sc;
// init out parameter
*ppDataObject = NULL;
// we can only resolve to the snapin if we have only one of them
if ( m_SelectionObjects.size() != 1 ) return sc = S_FALSE;
// ask for snapins DO
IDataObjectPtr spDataObject = m_SelectionObjects[0].spDataObject;
// return
*ppDataObject = spDataObject.Detach();
return sc; }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::GetDataHere * * PURPOSE: Implements IDataObject::GetDataHere. Forwards to snapin or fails * * PARAMETERS: * LPFORMATETC lpFormatetc * LPSTGMEDIUM lpMedium * * RETURNS: * HRESULT - result code. S_OK, or error code * \***************************************************************************/ STDMETHODIMP CMMCClipBoardDataObject::GetDataHere(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetDataHere"));
// should not be called on this object (too late)
if ( !m_bObjectValid ) return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(lpFormatetc, lpMedium); if (sc) return sc.ToHr();
// try to get the snapin
IDataObjectPtr spDataObject; sc = ScGetSingleSnapinObject( &spDataObject ); if (sc) return sc.ToHr();
// we do not support any clipboard format at all ourselves
if (sc == S_FALSE) return (sc = DATA_E_FORMATETC).ToHr();
// recheck
sc = ScCheckPointers( spDataObject, E_UNEXPECTED ); if (sc) return sc.ToHr();
// forward to the snapin
sc = spDataObject->GetDataHere(lpFormatetc, lpMedium); if (sc) return sc.ToHr();
return sc.ToHr(); }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::GetData * * PURPOSE: Implements IDataObject::GetData. Forwards to snapin or fails * * PARAMETERS: * LPFORMATETC lpFormatetcIn * LPSTGMEDIUM lpMedium * * RETURNS: * HRESULT - result code. S_OK, or error code * \***************************************************************************/ STDMETHODIMP CMMCClipBoardDataObject::GetData(LPFORMATETC lpFormatetcIn, LPSTGMEDIUM lpMedium) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::GetData"));
// should not be called on this object (too late)
if ( !m_bObjectValid ) return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(lpFormatetcIn, lpMedium); if (sc) return sc.ToHr();
// try to get the snapin
IDataObjectPtr spDataObject; sc = ScGetSingleSnapinObject( &spDataObject ); if (sc) return sc.ToHr();
// we do not support any clipboard format at all ourselves
if (sc == S_FALSE) return (sc = DATA_E_FORMATETC).ToHr();
// recheck
sc = ScCheckPointers( spDataObject, E_UNEXPECTED ); if (sc) return sc.ToHr();
// forward to the snapin
sc = spDataObject->GetData(lpFormatetcIn, lpMedium); if (sc) { HRESULT hr = sc.ToHr(); sc.Clear(); // ignore the error
return hr; }
return sc.ToHr(); }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::EnumFormatEtc * * PURPOSE: Implements IDataObject::EnumFormatEtc. Forwards to snapin or fails * * PARAMETERS: * DWORD dwDirection * LPENUMFORMATETC* ppEnumFormatEtc * * RETURNS: * HRESULT - result code. S_OK, or error code * \***************************************************************************/ STDMETHODIMP CMMCClipBoardDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC* ppEnumFormatEtc) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::EnumFormatEtc"));
// should not be called on this object (too late)
if ( !m_bObjectValid ) return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(ppEnumFormatEtc); if (sc) return sc.ToHr();
// init out parameter
*ppEnumFormatEtc = NULL;
IEnumFORMATETCPtr spEnum; std::vector<FORMATETC> vecFormats;
// add own entry
if (dwDirection == DATADIR_GET) { FORMATETC fmt ={GetWrapperCF(), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; vecFormats.push_back( fmt ); }
// try to get the snapin
IDataObjectPtr spDataObject; sc = ScGetSingleSnapinObject( &spDataObject ); if (sc) return sc.ToHr();
// add snapins formats (when we have one-and-only snapin)
IEnumFORMATETCPtr spEnumSnapin; if (sc == S_OK) { // recheck
sc = ScCheckPointers( spDataObject, E_UNEXPECTED ); if (sc) return sc.ToHr();
// forward to the snapin
sc = spDataObject->EnumFormatEtc(dwDirection, &spEnumSnapin); if ( !sc.IsError() ) { // recheck the pointer
sc = ScCheckPointers( spEnumSnapin ); if (sc) return sc.ToHr();
// reset the enumeration
sc = spEnumSnapin->Reset(); if (sc) return sc.ToHr();
FORMATETC frm; ZeroMemory( &frm, sizeof(frm) );
while ( (sc = spEnumSnapin->Next( 1, &frm, NULL )) == S_OK ) { vecFormats.push_back( frm ); } // trap the error
if (sc) return sc.ToHr();
} else { sc.Clear(); // ignore the error - some snapins does not implement it
} }
if ( vecFormats.size() == 0 ) // have nothing to return ?
return (sc = E_FAIL).ToHr();
// create the enumerator
sc = ::GetObjFormats( vecFormats.size(), vecFormats.begin(), (void **)ppEnumFormatEtc ); if (sc) return sc.ToHr();
return sc.ToHr(); }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::QueryGetData * * PURPOSE: Implements IDataObject::QueryGetData. Forwards to snapin or fails * * PARAMETERS: * LPFORMATETC lpFormatetc * * RETURNS: * HRESULT - result code. S_OK, or error code * \***************************************************************************/ STDMETHODIMP CMMCClipBoardDataObject::QueryGetData(LPFORMATETC lpFormatetc) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::QueryGetData"));
// should not be called on this object (too late)
if ( !m_bObjectValid ) return (sc = E_UNEXPECTED).ToHr();
// parameter check
sc = ScCheckPointers(lpFormatetc); if (sc) return sc.ToHr();
// try to get the snapin
IDataObjectPtr spDataObject; sc = ScGetSingleSnapinObject( &spDataObject ); if (sc) return sc.ToHr();
// we do not support any clipboard format at all ourselves
if (sc == S_FALSE) return DV_E_FORMATETC; // not assigning to sc - not an error
// recheck
sc = ScCheckPointers( spDataObject, E_UNEXPECTED ); if (sc) return sc.ToHr();
// forward to the snapin
sc = spDataObject->QueryGetData(lpFormatetc); if (sc) { HRESULT hr = sc.ToHr(); sc.Clear(); // ignore the error
return hr; }
return sc.ToHr(); }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::RemoveCutItems * * PURPOSE: Called to remove copied objects from the source snapin * * PARAMETERS: * DWORD dwIndex [in] snapin index * IDataObject *pCutDataObject [in] items to be removed * * RETURNS: * SC - result code * \***************************************************************************/ STDMETHODIMP CMMCClipBoardDataObject::RemoveCutItems( DWORD dwIndex, IDataObject *pCutDataObject ) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::RemoveCutItems"));
// this is the only method allowed to be called on invalid object
// check param
sc = ScCheckPointers(pCutDataObject); if (sc) return sc.ToHr();
// more parameter check
if ( dwIndex >= m_SelectionObjects.size() ) return (sc = E_INVALIDARG).ToHr();
// get to the snapin
IComponent *pComponent = m_SelectionObjects[dwIndex].spComponent; sc = ScCheckPointers( pComponent, E_UNEXPECTED ); if (sc) return sc.ToHr();
sc = pComponent->Notify( NULL, MMCN_CUTORMOVE, reinterpret_cast<LONG_PTR>(pCutDataObject), 0 ); if (sc) return sc.ToHr();
return sc.ToHr(); }
///////////////////////////////////////////////////////////////////////////////
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::ScCreateInstance * * PURPOSE: Helper method (static) to create instance of CMMCClipBoardDataObject * * PARAMETERS: * DATA_SOURCE_ACTION operation [in] why the object is created * CMTNode *pTiedObj [in] object to trigger revoking * CMMCClipBoardDataObject **ppRawObject [out] raw pointer * IMMCClipboardDataObject **ppInterface [out] pointer to interface * * RETURNS: * SC - result code * \***************************************************************************/ SC CMMCClipBoardDataObject::ScCreateInstance(DATA_SOURCE_ACTION operation, CMMCClipBoardDataObject **ppRawObject, IMMCClipboardDataObject **ppInterface) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScCreateInstance"));
// parameter check;
sc = ScCheckPointers( ppRawObject, ppInterface ); if (sc) return sc;
// out param initialization
*ppInterface = NULL; *ppRawObject = NULL;
typedef CComObject<CMMCClipBoardDataObject> CreatedObj; CreatedObj *pCreatedObj;
sc = CreatedObj::CreateInstance( &pCreatedObj ); if (sc) return sc;
// add first reference if non null;
IMMCClipboardDataObjectPtr spMMCDataObject = pCreatedObj;
// recheck
sc = ScCheckPointers( spMMCDataObject, E_UNEXPECTED ); if (sc) { delete pCreatedObj; return sc; }
// init the object
static_cast<CMMCClipBoardDataObject *>(pCreatedObj)->m_eOperation = operation;
// return 'em
*ppInterface = spMMCDataObject.Detach(); *ppRawObject = pCreatedObj;
return sc; }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::ScAddSnapinDataObject * * PURPOSE: Part of creating DO for the operation * Adds snapins data to be carried inside * * PARAMETERS: * IComponent *pComponent [in] - source snapin, which data id added * IDataObject *pObject [in] - data object supplied by snapin * bool bCopyEnabled [in] - if snapin allows to copy the data * bool bCutEnabled [in] - if snapin allows to move the data * * RETURNS: * SC - result code * \***************************************************************************/ SC CMMCClipBoardDataObject::ScAddSnapinDataObject( const CNodePtrArray& nodes, IComponent *pComponent, IDataObject *pObject, bool bCopyEnabled, bool bCutEnabled ) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScAddSnapinDataObject"));
// parameter check
sc = ScCheckPointers( pComponent, pObject ); if (sc) return sc;
// create the object;
ObjectEntry object; object.dwSnapinOptions = (bCopyEnabled ? COPY_ALLOWED : 0) | (bCutEnabled ? MOVE_ALLOWED : 0); object.spComponent = pComponent; object.spDataObject = pObject;
// register the nodes to invalidate this data object on destruction
for ( CNodePtrArray::const_iterator it = nodes.begin(); it != nodes.end(); ++it ) { CNode *pNode = *it; sc = ScCheckPointers( pNode, E_UNEXPECTED ); if (sc) return sc;
// register node to revoke this object from destructor
sc = CNode::CDataObjectCleanup::ScRegisterNode( pNode, this ); if (sc) return sc; }
// add to the array
m_SelectionObjects.push_back(object);
return sc; }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::GetNodeCopyAndCutVerbs * * PURPOSE: Calculates if copy and cut verb are enabled for node * * PARAMETERS: * CNode* pNode [in] node to examine * IDataObject *pDataObject [in] snapin's data object * bool bScopePane [in] Scope or result (item for which the verb states needed). * LPARAM lvData [in] If result then the LVDATA. * bool *pCopyEnabled [out] true == Copy verb enabled * bool *bCutEnabled [out] true == Cut verb enabled * * RETURNS: * SC - result code * \***************************************************************************/ SC CMMCClipBoardDataObject::ScGetNodeCopyAndCutVerbs( CNode* pNode, IDataObject *pDataObject, bool bScopePane, LPARAM lvData, bool *pbCopyEnabled, bool *pbCutEnabled ) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScGetNodeCopyAndCutVerbs"));
// paramter check
sc = ScCheckPointers(pNode, pDataObject, pbCopyEnabled, pbCutEnabled); if (sc) return sc;
// init out parameters
*pbCopyEnabled = *pbCutEnabled = false;
// Create temp verb with given context.
CComObject<CTemporaryVerbSet> stdVerbTemp;
sc = stdVerbTemp.ScInitialize(pDataObject, pNode, bScopePane, lvData);
BOOL bFlag = FALSE; stdVerbTemp.GetVerbState(MMC_VERB_COPY, ENABLED, &bFlag); *pbCopyEnabled = bFlag; stdVerbTemp.GetVerbState(MMC_VERB_CUT, ENABLED, &bFlag); *pbCutEnabled = bFlag;
return sc; }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::ScCreate * * PURPOSE: helper. Creates and initializes CMMCClipBoardDataObject * * PARAMETERS: * DATA_SOURCE_ACTION operation [in] - for which operation (d&d, cut, copy) * CNode* pNode [in] - Node to tie to * bool bScopePane [in] - if it is scope pane operation * bool bMultiSelect [in] - if it is multiselection * LPARAM lvData [in] - lvdata for result item * IMMCClipboardDataObject **ppMMCDO [out] - created data object * bool& bContainsItems [out] - If snapin does not support cut/copy then * dataobjets will not be added and this is * not an error * * RETURNS: * SC - result code * \***************************************************************************/ SC CMMCClipBoardDataObject::ScCreate( DATA_SOURCE_ACTION operation, CNode* pNode, bool bScopePane, bool bMultiSelect, LPARAM lvData, IMMCClipboardDataObject **ppMMCDataObject, bool& bContainsItems ) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::Create"));
bContainsItems = false;
// parameter check
sc = ScCheckPointers( ppMMCDataObject, pNode ); if (sc) return sc;
// init out param
*ppMMCDataObject = NULL;
// get MT node, view data;
CMTNode* pMTNode = pNode->GetMTNode(); CViewData *pViewData = pNode->GetViewData(); sc = ScCheckPointers( pMTNode, pViewData, E_UNEXPECTED ); if (sc) return sc;
// create data object to be used for data transfer
CMMCClipBoardDataObject *pResultObject = NULL; IMMCClipboardDataObjectPtr spResultInterface; sc = ScCreateInstance(operation, &pResultObject, &spResultInterface); if (sc) return sc;
// recheck pointers
sc = ScCheckPointers( pResultObject, spResultInterface, E_UNEXPECTED ); if (sc) return sc;
// valid from the start
pResultObject->m_bObjectValid = true;
// add data to the object...
if (!bMultiSelect) // single selection
{ // get snapins data object
IDataObjectPtr spDataObject; CComponent* pCComponent; bool bScopeItem = bScopePane; sc = pNode->ScGetDataObject(bScopePane, lvData, bScopeItem, &spDataObject, &pCComponent); if (sc) return sc;
// recheck data object
if ( IS_SPECIAL_DATAOBJECT ( spDataObject.GetInterfacePtr() ) ) { spDataObject.Detach(); return sc = E_UNEXPECTED; }
sc = ScCheckPointers(pCComponent, E_UNEXPECTED); if (sc) return sc;
IComponent *pComponent = pCComponent->GetIComponent(); sc = ScCheckPointers(pComponent, E_UNEXPECTED); if (sc) return sc;
// add snapin's data object to transfer object
sc = pResultObject->ScAddDataObjectForItem( pNode, bScopePane, lvData, pComponent, spDataObject, bContainsItems ); if (sc) return sc;
if (! bContainsItems) return sc; } else // result pane : multi selection
{ // get pointer to multiselection
CMultiSelection *pMultiSel = pViewData->GetMultiSelection(); sc = ScCheckPointers( pMultiSel, E_UNEXPECTED ); if (sc) return sc;
sc = pMultiSel->ScGetSnapinDataObjects(pResultObject); if (sc) return sc; }
// if no items were added, something is wrong
DWORD dwCount = 0; sc = pResultObject->GetCount( &dwCount ); if (sc) return sc;
if ( dwCount == 0 ) return sc = E_UNEXPECTED;
bContainsItems = true;
// return interface
*ppMMCDataObject = spResultInterface.Detach();
return sc; }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::ScAddDataObjectForItem * * PURPOSE: Adds data object for one item * * PARAMETERS: * CNode* pNode [in] - node to add (or one owning the item) * bool bScopePane [in] - if operation is on scope pane * LPARAM lvData [in] - if result pane the LVDATA * IComponent *pComponent [in] - snapins interface * IDataObject *pDataObject [in] - data object to add * bool& bContainsItems [out] - Are there any dataobjects added? * * RETURNS: * SC - result code * \***************************************************************************/ SC CMMCClipBoardDataObject::ScAddDataObjectForItem( CNode* pNode, bool bScopePane, LPARAM lvData, IComponent *pComponent, IDataObject *pDataObject , bool& bContainsItems) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScAddDataObjectForScopeNode"));
// Init out param.
bContainsItems = false;
// paramter check
sc = ScCheckPointers( pNode, pComponent, pDataObject ); if (sc) return sc;
// get the verbs
bool bCopyEnabled = false; bool bCutEnabled = false; sc = ScGetNodeCopyAndCutVerbs( pNode, pDataObject, bScopePane, lvData, &bCopyEnabled, &bCutEnabled); if (sc) return sc;
// see it the data matches our criteria
// (needs to allow something at least)
if ( ( (m_eOperation == ACTION_COPY) && (bCopyEnabled == false) ) || ( (m_eOperation == ACTION_CUT) && (bCutEnabled == false) ) || ( (bCutEnabled == false) && (bCopyEnabled == false) ) ) return sc = S_FALSE;
// add to the list
sc = ScAddSnapinDataObject( CNodePtrArray(1, pNode), pComponent, pDataObject, bCopyEnabled, bCutEnabled ); if (sc) return sc;
bContainsItems = true;
return sc; }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::GetWrapperCF * * PURPOSE: Helper. registers and returns own clipboard format * * PARAMETERS: * * RETURNS: * CLIPFORMAT * \***************************************************************************/ CLIPFORMAT CMMCClipBoardDataObject::GetWrapperCF() { static CLIPFORMAT s_cf = 0; if (s_cf == 0) s_cf = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_MMC_INTERNAL"));
return s_cf; }
/***************************************************************************\
* * METHOD: CMMCClipBoardDataObject::ScEnsureNotInClipboard * * PURPOSE: called to remove data from clipbord when comonent is destoyed * * PARAMETERS: * * RETURNS: * SC - result code * \***************************************************************************/ SC CMMCClipBoardDataObject::ScInvalidate( void ) { DECLARE_SC(sc, TEXT("CMMCClipBoardDataObject::ScEnsureNotInClipboard"));
// not valid anymore
m_bObjectValid = false;
// release data objects
for ( int i = 0; i< m_SelectionObjects.size(); i++) m_SelectionObjects[i].spDataObject = NULL;
// check the clipboard
sc = ::OleIsCurrentClipboard( this ); if (sc) return sc;
// it is on clipboard - remove
if (sc == S_OK) OleSetClipboard(NULL);
return sc; }
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
|