• 拖拽的实现


    1.参考内容:

    英文资料

    中文翻译

    2.拖动涉及:源、目标、数据对象

    2.1 鼠标左键按下并且移动,触发拖动。

          构建源和数据对象。调用拖放函数DoDragDrop。

    	case WM_MOUSEMOVE:
    
    		// if the mouse is held down then start a drag-drop
    		if(fMouseDown)
    		{
    			IDataObject *pDataObject;
    			IDropSource *pDropSource;
    			DWORD		 dwEffect;
    			DWORD		 dwResult;
    
    			FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
    			STGMEDIUM stgmed = { TYMED_HGLOBAL, { 0 }, 0 };
    
    			// transfer the current selection into the IDataObject
    			stgmed.hGlobal = CopySelection(hwndEdit);
    
    			// Create IDataObject and IDropSource COM objects
    			CreateDropSource(&pDropSource);
    			CreateDataObject(&fmtetc, &stgmed, 1, &pDataObject);
    
    			//
    			//	** ** ** The drag-drop operation starts here! ** ** **
    			//
    			dwResult = DoDragDrop(pDataObject, pDropSource, DROPEFFECT_COPY|DROPEFFECT_MOVE, &dwEffect);
    
    			// success!
    			if(dwResult == DRAGDROP_S_DROP)
    			{
    				if(dwEffect & DROPEFFECT_MOVE)
    				{
    					// remove selection from edit control
    				}
    			}
    			// cancelled
    			else if(dwResult == DRAGDROP_S_CANCEL)
    			{
    			}
    
    			pDataObject->Release();
    			pDropSource->Release();
    
    			ReleaseCapture();
    			fMouseDown = FALSE;
    			fDidDragDrop = TRUE;
    		}
    

     2.拖放的目标程序,需要调用RegisterDragDrop,为拖放注册。

    	
    void RegisterDropWindow(HWND hwnd, IDropTarget **ppDropTarget)
    {
    	CDropTarget *pDropTarget = new CDropTarget(hwnd);
    
    	// acquire a strong lock
    	CoLockObjectExternal(pDropTarget, TRUE, FALSE);
    
    	// tell OLE that the window is a drop target
    	RegisterDragDrop(hwnd, pDropTarget);
    
    	*ppDropTarget = pDropTarget;
    }
    
    case WM_CREATE:
    
    		hwndEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
    			WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_WANTRETURN|WS_VSCROLL,
    			0,0,0,0, hwnd, 0, hInstance, 0);
    
    		SendMessage(hwndEdit, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), 0);
    
    		// make the Edit control into a DropTarget
    		RegisterDropWindow(hwndEdit, &pDropTarget);
    

     注意:如果你的程序是直接继承自IDropTarget,CoLockObjectExternal(this, TRUE, FALSE);这么写的话,紧接着的下面一句(RegisterDropWindow(hwndEdit, &pDropTarget);)可能就不会执行。换句话说,拖放可能会失败。

    3.所有的一切,都由DoDragDrop发轫。这个函数,会调用一些虚函数。如:CDataObject::EnumFormatEtc

    4.CDropTarget::Drop中响应事件操作。

    注意:   初始化 、反初始化

    OleInitialize(0);

    OleUninitialize();
    源文件

    dropsource.h

    //
    //	DROPSOURCE.H
    //
    //	Implementation of the IDropSource COM interface
    //
    //	By J Brown 2004 
    //
    //	www.catch22.net
    //
    
    
    #include <windows.h>
    
    HANDLE StringToHandle(char *szText, int nTextLen);
    HRESULT CreateDropSource(IDropSource **ppDropSource);
    
    class CDropSource : public IDropSource
    {
    public:
    	//
    	// IUnknown members
    	//
    	HRESULT __stdcall QueryInterface	(REFIID iid, void ** ppvObject);
    	ULONG   __stdcall AddRef			(void);
    	ULONG   __stdcall Release			(void);
    
    	//
    	// IDropSource members
    	//
    	HRESULT __stdcall QueryContinueDrag	(BOOL fEscapePressed, DWORD grfKeyState);
    	HRESULT __stdcall GiveFeedback		(DWORD dwEffect);
    
    	//
    	// Constructor / Destructor
    	//
    	CDropSource();
    	~CDropSource();
    
    private:
    
    	//
    	// private members and functions
    	//
    	LONG	   m_lRefCount;
    };
    

     dropsource.cpp

    //
    //	DROPSOURCE.CPP
    //
    //	Implementation of the IDropSource COM interface
    //
    //	By J Brown 2004 
    //
    //	www.catch22.net
    //
    
    #include "../stdafx.h"
    #include "dropsource.h"
    
    HANDLE StringToHandle(char *szText, int nTextLen)
    {
    	void  *ptr;
    
    	// if text length is -1 then treat as a nul-terminated string
    	if(nTextLen == -1)
    		nTextLen = lstrlen(szText) + 1;
    
    	// allocate and lock a global memory buffer. Make it fixed
    	// data so we don't have to use GlobalLock
    	ptr = (void *)GlobalAlloc(GMEM_FIXED, nTextLen);
    
    	// copy the string into the buffer
    	memcpy(ptr, szText, nTextLen);
    
    	return ptr;
    }
    
    //
    //	Constructor
    //
    CDropSource::CDropSource() 
    {
    	m_lRefCount = 1;
    }
    
    //
    //	Destructor
    //
    CDropSource::~CDropSource()
    {
    }
    
    //
    //	IUnknown::AddRef
    //
    ULONG __stdcall CDropSource::AddRef(void)
    {
        // increment object reference count
        return InterlockedIncrement(&m_lRefCount);
    }
    
    //
    //	IUnknown::Release
    //
    ULONG __stdcall CDropSource::Release(void)
    {
        // decrement object reference count
    	LONG count = InterlockedDecrement(&m_lRefCount);
    		
    	if(count == 0)
    	{
    		delete this;
    		return 0;
    	}
    	else
    	{
    		return count;
    	}
    }
    
    //
    //	IUnknown::QueryInterface
    //
    HRESULT __stdcall CDropSource::QueryInterface(REFIID iid, void **ppvObject)
    {
        // check to see what interface has been requested
        if(iid == IID_IDropSource || iid == IID_IUnknown)
        {
            AddRef();
            *ppvObject = this;
            return S_OK;
        }
        else
        {
            *ppvObject = 0;
            return E_NOINTERFACE;
        }
    }
    
    //
    //	CDropSource::QueryContinueDrag
    //
    //	Called by OLE whenever Escape/Control/Shift/Mouse buttons have changed
    //
    HRESULT __stdcall CDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
    {
    	// if the <Escape> key has been pressed since the last call, cancel the drop
    	if(fEscapePressed == TRUE)
    		return DRAGDROP_S_CANCEL;	
    
    	// if the <LeftMouse> button has been released, then do the drop!
    	if((grfKeyState & MK_LBUTTON) == 0)
    		return DRAGDROP_S_DROP;
    
    	// continue with the drag-drop
    	return S_OK;
    }
    
    //
    //	CDropSource::GiveFeedback
    //
    //	Return either S_OK, or DRAGDROP_S_USEDEFAULTCURSORS to instruct OLE to use the
    //  default mouse cursor images
    //
    HRESULT __stdcall CDropSource::GiveFeedback(DWORD dwEffect)
    {
    	return DRAGDROP_S_USEDEFAULTCURSORS;
    }
    
    //
    //	Helper routine to create an IDropSource object
    //	
    HRESULT CreateDropSource(IDropSource **ppDropSource)
    {
    	if(ppDropSource == 0)
    		return E_INVALIDARG;
    
    	*ppDropSource = new CDropSource();
    
    	return (*ppDropSource) ? S_OK : E_OUTOFMEMORY;
    
    }
    

     droptarget.h

    //
    //	DROPTARGET.H
    //
    //	By J Brown 2004 
    //
    //	www.catch22.net
    //
    
    #pragma once 
    #include <windows.h>
    
    void DropData(HWND hwnd, IDataObject *pDataObject);
    
    //
    //	This is our definition of a class which implements
    //  the IDropTarget interface
    //
    class CDropTarget : public IDropTarget
    {
    public:
    	// IUnknown implementation
    	HRESULT __stdcall QueryInterface (REFIID iid, void ** ppvObject);
    	ULONG	__stdcall AddRef (void);
    	ULONG	__stdcall Release (void);
    
    	// IDropTarget implementation
    	HRESULT __stdcall DragEnter (IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
    	HRESULT __stdcall DragOver (DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
    	HRESULT __stdcall DragLeave (void);
    	HRESULT __stdcall Drop (IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
    
    	virtual void DropData(HWND hwnd, IDataObject *pDataObject) = 0;
    	virtual const HWND GetWnd() = 0;
    
    	// Constructor
    	CDropTarget(/*HWND hwnd*/);
    	~CDropTarget();
    
    private:
    
    	// internal helper function
    	DWORD DropEffect(DWORD grfKeyState, POINTL pt, DWORD dwAllowed);
    	bool  QueryDataObject(IDataObject *pDataObject);
    
    
    	// Private member variables
    	LONG	m_lRefCount;
    	bool    m_fAllowDrop;
    
    	IDataObject *m_pDataObject;
    
    };
    

     droptarget.cpp

    //
    //	DROPTARGET.CPP
    //
    //	By J Brown 2004 
    //
    //	www.catch22.net
    //
    
    #include "../stdafx.h"
    #include "droptarget.h"
    
    //
    //	Constructor for the CDropTarget class
    //
    CDropTarget::CDropTarget(/*HWND hwnd*/)
    {
    	m_lRefCount  = 1;
    	m_fAllowDrop = false;
    }
    
    //
    //	Destructor for the CDropTarget class
    //
    CDropTarget::~CDropTarget()
    {
    	
    }
    
    //
    //	Position the edit control's caret under the mouse
    //
    void PositionCursor(HWND hwndEdit, POINTL pt)
    {
    	DWORD curpos; 
    		
    	// get the character position of mouse
    	ScreenToClient(hwndEdit, (POINT *)&pt);
    	curpos = SendMessage(hwndEdit, EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y));
    
    	// set cursor position
    	SendMessage(hwndEdit, EM_SETSEL, LOWORD(curpos), LOWORD(curpos));
    }
    
    //
    //	IUnknown::QueryInterface
    //
    HRESULT __stdcall CDropTarget::QueryInterface (REFIID iid, void ** ppvObject)
    {
    	if(iid == IID_IDropTarget || iid == IID_IUnknown)
    	{
    		AddRef();
    		*ppvObject = this;
    		return S_OK;
    	}
    	else
    	{
    		*ppvObject = 0;
    		return E_NOINTERFACE;
    	}
    }
    
    //
    //	IUnknown::AddRef
    //
    ULONG __stdcall CDropTarget::AddRef(void)
    {
    	return InterlockedIncrement(&m_lRefCount);
    }	
    
    //
    //	IUnknown::Release
    //
    ULONG __stdcall CDropTarget::Release(void)
    {
    	LONG count = InterlockedDecrement(&m_lRefCount);
    		
    	if(count == 0)
    	{
    		return 0;
    	}
    	else
    	{
    		return count;
    	}
    }
    
    //
    //	QueryDataObject private helper routine
    //
    bool CDropTarget::QueryDataObject(IDataObject *pDataObject)
    {
    	FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
    
    	// does the data object support CF_TEXT using a HGLOBAL?
    	return pDataObject->QueryGetData(&fmtetc) == S_OK ? true : false;
    }
    
    //
    //	DropEffect private helper routine
    //
    DWORD CDropTarget::DropEffect(DWORD grfKeyState, POINTL pt, DWORD dwAllowed)
    {
    	DWORD dwEffect = 0;
    
    	// 1. check "pt" -> do we allow a drop at the specified coordinates?
    	
    	// 2. work out that the drop-effect should be based on grfKeyState
    	if(grfKeyState & MK_CONTROL)
    	{
    		dwEffect = dwAllowed & DROPEFFECT_COPY;
    	}
    	else if(grfKeyState & MK_SHIFT)
    	{
    		dwEffect = dwAllowed & DROPEFFECT_MOVE;
    	}
    	
    	// 3. no key-modifiers were specified (or drop effect not allowed), so
    	//    base the effect on those allowed by the dropsource
    	if(dwEffect == 0)
    	{
    		if(dwAllowed & DROPEFFECT_COPY) dwEffect = DROPEFFECT_COPY;
    		if(dwAllowed & DROPEFFECT_MOVE) dwEffect = DROPEFFECT_MOVE;
    	}
    	
    	return dwEffect;
    }
    
    
    //
    //	IDropTarget::DragEnter
    //
    //
    //
    HRESULT __stdcall CDropTarget::DragEnter(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
    {
    	// does the dataobject contain data we want?
    	m_fAllowDrop = QueryDataObject(pDataObject);
    	
    	if(m_fAllowDrop)
    	{
    		// get the dropeffect based on keyboard state
    		*pdwEffect = DropEffect(grfKeyState, pt, *pdwEffect);
    
    		SetFocus(GetWnd());
    
    		PositionCursor(GetWnd(), pt);
    	}
    	else
    	{
    		*pdwEffect = DROPEFFECT_NONE;
    	}
    
    	return S_OK;
    }
    
    //
    //	IDropTarget::DragOver
    //
    //
    //
    HRESULT __stdcall CDropTarget::DragOver(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
    {
    	if(m_fAllowDrop)
    	{
    		*pdwEffect = DropEffect(grfKeyState, pt, *pdwEffect);
    		PositionCursor(GetWnd(), pt);
    	}
    	else
    	{
    		*pdwEffect = DROPEFFECT_NONE;
    	}
    
    	return S_OK;
    }
    
    //
    //	IDropTarget::DragLeave
    //
    HRESULT __stdcall CDropTarget::DragLeave(void)
    {
    	return S_OK;
    }
    
    //
    //	IDropTarget::Drop
    //
    //
    HRESULT __stdcall CDropTarget::Drop(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
    {
    	PositionCursor(GetWnd(), pt);
    
    	if(m_fAllowDrop)
    	{
    		DropData(GetWnd(), pDataObject);
    
    		*pdwEffect = DropEffect(grfKeyState, pt, *pdwEffect);
    	}
    	else
    	{
    		*pdwEffect = DROPEFFECT_NONE;
    	}
    
    	return S_OK;
    }
    
    void DropData(HWND hwnd, IDataObject *pDataObject)
    {
    	// construct a FORMATETC object
    	FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
    	STGMEDIUM stgmed;
    
    	// See if the dataobject contains any TEXT stored as a HGLOBAL
    	if(pDataObject->QueryGetData(&fmtetc) == S_OK)
    	{
    		// Yippie! the data is there, so go get it!
    		if(pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
    		{
    			// we asked for the data as a HGLOBAL, so access it appropriately
    			PVOID data = GlobalLock(stgmed.hGlobal);
    
    			SetWindowText(hwnd, (char *)data);
    
    			GlobalUnlock(stgmed.hGlobal);
    
    			// release the data using the COM API
    			ReleaseStgMedium(&stgmed);
    		}
    	}
    }
    

     dataobject.h

    //
    //	DATAOBJECT.H
    //
    //	Implementation of the IDataObject COM interface
    //
    //	By J Brown 2004 
    //
    //	www.catch22.net
    //
    
    
    #include <windows.h>
    
    // defined in enumformat.cpp
    HRESULT CreateEnumFormatEtc(UINT nNumFormats, FORMATETC *pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc);
    HRESULT CreateDataObject (FORMATETC *fmtetc, STGMEDIUM *stgmeds, UINT count, IDataObject **ppDataObject);
    
    class CDataObject : public IDataObject
    {
    public:
    	//
    	// IUnknown members
    	//
    	HRESULT __stdcall QueryInterface (REFIID iid, void ** ppvObject);
    	ULONG   __stdcall AddRef (void);
    	ULONG   __stdcall Release (void);
    
    	//
    	// IDataObject members
    	//
    	HRESULT __stdcall GetData				(FORMATETC *pFormatEtc,  STGMEDIUM *pMedium);
    	HRESULT __stdcall GetDataHere			(FORMATETC *pFormatEtc,  STGMEDIUM *pMedium);
    	HRESULT __stdcall QueryGetData			(FORMATETC *pFormatEtc);
    	HRESULT __stdcall GetCanonicalFormatEtc (FORMATETC *pFormatEct,  FORMATETC *pFormatEtcOut);
    	HRESULT __stdcall SetData				(FORMATETC *pFormatEtc,  STGMEDIUM *pMedium,  BOOL fRelease);
    	HRESULT __stdcall EnumFormatEtc			(DWORD      dwDirection, IEnumFORMATETC **ppEnumFormatEtc);
    	HRESULT __stdcall DAdvise				(FORMATETC *pFormatEtc,  DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
    	HRESULT __stdcall DUnadvise				(DWORD      dwConnection);
    	HRESULT __stdcall EnumDAdvise			(IEnumSTATDATA **ppEnumAdvise);
    
    	//
    	// Constructor / Destructor
    	//
    	CDataObject(FORMATETC *fmt, STGMEDIUM *stgmed, int count);
    	~CDataObject();
    
    private:
    
    	int LookupFormatEtc(FORMATETC *pFormatEtc);
    
    	//
    	// any private members and functions
    	//
    	LONG	   m_lRefCount;
    
    	FORMATETC *m_pFormatEtc;
    	STGMEDIUM *m_pStgMedium;
    	LONG	   m_nNumFormats;
    
    };
    

     dataobject.cpp

    //
    //	DATAOBJECT.CPP
    //
    //	Implementation of the IDataObject COM interface
    //
    //	By J Brown 2004 
    //
    //	www.catch22.net
    //
    
    #include "../stdafx.h"
    #include "dataobject.h"
    
    //
    //	Constructor
    //
    CDataObject::CDataObject(FORMATETC *fmtetc, STGMEDIUM *stgmed, int count) 
    {
    	m_lRefCount  = 1;
    	m_nNumFormats = count;
    	
    	m_pFormatEtc  = new FORMATETC[count];
    	m_pStgMedium  = new STGMEDIUM[count];
    
    	for(int i = 0; i < count; i++)
    	{
    		m_pFormatEtc[i] = fmtetc[i];
    		m_pStgMedium[i] = stgmed[i];
    	}
    }
    
    //
    //	Destructor
    //
    CDataObject::~CDataObject()
    {
    	// cleanup
    	if(m_pFormatEtc) delete[] m_pFormatEtc;
    	if(m_pStgMedium) delete[] m_pStgMedium;
    
    	OutputDebugString("oof\n");
    }
    
    //
    //	IUnknown::AddRef
    //
    ULONG __stdcall CDataObject::AddRef(void)
    {
        // increment object reference count
        return InterlockedIncrement(&m_lRefCount);
    }
    
    //
    //	IUnknown::Release
    //
    ULONG __stdcall CDataObject::Release(void)
    {
        // decrement object reference count
    	LONG count = InterlockedDecrement(&m_lRefCount);
    		
    	if(count == 0)
    	{
    		delete this;
    		return 0;
    	}
    	else
    	{
    		return count;
    	}
    }
    
    //
    //	IUnknown::QueryInterface
    //
    HRESULT __stdcall CDataObject::QueryInterface(REFIID iid, void **ppvObject)
    {
        // check to see what interface has been requested
        if(iid == IID_IDataObject || iid == IID_IUnknown)
        {
            AddRef();
            *ppvObject = this;
            return S_OK;
        }
        else
        {
            *ppvObject = 0;
            return E_NOINTERFACE;
        }
    }
    
    HGLOBAL DupMem(HGLOBAL hMem)
    {
    	// lock the source memory object
    	DWORD   len    = GlobalSize(hMem);
    	PVOID   source = GlobalLock(hMem);
    	
    	// create a fixed "global" block - i.e. just
    	// a regular lump of our process heap
    	PVOID   dest   = GlobalAlloc(GMEM_FIXED, len);
    
    	memcpy(dest, source, len);
    
    	GlobalUnlock(hMem);
    
    	return dest;
    }
    
    int CDataObject::LookupFormatEtc(FORMATETC *pFormatEtc)
    {
    	for(int i = 0; i < m_nNumFormats; i++)
    	{
    		if((pFormatEtc->tymed    &  m_pFormatEtc[i].tymed)   &&
    			pFormatEtc->cfFormat == m_pFormatEtc[i].cfFormat && 
    			pFormatEtc->dwAspect == m_pFormatEtc[i].dwAspect)
    		{
    			return i;
    		}
    	}
    
    	return -1;
    
    }
    
    //
    //	IDataObject::GetData
    //
    HRESULT __stdcall CDataObject::GetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium)
    {
    	int idx;
    
    	//
    	// try to match the requested FORMATETC with one of our supported formats
    	//
    	if((idx = LookupFormatEtc(pFormatEtc)) == -1)
    	{
    		return DV_E_FORMATETC;
    	}
    
    	//
    	// found a match! transfer the data into the supplied storage-medium
    	//
    	pMedium->tymed			 = m_pFormatEtc[idx].tymed;
    	pMedium->pUnkForRelease  = 0;
    	
    	switch(m_pFormatEtc[idx].tymed)
    	{
    	case TYMED_HGLOBAL:
    
    		pMedium->hGlobal = DupMem(m_pStgMedium[idx].hGlobal);
    		//return S_OK;
    		break;
    
    	default:
    		return DV_E_FORMATETC;
    	}
    
    	return S_OK;
    }
    
    //
    //	IDataObject::GetDataHere
    //
    HRESULT __stdcall CDataObject::GetDataHere (FORMATETC *pFormatEtc, STGMEDIUM *pMedium)
    {
    	// GetDataHere is only required for IStream and IStorage mediums
    	// It is an error to call GetDataHere for things like HGLOBAL and other clipboard formats
    	//
    	//	OleFlushClipboard 
    	//
    	return DATA_E_FORMATETC;
    }
    
    //
    //	IDataObject::QueryGetData
    //
    //	Called to see if the IDataObject supports the specified format of data
    //
    HRESULT __stdcall CDataObject::QueryGetData (FORMATETC *pFormatEtc)
    {
    	return (LookupFormatEtc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK;
    }
    
    //
    //	IDataObject::GetCanonicalFormatEtc
    //
    HRESULT __stdcall CDataObject::GetCanonicalFormatEtc (FORMATETC *pFormatEct, FORMATETC *pFormatEtcOut)
    {
    	// Apparently we have to set this field to NULL even though we don't do anything else
    	pFormatEtcOut->ptd = NULL;
    	return E_NOTIMPL;
    }
    
    //
    //	IDataObject::SetData
    //
    HRESULT __stdcall CDataObject::SetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium,  BOOL fRelease)
    {
    	return E_NOTIMPL;
    }
    
    //
    //	IDataObject::EnumFormatEtc
    //
    HRESULT __stdcall CDataObject::EnumFormatEtc (DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc)
    {
    	if(dwDirection == DATADIR_GET)
    	{
    		// for Win2k+ you can use the SHCreateStdEnumFmtEtc API call, however
    		// to support all Windows platforms we need to implement IEnumFormatEtc ourselves.
    		return CreateEnumFormatEtc(m_nNumFormats, m_pFormatEtc, ppEnumFormatEtc);
    	}
    	else
    	{
    		// the direction specified is not support for drag+drop
    		return E_NOTIMPL;
    	}
    }
    
    //
    //	IDataObject::DAdvise
    //
    HRESULT __stdcall CDataObject::DAdvise (FORMATETC *pFormatEtc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
    {
    	return OLE_E_ADVISENOTSUPPORTED;
    }
    
    //
    //	IDataObject::DUnadvise
    //
    HRESULT __stdcall CDataObject::DUnadvise (DWORD dwConnection)
    {
    	return OLE_E_ADVISENOTSUPPORTED;
    }
    
    //
    //	IDataObject::EnumDAdvise
    //
    HRESULT __stdcall CDataObject::EnumDAdvise (IEnumSTATDATA **ppEnumAdvise)
    {
    	return OLE_E_ADVISENOTSUPPORTED;
    }
    
    //
    //	Helper function
    //
    HRESULT CreateDataObject (FORMATETC *fmtetc, STGMEDIUM *stgmeds, UINT count, IDataObject **ppDataObject)
    {
    	if(ppDataObject == 0)
    		return E_INVALIDARG;
    
    	*ppDataObject = new CDataObject(fmtetc, stgmeds, count);
    
    	return (*ppDataObject) ? S_OK : E_OUTOFMEMORY;
    }
    

     enumformat.h

    //
    //	ENUMFORMAT.H
    //
    //	By J Brown 2004 
    //
    //	www.catch22.net
    //
    //	Implementation of the IEnumFORMATETC interface
    //
    //	For Win2K and above look at the SHCreateStdEnumFmtEtc API call!!
    //
    //	Apparently the order of formats in an IEnumFORMATETC object must be
    //  the same as those that were stored in the clipboard
    //
    //
    
    
    #include <windows.h>
    
    class CEnumFormatEtc : public IEnumFORMATETC
    {
    public:
    
    	//
    	// IUnknown members
    	//
    	HRESULT __stdcall  QueryInterface (REFIID iid, void ** ppvObject);
    	ULONG	__stdcall  AddRef (void);
    	ULONG	__stdcall  Release (void);
    
    	//
    	// IEnumFormatEtc members
    	//
    	HRESULT __stdcall  Next  (ULONG celt, FORMATETC * rgelt, ULONG * pceltFetched);
    	HRESULT __stdcall  Skip  (ULONG celt); 
    	HRESULT __stdcall  Reset (void);
    	HRESULT __stdcall  Clone (IEnumFORMATETC ** ppEnumFormatEtc);
    
    	//
    	// Construction / Destruction
    	//
    	CEnumFormatEtc(FORMATETC *pFormatEtc, int nNumFormats);
    	~CEnumFormatEtc();
    
    private:
    
    	LONG		m_lRefCount;		// Reference count for this COM interface
    	ULONG		m_nIndex;			// current enumerator index
    	ULONG		m_nNumFormats;		// number of FORMATETC members
    	FORMATETC * m_pFormatEtc;		// array of FORMATETC objects
    };
    

     enumformat.cpp

    //
    //	ENUMFORMAT.CPP
    //
    //	By J Brown 2004 
    //
    //	www.catch22.net
    //
    //	Implementation of the IEnumFORMATETC interface
    //
    //	For Win2K and above look at the SHCreateStdEnumFmtEtc API call!!
    //
    //	Apparently the order of formats in an IEnumFORMATETC object must be
    //  the same as those that were stored in the clipboard
    //
    //
    
    #include "../stdafx.h"
    #include "enumformat.h"
    
    //
    //	"Drop-in" replacement for SHCreateStdEnumFmtEtc. Called by CDataObject::EnumFormatEtc
    //
    HRESULT CreateEnumFormatEtc(UINT nNumFormats, FORMATETC *pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc)
    {
    	if(nNumFormats == 0 || pFormatEtc == 0 || ppEnumFormatEtc == 0)
    		return E_INVALIDARG;
    
    	*ppEnumFormatEtc = new CEnumFormatEtc(pFormatEtc, nNumFormats);
    
    	return (*ppEnumFormatEtc) ? S_OK : E_OUTOFMEMORY;
    }
    
    //
    //	Helper function to perform a "deep" copy of a FORMATETC
    //
    static void DeepCopyFormatEtc(FORMATETC *dest, FORMATETC *source)
    {
    	// copy the source FORMATETC into dest
    	*dest = *source;
    	
    	if(source->ptd)
    	{
    		// allocate memory for the DVTARGETDEVICE if necessary
    		dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
    
    		// copy the contents of the source DVTARGETDEVICE into dest->ptd
    		*(dest->ptd) = *(source->ptd);
    	}
    }
    
    //
    //	Constructor 
    //
    CEnumFormatEtc::CEnumFormatEtc(FORMATETC *pFormatEtc, int nNumFormats)
    {
    	m_lRefCount   = 1;
    	m_nIndex      = 0;
    	m_nNumFormats = nNumFormats;
    	m_pFormatEtc  = new FORMATETC[nNumFormats];
    	
    	// copy the FORMATETC structures
    	for(int i = 0; i < nNumFormats; i++)
    	{	
    		DeepCopyFormatEtc(&m_pFormatEtc[i], &pFormatEtc[i]);
    	}
    }
    
    //
    //	Destructor
    //
    CEnumFormatEtc::~CEnumFormatEtc()
    {
    	if(m_pFormatEtc)
    	{
    		for(ULONG i = 0; i < m_nNumFormats; i++)
    		{
    			if(m_pFormatEtc[i].ptd)
    				CoTaskMemFree(m_pFormatEtc[i].ptd);
    		}
    
    		delete[] m_pFormatEtc;
    	}
    }
    
    //
    //	IUnknown::AddRef
    //
    ULONG __stdcall CEnumFormatEtc::AddRef(void)
    {
        // increment object reference count
        return InterlockedIncrement(&m_lRefCount);
    }
    
    //
    //	IUnknown::Release
    //
    ULONG __stdcall CEnumFormatEtc::Release(void)
    {
        // decrement object reference count
    	LONG count = InterlockedDecrement(&m_lRefCount);
    		
    	if(count == 0)
    	{
    		delete this;
    		return 0;
    	}
    	else
    	{
    		return count;
    	}
    }
    
    //
    //	IUnknown::QueryInterface
    //
    HRESULT __stdcall CEnumFormatEtc::QueryInterface(REFIID iid, void **ppvObject)
    {
        // check to see what interface has been requested
        if(iid == IID_IEnumFORMATETC || iid == IID_IUnknown)
        {
            AddRef();
            *ppvObject = this;
            return S_OK;
        }
        else
        {
            *ppvObject = 0;
            return E_NOINTERFACE;
        }
    }
    
    //
    //	IEnumFORMATETC::Next
    //
    //	If the returned FORMATETC structure contains a non-null "ptd" member, then
    //  the caller must free this using CoTaskMemFree (stated in the COM documentation)
    //
    HRESULT __stdcall CEnumFormatEtc::Next(ULONG celt, FORMATETC *pFormatEtc, ULONG * pceltFetched)
    {
    	ULONG copied  = 0;
    
    	// validate arguments
    	if(celt == 0 || pFormatEtc == 0)
    		return E_INVALIDARG;
    
    	// copy FORMATETC structures into caller's buffer
    	while(m_nIndex < m_nNumFormats && copied < celt)
    	{
    		DeepCopyFormatEtc(&pFormatEtc[copied], &m_pFormatEtc[m_nIndex]);
    		copied++;
    		m_nIndex++;
    	}
    
    	// store result
    	if(pceltFetched != 0) 
    		*pceltFetched = copied;
    
    	// did we copy all that was requested?
    	return (copied == celt) ? S_OK : S_FALSE;
    }
    
    //
    //	IEnumFORMATETC::Skip
    //
    HRESULT __stdcall CEnumFormatEtc::Skip(ULONG celt)
    {
    	m_nIndex += celt;
    	return (m_nIndex <= m_nNumFormats) ? S_OK : S_FALSE;
    }
    
    //
    //	IEnumFORMATETC::Reset
    //
    HRESULT __stdcall CEnumFormatEtc::Reset(void)
    {
    	m_nIndex = 0;
    	return S_OK;
    }
    
    //
    //	IEnumFORMATETC::Clone
    //
    HRESULT __stdcall CEnumFormatEtc::Clone(IEnumFORMATETC ** ppEnumFormatEtc)
    {
    	HRESULT hResult;
    
    	// make a duplicate enumerator
    	hResult = CreateEnumFormatEtc(m_nNumFormats, m_pFormatEtc, ppEnumFormatEtc);
    
    	if(hResult == S_OK)
    	{
    		// manually set the index state
    		((CEnumFormatEtc *) *ppEnumFormatEtc)->m_nIndex = m_nIndex;
    	}
    
    	return hResult;
    }
    



    //
    //    DATAOBJECT.H
    //
    //    Implementation of the IDataObject COM interface
    //
    //    By J Brown 2004
    //
    //    www.catch22.net
    //


    #include <windows.h>

    // defined in enumformat.cpp
    HRESULT CreateEnumFormatEtc(UINT nNumFormats, FORMATETC *pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc);
    HRESULT CreateDataObject (FORMATETC *fmtetc, STGMEDIUM *stgmeds, UINT count, IDataObject **ppDataObject);

    class CDataObject : public IDataObject
    {
    public:
        //
        // IUnknown members
        //
        HRESULT __stdcall QueryInterface (REFIID iid, void ** ppvObject);
        ULONG   __stdcall AddRef (void);
        ULONG   __stdcall Release (void);

        //
        // IDataObject members
        //
        HRESULT __stdcall GetData                (FORMATETC *pFormatEtc,  STGMEDIUM *pMedium);
        HRESULT __stdcall GetDataHere            (FORMATETC *pFormatEtc,  STGMEDIUM *pMedium);
        HRESULT __stdcall QueryGetData            (FORMATETC *pFormatEtc);
        HRESULT __stdcall GetCanonicalFormatEtc (FORMATETC *pFormatEct,  FORMATETC *pFormatEtcOut);
        HRESULT __stdcall SetData                (FORMATETC *pFormatEtc,  STGMEDIUM *pMedium,  BOOL fRelease);
        HRESULT __stdcall EnumFormatEtc            (DWORD      dwDirection, IEnumFORMATETC **ppEnumFormatEtc);
        HRESULT __stdcall DAdvise                (FORMATETC *pFormatEtc,  DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
        HRESULT __stdcall DUnadvise                (DWORD      dwConnection);
        HRESULT __stdcall EnumDAdvise            (IEnumSTATDATA **ppEnumAdvise);

        //
        // Constructor / Destructor
        //
        CDataObject(FORMATETC *fmt, STGMEDIUM *stgmed, int count);
        ~CDataObject();

    private:

        int LookupFormatEtc(FORMATETC *pFormatEtc);

        //
        // any private members and functions
        //
        LONG       m_lRefCount;

        FORMATETC *m_pFormatEtc;
        STGMEDIUM *m_pStgMedium;
        LONG       m_nNumFormats;

    };

  • 相关阅读:
    不需重新编译php,安装postgresql扩展(pgsql和pdo_pgsql)
    css如何实现水平垂直居中
    win系统DOS批处理命令:每日根据定时计划,弹出相应的提醒
    使用navicat连接mysql连接错误:Lost connection to Mysql server at 'waiting for initial communication packet'
    mysql域名解析引起的远程访问过慢?
    Jquery封装: 地区选择联动插件
    Jquery封装: WebSocket插件
    Jquery封装:下拉框插件
    如何在微信小程序中使用阿里字体图标
    轻量级进度条 – Nprogress.js
  • 原文地址:https://www.cnblogs.com/chunyou128/p/2360607.html
Copyright © 2020-2023  润新知