为了实现将自己窗口中的文件,或者文件夹从自己本身的客户端窗口拖动到其他的客户端窗口,或者系统窗口中实现系统的拖动效果;需要对系统接口 IDropSource,IDataObject,IDropTarget 重写
代码如下:
IDropSource,IDataObject,IDropTarget 重写头文件
// 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
#include
namespace DropSpace {
typedef std::vector FormatEtcArray;
typedef std::vector PFormatEtcArray;
typedef std::vector PStgMediumArray;
///////////////////////////////////////////////////////////////////////////////////////////////
class CEnumFormatEtc : public IEnumFORMATETC
{
private:
ULONG m_cRefCount;
FormatEtcArray m_pFmtEtc;
size_t m_iCur;
public:
CEnumFormatEtc(const FormatEtcArray& ArrFE);
CEnumFormatEtc(const PFormatEtcArray& ArrFE);
//IUnknown members
STDMETHOD(QueryInterface)(REFIID, void FAR* FAR*);
STDMETHOD_(ULONG, AddRef)(void);
STDMETHOD_(ULONG, Release)(void);
//IEnumFORMATETC members
STDMETHOD(Next)(ULONG, LPFORMATETC, ULONG FAR *);
STDMETHOD(Skip)(ULONG);
STDMETHOD(Reset)(void);
STDMETHOD(Clone)(IEnumFORMATETC FAR * FAR*);
};
///////////////////////////////////////////////////////////////////////////////////////////////
class CIDropSource : public IDropSource
{
long m_cRefCount;
public:
bool m_bDropped;
CIDropSource():m_cRefCount(0),m_bDropped(false) {}
//IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef( void);
virtual ULONG STDMETHODCALLTYPE Release( void);
//IDropSource
virtual HRESULT STDMETHODCALLTYPE QueryContinueDrag(
/* [in] */ BOOL fEscapePressed,
/* [in] */ DWORD grfKeyState);
virtual HRESULT STDMETHODCALLTYPE GiveFeedback(
/* [in] */ DWORD dwEffect);
};
///////////////////////////////////////////////////////////////////////////////////////////////
class CIDataObject : public IDataObject//,public IAsyncOperation
{
CIDropSource* m_pDropSource;
long m_cRefCount;
PFormatEtcArray m_ArrFormatEtc;
PStgMediumArray m_StgMedium;
public:
CIDataObject(CIDropSource* pDropSource);
~CIDataObject();
void CopyMedium(STGMEDIUM* pMedDest, STGMEDIUM* pMedSrc, FORMATETC* pFmtSrc);
//IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef( void);
virtual ULONG STDMETHODCALLTYPE Release( void);
//IDataObject
virtual /* [local] */ HRESULT STDMETHODCALLTYPE GetData(
/* [unique][in] */ FORMATETC __RPC_FAR *pformatetcIn,
/* [out] */ STGMEDIUM __RPC_FAR *pmedium);
virtual /* [local] */ HRESULT STDMETHODCALLTYPE GetDataHere(
/* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
/* [out][in] */ STGMEDIUM __RPC_FAR *pmedium);
virtual HRESULT STDMETHODCALLTYPE QueryGetData(
/* [unique][in] */ FORMATETC __RPC_FAR *pformatetc);
virtual HRESULT STDMETHODCALLTYPE GetCanonicalFormatEtc(
/* [unique][in] */ FORMATETC __RPC_FAR *pformatectIn,
/* [out] */ FORMATETC __RPC_FAR *pformatetcOut);
virtual /* [local] */ HRESULT STDMETHODCALLTYPE SetData(
/* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
/* [unique][in] */ STGMEDIUM __RPC_FAR *pmedium,
/* [in] */ BOOL fRelease);
virtual HRESULT STDMETHODCALLTYPE EnumFormatEtc(
/* [in] */ DWORD dwDirection,
/* [out] */ IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenumFormatEtc);
virtual HRESULT STDMETHODCALLTYPE DAdvise(
/* [in] */ FORMATETC __RPC_FAR *pformatetc,
/* [in] */ DWORD advf,
/* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink,
/* [out] */ DWORD __RPC_FAR *pdwConnection);
virtual HRESULT STDMETHODCALLTYPE DUnadvise(
/* [in] */ DWORD dwConnection);
virtual HRESULT STDMETHODCALLTYPE EnumDAdvise(
/* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise);
//IAsyncOperation
//virtual HRESULT STDMETHODCALLTYPE SetAsyncMode(
// /* [in] */ BOOL fDoOpAsync)
//{
// return E_NOTIMPL;
//}
//
//virtual HRESULT STDMETHODCALLTYPE GetAsyncMode(
// /* [out] */ BOOL __RPC_FAR *pfIsOpAsync)
//{
// return E_NOTIMPL;
//}
//
//virtual HRESULT STDMETHODCALLTYPE StartOperation(
// /* [optional][unique][in] */ IBindCtx __RPC_FAR *pbcReserved)
//{
// return E_NOTIMPL;
//}
//
//virtual HRESULT STDMETHODCALLTYPE InOperation(
// /* [out] */ BOOL __RPC_FAR *pfInAsyncOp)
//{
// return E_NOTIMPL;
//}
//
//virtual HRESULT STDMETHODCALLTYPE EndOperation(
// /* [in] */ HRESULT hResult,
// /* [unique][in] */ IBindCtx __RPC_FAR *pbcReserved,
// /* [in] */ DWORD dwEffects)
//{
// return E_NOTIMPL;
//}
};
///////////////////////////////////////////////////////////////////////////////////////////////
class CIDropTarget : public IDropTarget
{
DWORD m_cRefCount;
bool m_bAllowDrop;
struct IDropTargetHelper *m_pDropTargetHelper;
FormatEtcArray m_formatetc;
FORMATETC* m_pSupportedFrmt;
protected:
HWND m_hTargetWnd;
public:
CIDropTarget(HWND m_hTargetWnd = NULL);
virtual ~CIDropTarget();
void AddSuportedFormat(FORMATETC& ftetc) { m_formatetc.push_back(ftetc); }
void SetTargetWnd(HWND hWnd) { m_hTargetWnd = hWnd; }
//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) { 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__
拖出文件封装:
#pragma once
/**
* @brief
* @brief
* @brief
*/
#include
#include
#include
#include "DragDropImpl.h"
using namespace std;
using namespace DropSpace;
struct DragHelper_FileSizeItem
{
wstring strName;
int nSize;
};
class CDropHelper
{
public:
CDropHelper();
~CDropHelper();
/**
* @brief 将文件列表拖动到其他程序窗口
* @param[in] POINT pt
* @param[in] RECT rc
* @param[in] HBITMAP hBitMap 拖动图标显示
* @param[in] std::list listFile 拖动文件列表
* @return 无
*/
void DragOutFile(POINT pt, RECT rc, HBITMAP hBitMap, std::list listFile);
/*
* @brief 计算拖动文件名转换为DROPFILES的总长度
* @param[in] std::list listFile 需要转换的文件列表
* @param[out] std::list listFileSize 单个Item 文件名对应大小
* @return int 拖动文件名转换为DROPFILES的总长度
*/
int CalFileListLen( std::list listFile , std::list& listFileSize);
/*
* @brief 将文件列表拷贝到 DROPFILES 文件列表区域内存
* @param[in] std::list &listSize 文件列表
* @param[out] char* pData DROPFILES 文件列表区域内存首地址
* @return
*/
void CopyFileListIntoDropFiles(char* pData, std::list &listSize);
private:
};
效果图: