最新消息:想得多,做的少。一天到晚瞎鸡巴搞。

鼠标拖拽文件移动的实现(com 基于windos sdk)

Windows编程 阿虚 453浏览 0评论

.      拖动涉及:源、目标、数据对象,鼠标左键按下并且移动,触发拖动。构建源和数据对象。调用拖放函数DoDragDrop。

bool DragDropTo(WCHAR* path)
{
    OleInitialize(NULL);    // needed for Drag and Drop
      
    IDropSource *pDropSource;
    IDataObject *pDataObject;
      
    FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
    STGMEDIUM stgmed = { TYMED_HGLOBAL, { 0 }, 0 };
      
    stgmed.hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_DDESHARE, MAX_PATH * 2);
    
    LPDROPFILES pDropFiles = (LPDROPFILES)::GlobalLock(stgmed.hGlobal);
    pDropFiles->pFiles = sizeof(DROPFILES);
    pDropFiles->fWide = TRUE;
    LPBYTE pData = (LPBYTE)pDropFiles + sizeof(DROPFILES); 
    memcpy(pData, path, sizeof(WCHAR)*wcslen(path));
    ::GlobalUnlock(stgmed.hGlobal);

    if (CDropSource::CreateDropSource(&pDropSource) != S_OK) return false;

    if (CDataObject::CreateDataObject(&fmtetc, &stgmed, 1, &pDataObject) != S_OK)
    {
        delete pDropSource;
        return false;
    }
         
    DWORD        dwEffect;
    DWORD        dwResult;  
    dwResult = DoDragDrop(pDataObject, pDropSource, DROPEFFECT_COPY, &dwEffect);
      
    pDataObject->Release();
    pDropSource->Release();
    OleUninitialize(); 
    return true;
} 


//DragDropImpl.h
// IDataObjectImpl.h: interface for the CIDataObjectImpl class.
/**************************************************************************
   THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF
   ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
   PARTICULAR PURPOSE.
   Author: Leon Finker  1/2001
**************************************************************************/
#ifndef __DRAGDROPIMPL_H__
#define __DRAGDROPIMPL_H__
//#include <ShlDisp.h>
#include <atlbase.h>
#include <objidl.h>
#include <Shlobj.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  
};

///////////////////////////////////////////////////////////////////////////////////////////////
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);

    static HRESULT CreateDropSource(IDropSource **ppDropSource);

    //  
    // Constructor / Destructor  
    //  
    CDropSource();
    ~CDropSource();

private:

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

///////////////////////////////////////////////////////////////////////////////////////////////
class CDataObject : public IDataObject//,public IAsyncOperation
{
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);

    static HRESULT CreateDataObject(FORMATETC *fmtetc, STGMEDIUM *stgmeds, UINT count, IDataObject **ppDataObject);

    //  
    // 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;
};

///////////////////////////////////////////////////////////////////////////////////////////////
class CIDropTarget : public IDropTarget
{
	DWORD m_cRefCount;
	bool m_bAllowDrop;
	struct IDropTargetHelper *m_pDropTargetHelper;
	CSimpleArray<FORMATETC> m_formatetc;
	FORMATETC* m_pSupportedFrmt;
protected:
	HWND m_hTargetWnd;
public:
	
	CIDropTarget(HWND m_hTargetWnd);
	virtual ~CIDropTarget();
	void AddSuportedFormat(FORMATETC& ftetc) { m_formatetc.Add(ftetc); }
	
	//return values: true - release the medium. false - don't release the medium 
	virtual bool OnDrop(FORMATETC* pFmtEtc, STGMEDIUM& medium,DWORD *pdwEffect) = 0;

	virtual HRESULT STDMETHODCALLTYPE QueryInterface( 
		/* [in] */ REFIID riid,
		/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
	virtual ULONG STDMETHODCALLTYPE AddRef( void) { ATLTRACE("CIDropTarget::AddRef\n"); return ++m_cRefCount; }
	virtual ULONG STDMETHODCALLTYPE Release( void);

    bool QueryDrop(DWORD grfKeyState, LPDWORD pdwEffect);
	virtual HRESULT STDMETHODCALLTYPE DragEnter(
        /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
        /* [in] */ DWORD grfKeyState,
        /* [in] */ POINTL pt,
        /* [out][in] */ DWORD __RPC_FAR *pdwEffect);
    virtual HRESULT STDMETHODCALLTYPE DragOver( 
        /* [in] */ DWORD grfKeyState,
        /* [in] */ POINTL pt,
        /* [out][in] */ DWORD __RPC_FAR *pdwEffect);
    virtual HRESULT STDMETHODCALLTYPE DragLeave( void);    
    virtual HRESULT STDMETHODCALLTYPE Drop(
        /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
        /* [in] */ DWORD grfKeyState,
        /* [in] */ POINTL pt,
        /* [out][in] */ DWORD __RPC_FAR *pdwEffect);
};

class CDragSourceHelper
{
	IDragSourceHelper* pDragSourceHelper;
public:
	CDragSourceHelper()
	{
		if(FAILED(CoCreateInstance(CLSID_DragDropHelper,
                        NULL,
                        CLSCTX_INPROC_SERVER,
                        IID_IDragSourceHelper,
                        (void**)&pDragSourceHelper)))
			pDragSourceHelper = NULL;
	}
	virtual ~CDragSourceHelper()
	{
		if( pDragSourceHelper!= NULL )
		{
			pDragSourceHelper->Release();
			pDragSourceHelper=NULL;
		}
	}
    
	// IDragSourceHelper
    HRESULT InitializeFromBitmap(HBITMAP hBitmap, 
		POINT& pt,	// cursor position in client coords of the window
		RECT& rc,	// selected item's bounding rect
		IDataObject* pDataObject,
		COLORREF crColorKey=GetSysColor(COLOR_WINDOW)// color of the window used for transparent effect.
		)
	{
		if(pDragSourceHelper == NULL)
			return E_FAIL;

		    SHDRAGIMAGE di;
            BITMAP      bm;
            GetObject(hBitmap, sizeof(bm), &bm);
            di.sizeDragImage.cx = bm.bmWidth;
            di.sizeDragImage.cy = bm.bmHeight;
            di.hbmpDragImage = hBitmap;
            di.crColorKey = crColorKey; 
            di.ptOffset.x = pt.x - rc.left;
            di.ptOffset.y = pt.y - rc.top;
        return pDragSourceHelper->InitializeFromBitmap(&di, pDataObject);
	}
    HRESULT InitializeFromWindow(HWND hwnd, POINT& pt,IDataObject* pDataObject)
	{		
		if(pDragSourceHelper == NULL)
			return E_FAIL;
		return pDragSourceHelper->InitializeFromWindow(hwnd, &pt, pDataObject);
	}
};


#endif //__DRAGDROPIMPL_H__



//DragDropImpl.cpp
/**************************************************************************
   THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF
   ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
   PARTICULAR PURPOSE.
   Author: Leon Finker  1/2001
**************************************************************************/
// IDataObjectImpl.cpp: implementation of the CIDataObjectImpl class.
//////////////////////////////////////////////////////////////////////
#include <shlobj.h>
#include <atlbase.h>
#include "DragDropImpl.h"

HRESULT CreateEnumFormatEtc(UINT cfmt, FORMATETC *afmt, IEnumFORMATETC **ppEnumFormatEtc)
{
    if (cfmt == 0 || afmt == 0 || ppEnumFormatEtc == 0)
        return E_INVALIDARG;
    *ppEnumFormatEtc = new CEnumFormatEtc(afmt, cfmt);
    return (*ppEnumFormatEtc) ? S_OK : E_OUTOFMEMORY;

}


//////////////////////////////////////////////////////////////////////
// CIDataObject Class
//////////////////////////////////////////////////////////////////////

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(L"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 CDataObject::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;
}

//////////////////////////////////////////////////////////////////////
// CIDropSource Class
//////////////////////////////////////////////////////////////////////



//  
//  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 CDropSource::CreateDropSource(IDropSource **ppDropSource)
{
    if (ppDropSource == 0)
        return E_INVALIDARG;

    *ppDropSource = new CDropSource();

    return (*ppDropSource) ? S_OK : E_OUTOFMEMORY;

}

//////////////////////////////////////////////////////////////////////
// CEnumFormatEtc Class
//////////////////////////////////////////////////////////////////////
 

//  
//  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;
}


//////////////////////////////////////////////////////////////////////
// CIDropTarget Class
//////////////////////////////////////////////////////////////////////
CIDropTarget::CIDropTarget(HWND hTargetWnd): 
	m_hTargetWnd(hTargetWnd),
	m_cRefCount(0), m_bAllowDrop(false),
	m_pDropTargetHelper(NULL), m_pSupportedFrmt(NULL)
{ 
	ATLASSERT(m_hTargetWnd != NULL);

	if(FAILED(CoCreateInstance(CLSID_DragDropHelper,NULL,CLSCTX_INPROC_SERVER,
                     IID_IDropTargetHelper,(LPVOID*)&m_pDropTargetHelper)))
		m_pDropTargetHelper = NULL;
}

CIDropTarget::~CIDropTarget()
{
	if(m_pDropTargetHelper != NULL)
	{
		m_pDropTargetHelper->Release();
		m_pDropTargetHelper = NULL;
	}
}

HRESULT STDMETHODCALLTYPE CIDropTarget::QueryInterface( /* [in] */ REFIID riid,
						/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
{
   *ppvObject = NULL;
   if (IID_IUnknown==riid || IID_IDropTarget==riid)
			 *ppvObject=this;

	if (*ppvObject != NULL)
	{
		((LPUNKNOWN)*ppvObject)->AddRef();
		return S_OK;
	}
	return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE CIDropTarget::Release( void)
{
   ATLTRACE("CIDropTarget::Release\n");
   long nTemp;
   nTemp = --m_cRefCount;
   ATLASSERT(nTemp >= 0);
   if(nTemp==0)
	  delete this;
   return nTemp;
}

bool CIDropTarget::QueryDrop(DWORD grfKeyState, LPDWORD pdwEffect)
{  
	ATLTRACE("CIDropTarget::QueryDrop\n");
	DWORD dwOKEffects = *pdwEffect; 

	if(!m_bAllowDrop)
	{
	   *pdwEffect = DROPEFFECT_NONE;
	   return false;
	}
	//CTRL+SHIFT  -- DROPEFFECT_LINK
	//CTRL        -- DROPEFFECT_COPY
	//SHIFT       -- DROPEFFECT_MOVE
	//no modifier -- DROPEFFECT_MOVE or whatever is allowed by src
 	*pdwEffect = (grfKeyState & MK_CONTROL) ?
				 ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_LINK : DROPEFFECT_COPY ):
				 ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_MOVE : 0 );
	if(*pdwEffect == 0) 
	{
	   // No modifier keys used by user while dragging. 
	   if (DROPEFFECT_COPY & dwOKEffects)
		  *pdwEffect = DROPEFFECT_COPY;
	   else if (DROPEFFECT_MOVE & dwOKEffects)
		  *pdwEffect = DROPEFFECT_MOVE; 
	   else if (DROPEFFECT_LINK & dwOKEffects)
		  *pdwEffect = DROPEFFECT_LINK; 
	   else 
	   {
		  *pdwEffect = DROPEFFECT_NONE;
	   }
	} 
	else
	{
	   // Check if the drag source application allows the drop effect desired by user.
	   // The drag source specifies this in DoDragDrop
	   if(!(*pdwEffect & dwOKEffects))
		  *pdwEffect = DROPEFFECT_NONE;
	}  

	return (DROPEFFECT_NONE == *pdwEffect)?false:true;
}   

HRESULT STDMETHODCALLTYPE CIDropTarget::DragEnter(
    /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
    /* [in] */ DWORD grfKeyState,
    /* [in] */ POINTL pt,
    /* [out][in] */ DWORD __RPC_FAR *pdwEffect)
{
	ATLTRACE("CIDropTarget::DragEnter\n");
	if(pDataObj == NULL)
		return E_INVALIDARG;

	if(m_pDropTargetHelper)
		m_pDropTargetHelper->DragEnter(m_hTargetWnd, pDataObj, (LPPOINT)&pt, *pdwEffect);
	//IEnumFORMATETC* pEnum;
	//pDataObj->EnumFormatEtc(DATADIR_GET,&pEnum);
	//FORMATETC ftm;
	//for()
	//pEnum->Next(1,&ftm,0);
	//pEnum->Release();
	m_pSupportedFrmt = NULL;
	for(int i =0; i<m_formatetc.GetSize(); ++i)
	{
		m_bAllowDrop = (pDataObj->QueryGetData(&m_formatetc[i]) == S_OK)?true:false;
		if(m_bAllowDrop)
		{
			m_pSupportedFrmt = &m_formatetc[i];
			break;
		}
	}

	QueryDrop(grfKeyState, pdwEffect);
	return S_OK;
}

HRESULT STDMETHODCALLTYPE CIDropTarget::DragOver( 
        /* [in] */ DWORD grfKeyState,
        /* [in] */ POINTL pt,
        /* [out][in] */ DWORD __RPC_FAR *pdwEffect)
{
	ATLTRACE("CIDropTarget::DragOver\n");
	if(m_pDropTargetHelper)
		m_pDropTargetHelper->DragOver((LPPOINT)&pt, *pdwEffect);
	QueryDrop(grfKeyState, pdwEffect);
	return S_OK;
}

HRESULT STDMETHODCALLTYPE CIDropTarget::DragLeave( void)
{
	ATLTRACE("CIDropTarget::DragLeave\n");

	if(m_pDropTargetHelper)
		m_pDropTargetHelper->DragLeave();
	
	m_bAllowDrop = false;
	m_pSupportedFrmt = NULL;
	return S_OK;
}

HRESULT STDMETHODCALLTYPE CIDropTarget::Drop(
	/* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
    /* [in] */ DWORD grfKeyState, /* [in] */ POINTL pt, 
	/* [out][in] */ DWORD __RPC_FAR *pdwEffect)
{
	ATLTRACE("CIDropTarget::Drop\n");
	if (pDataObj == NULL)
		return E_INVALIDARG;	

	if(m_pDropTargetHelper)
		m_pDropTargetHelper->Drop(pDataObj, (LPPOINT)&pt, *pdwEffect);

	if(QueryDrop(grfKeyState, pdwEffect))
	{
		if(m_bAllowDrop && m_pSupportedFrmt != NULL)
		{
			STGMEDIUM medium;
			if(pDataObj->GetData(m_pSupportedFrmt, &medium) == S_OK)
			{
				if(OnDrop(m_pSupportedFrmt, medium, pdwEffect)) //does derive class wants us to free medium?
					ReleaseStgMedium(&medium);
			}
		}
	}
	m_bAllowDrop=false;
	*pdwEffect = DROPEFFECT_NONE;
	m_pSupportedFrmt = NULL;
	return S_OK;
}

转载请注明:虚无 » 鼠标拖拽文件移动的实现(com 基于windos sdk)

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址