|
|
//////////////////////////////////////////////////////////////////////////////
/*++
Copyright (C) Microsoft Corporation, 1997 - 1999
Module Name:
CutAndPasteDataObject.h
Abstract:
Header file for the CCutAndPasteDataObject template class.
This is an inline template class.
Usage Notes:
This template class can be used to enable cutting and pasting for a node.
Override ATLsnap's CSnapInItem::GetDataObject and instead of passing back an IDataObject pointer on ATLsnap's CSnapInDataObjectImpl, pass back an IDataObject interface pointer on CCutAndPasteDataObject<CYourNode>.
In order to use this template class, your node class must have the following:
HRESULT FillText(LPSTGMEDIUM pSTM); // So our data can be pasted into any apps.
HRESULT FillClipboardData(LPSTGMEDIUM pSTM); static CLIPFORMAT m_CCF_CUT_AND_PASTE_FORMAT; You should make sure that your static m_CCF_CUT_AND_PASTE_FORMAT is registered as a clipformat in some static function you call at snapin startup, e.g.
static void InitClipboardFormat();
Note that once you have these implemented, you will also need to set the MMC_VERB_COPY on your node. You must them set the MMC_VERB_PASTE node on the folder node into which you would like to paste the node you've copied. That folder node must also repond appropriately to the MMCN_QUERY_PASTE notification. To handle this notification properly, you may find it helpful to add a method to the copied node which will tell whether the IDataObject has a valid clipboard format, e.g.:
static HRESULT IsClientClipboardData( IDataObject* pDataObj );
Once you've told MMC your folder node can handle a paste, you will have to respond correctly to the MMCN_PASTE notification, and you may again find it helpful to implement a method on the copied node which can fill that node with data from the IDataObject, e.g.: HRESULT SetClientWithDataFromClipboard( IDataObject* pDataObject );
Author:
Michael A. Maguire 02/12/98
Revision History: mmaguire 02/12/98 - abstracted from CClientDataObject
--*/ //////////////////////////////////////////////////////////////////////////////
#if !defined(_IAS_CUT_AND_PASTE_DATA_OBJECT_H_)
#define _IAS_CUT_AND_PASTE_DATA_OBJECT_H_
//////////////////////////////////////////////////////////////////////////////
// BEGIN INCLUDES
//
// where we can find what this class derives from:
//
//#include <atlctl.h> We've decided not to derive from ATL's IDataObjectImpl.
//
//
// where we can find what this class has or uses:
//
//
// END INCLUDES
//////////////////////////////////////////////////////////////////////////////
// Helper class used by class below.
template <class NodeToBeCutAndPasted> class CCutAndPasteObjectData { public: NodeToBeCutAndPasted * m_pItem; DATA_OBJECT_TYPES m_type; };
template <class NodeToBeCutAndPasted> class ATL_NO_VTABLE CCutAndPasteDataObject : public IDataObject , public CComObjectRoot {
public:
BEGIN_COM_MAP(CCutAndPasteDataObject<NodeToBeCutAndPasted>) COM_INTERFACE_ENTRY(IDataObject) END_COM_MAP()
//////////////////////////////////////////////////////////////////////////////
/*++
CCutAndPasteDataObject::GetData
This method is needed for spiffy clipboard functions.
Purpose: Retrieves data described by a specific FormatEtc into a StgMedium allocated by this function. Used like GetClipboardData.
Parameters: pFE LPFORMATETC describing the desired data. pSTM LPSTGMEDIUM in which to return the data.
Return Value: HRESULT NOERROR or a general error value.
--*/ //////////////////////////////////////////////////////////////////////////////
STDMETHOD(GetData)(FORMATETC *pFormatEtc, STGMEDIUM *pStorageMedium ) { ATLTRACE(_T("CCutAndPasteDataObject::GetData\n"));
HRESULT hr; UINT cf=pFormatEtc->cfFormat;
// Check the aspects we support.
// if (!(DVASPECT_CONTENT & pFE->dwAspect))
// return ResultFromScode(DATA_E_FORMATETC);
if( TYMED_HGLOBAL & pFormatEtc->tymed ) { if( cf == CF_TEXT ) { return hr = m_objectData.m_pItem->FillText( pStorageMedium ); }
if( cf == NodeToBeCutAndPasted::m_CCF_CUT_AND_PASTE_FORMAT ) { return hr = m_objectData.m_pItem->FillClipboardData( pStorageMedium ); } }
return E_NOTIMPL;
}
//////////////////////////////////////////////////////////////////////////////
/*++
CCutAndPasteDataObject::GetDataHere
This method is needed by MMC to do its usual work -- we are pretty much copying the ATLsnap.h implementation here.
--*/ //////////////////////////////////////////////////////////////////////////////
STDMETHOD(GetDataHere)(FORMATETC* pformatetc, STGMEDIUM* pmedium) { ATLTRACE(_T("CCutAndPasteDataObject::GetDataHere\n"));
if (pmedium == NULL) return E_POINTER;
HRESULT hr = DV_E_TYMED; // Make sure the type medium is HGLOBAL
if (pmedium->tymed == TYMED_HGLOBAL) { // Create the stream on the hGlobal passed in
CComPtr<IStream> spStream; hr = CreateStreamOnHGlobal(pmedium->hGlobal, FALSE, &spStream); if (SUCCEEDED(hr)) if (pformatetc->cfFormat == CSnapInItem::m_CCF_SNAPIN_GETOBJECTDATA) { hr = DV_E_CLIPFORMAT; ULONG uWritten; hr = spStream->Write(&m_objectData, sizeof(CObjectData), &uWritten); } else hr = m_objectData.m_pItem->FillData(pformatetc->cfFormat, spStream); } return hr; }
STDMETHOD(QueryGetData)(FORMATETC* /* pformatetc */) { ATLTRACENOTIMPL(_T("CCutAndPasteDataObject::QueryGetData\n")); }
STDMETHOD(GetCanonicalFormatEtc)(FORMATETC* /* pformatectIn */,FORMATETC* /* pformatetcOut */) { ATLTRACENOTIMPL(_T("CCutAndPasteDataObject::GetCanonicalFormatEtc\n")); }
STDMETHOD(SetData)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */, BOOL /* fRelease */) { ATLTRACENOTIMPL(_T("CCutAndPasteDataObject::SetData\n")); }
//////////////////////////////////////////////////////////////////////////////
/*++
CCutAndPasteDataObject::GetDataHere
For cut and paste, the OLE clipboard will ask us for an IEnumFORMATETC structure that lists the formats we support.
We construct a enumerator which will say that we support the format indicated by the m_CCF_CUT_AND_PASTE_FORMAT class variable from the node as template parameter.
You can use this template class for many nodes, each of which will have the m_CCF_CUT_AND_PASTE_FORMAT class variable, but just make sure that you use a different string for each of them in the RegisterClipboardFormat call.
CClientNode::m_CCF_CUT_AND_PASTE_FORMAT = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_IAS_CLIENT_NODE")); CPolicyNode::m_CCF_CUT_AND_PASTE_FORMAT = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_NAP_POLICY_NODE"));
Also, so that we can paste our data into any app, we support CF_TEXT. If you don't want this functionality, respond minimally in your node's FillText method. --*/ //////////////////////////////////////////////////////////////////////////////
STDMETHOD(EnumFormatEtc)(DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc ) { ATLTRACE(_T("CCutAndPasteDataObject::EnumFormatEtc\n"));
static FORMATETC fetcFormat[2];
fetcFormat[0].cfFormat=CF_TEXT; fetcFormat[0].dwAspect=DVASPECT_CONTENT; fetcFormat[0].ptd=NULL; fetcFormat[0].tymed=TYMED_HGLOBAL; fetcFormat[0].lindex=-1;
fetcFormat[1].cfFormat= NodeToBeCutAndPasted::m_CCF_CUT_AND_PASTE_FORMAT; fetcFormat[1].dwAspect=DVASPECT_CONTENT; fetcFormat[1].ptd=NULL; fetcFormat[1].tymed=TYMED_HGLOBAL; fetcFormat[1].lindex=-1;
switch (dwDirection) { case DATADIR_GET: *ppenumFormatEtc=new CEnumFormatEtc(2, fetcFormat); break;
case DATADIR_SET: *ppenumFormatEtc=NULL; break;
default: *ppenumFormatEtc=NULL; break; }
if( NULL == *ppenumFormatEtc ) { return E_FAIL; } else { (*ppenumFormatEtc)->AddRef(); }
return NOERROR; }
STDMETHOD(DAdvise)( FORMATETC *pformatetc , DWORD advf , IAdviseSink *pAdvSink , DWORD *pdwConnection ) { ATLTRACENOTIMPL(_T("CCutAndPasteDataObject::DAdvise\n")); }
STDMETHOD(DUnadvise)(DWORD dwConnection) { ATLTRACENOTIMPL(_T("CCutAndPasteDataObject::DUnadvise\n")); }
STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise) { ATLTRACENOTIMPL(_T("CCutAndPasteDataObject::EnumDAdvise\n")); }
CCutAndPasteObjectData<NodeToBeCutAndPasted> m_objectData;
};
#endif // _IAS_CUT_AND_PASTE_DATA_OBJECT_H_
|