DragDrop.h
上传用户:sztopon
上传日期:2014-01-21
资源大小:55k
文件大小:20k
源码类别:

ListView/ListBox

开发平台:

Visual C++

  1. #pragma once
  2. #include <vector>
  3. #include <shlobj.h>
  4. using namespace std;
  5. class CEnumFormatEtc : public IEnumFORMATETC
  6. {
  7. public:
  8. CEnumFormatEtc( const vector < FORMATETC >& vFormatEtc )
  9. {
  10. m_nRefCount = 0;
  11. m_nIndex = 0;
  12. m_vFormatEtc = vFormatEtc;
  13. }
  14. protected:
  15. vector < FORMATETC > m_vFormatEtc;
  16. int m_nRefCount;
  17. int m_nIndex;
  18. public:
  19. // IUnknown members
  20. STDMETHOD(QueryInterface)( REFIID refiid, void FAR* FAR* ppvObject )
  21. {
  22. *ppvObject = ( refiid == IID_IUnknown || refiid == IID_IEnumFORMATETC ) ? this : NULL;
  23. if ( *ppvObject != NULL )
  24. ( (LPUNKNOWN)*ppvObject )->AddRef();
  25. return *ppvObject == NULL ? E_NOINTERFACE : S_OK;
  26. }
  27. STDMETHOD_(ULONG, AddRef)( void )
  28. {
  29. return ++m_nRefCount;
  30. }
  31. STDMETHOD_(ULONG, Release)( void )
  32. {
  33. int nRefCount = --m_nRefCount;
  34. if ( nRefCount == 0 )
  35. delete this;
  36. return nRefCount;
  37. }
  38. // IEnumFORMATETC members
  39. STDMETHOD(Next)( ULONG celt, LPFORMATETC lpFormatEtc, ULONG FAR *pceltFetched )
  40. {
  41. if ( pceltFetched != NULL )
  42. *pceltFetched=0;
  43. ULONG cReturn = celt;
  44. if ( celt <= 0 || lpFormatEtc == NULL || m_nIndex >= (int)m_vFormatEtc.size() )
  45. return S_FALSE;
  46. if ( pceltFetched == NULL && celt != 1 ) // pceltFetched can be NULL only for 1 item request
  47. return S_FALSE;
  48. while ( m_nIndex < (int)m_vFormatEtc.size() && cReturn > 0 )
  49. {
  50. *lpFormatEtc++ = m_vFormatEtc[ m_nIndex++ ];
  51. cReturn--;
  52. }
  53. if ( pceltFetched != NULL )
  54. *pceltFetched = celt - cReturn;
  55. return cReturn == 0 ? S_OK : S_FALSE;
  56. }
  57. STDMETHOD(Skip)( ULONG celt )
  58. {
  59. if ( ( m_nIndex + (int)celt ) >= (int)m_vFormatEtc.size() )
  60. return S_FALSE;
  61. m_nIndex += celt;
  62. return S_OK;
  63. }
  64. STDMETHOD(Reset)( void )
  65. {
  66. m_nIndex = 0;
  67. return S_OK;
  68. }
  69. STDMETHOD(Clone)( IEnumFORMATETC FAR * FAR* ppCloneEnumFormatEtc )
  70. {
  71. if ( ppCloneEnumFormatEtc == NULL )
  72. return E_POINTER;
  73. *ppCloneEnumFormatEtc = new CEnumFormatEtc( m_vFormatEtc );
  74. ( (CEnumFormatEtc*)*ppCloneEnumFormatEtc )->AddRef();
  75. ( (CEnumFormatEtc*)*ppCloneEnumFormatEtc )->m_nIndex = m_nIndex;
  76. return S_OK;
  77. }
  78. };
  79. class CDropSource : public IDropSource
  80. {
  81. public:
  82. CDropSource()
  83. {
  84. m_nRefCount = 0;
  85. }
  86. protected:
  87. int m_nRefCount;
  88. public:
  89. // IUnknown members
  90. STDMETHOD(QueryInterface)( REFIID refiid, void FAR* FAR* ppvObject )
  91. {
  92. *ppvObject = ( refiid == IID_IUnknown || refiid == IID_IDropSource ) ? this : NULL;
  93. if ( *ppvObject != NULL )
  94. ( (LPUNKNOWN)*ppvObject )->AddRef();
  95. return *ppvObject == NULL ? E_NOINTERFACE : S_OK;
  96. }
  97. STDMETHOD_(ULONG, AddRef)( void )
  98. {
  99. return ++m_nRefCount;
  100. }
  101. STDMETHOD_(ULONG, Release)( void )
  102. {
  103. int nRefCount = --m_nRefCount;
  104. if ( nRefCount == 0 )
  105. delete this;
  106. return nRefCount;
  107. }
  108. // IDropSource members
  109. STDMETHOD(QueryContinueDrag)( BOOL bEscapePressed, DWORD dwKeyState )
  110. {
  111. if ( bEscapePressed )
  112. return DRAGDROP_S_CANCEL;
  113. if ( !( dwKeyState & ( MK_LBUTTON | MK_RBUTTON ) ) )
  114. return DRAGDROP_S_DROP;
  115. return S_OK;
  116. }
  117.     STDMETHOD(GiveFeedback)( DWORD dwEffect )
  118.     {
  119. return DRAGDROP_S_USEDEFAULTCURSORS;
  120.     }
  121. };
  122. class CDataObject : public IDataObject
  123. {
  124. public:
  125. CDataObject( CDropSource *pDropSource )
  126. {
  127. m_nRefCount = 0;
  128. m_pDropSource = pDropSource;
  129. m_bSwappedButtons = GetSystemMetrics( SM_SWAPBUTTON );
  130. }
  131. virtual ~CDataObject()
  132. {
  133. for ( vector < STGMEDIUM >::iterator posStgMedium = m_vStgMedium.begin(); posStgMedium != m_vStgMedium.end(); posStgMedium++ )
  134. ReleaseStgMedium( &( *posStgMedium ) );
  135. }
  136. protected:
  137. CDropSource *m_pDropSource;
  138. int m_nRefCount;
  139. BOOL m_bSwappedButtons;
  140. vector < FORMATETC > m_vFormatEtc;
  141. vector < STGMEDIUM > m_vStgMedium;
  142. public:
  143. // IUnknown members
  144. STDMETHOD(QueryInterface)( REFIID refiid, void FAR* FAR* ppvObject )
  145. {
  146. *ppvObject = ( refiid == IID_IUnknown || refiid == IID_IDataObject ) ? this : NULL;
  147. if ( *ppvObject != NULL )
  148. ( (LPUNKNOWN)*ppvObject )->AddRef();
  149. return *ppvObject == NULL ? E_NOINTERFACE : S_OK;
  150. }
  151. STDMETHOD_(ULONG, AddRef)( void )
  152. {
  153. return ++m_nRefCount;
  154. }
  155. STDMETHOD_(ULONG, Release)( void )
  156. {
  157. int nRefCount = --m_nRefCount;
  158. if ( nRefCount == 0 )
  159. delete this;
  160. return nRefCount;
  161. }
  162. // IDataObject members
  163. STDMETHOD(GetData)( FORMATETC __RPC_FAR *pformatetcIn, STGMEDIUM __RPC_FAR *pmedium )
  164. {
  165. if ( pformatetcIn == NULL || pmedium == NULL )
  166. return E_INVALIDARG;
  167. ZeroMemory( pmedium, sizeof( STGMEDIUM ) );
  168. for ( int nFormatEtc = 0; nFormatEtc < (int)m_vFormatEtc.size(); nFormatEtc++ )
  169. {
  170. if ( pformatetcIn->tymed & m_vFormatEtc[ nFormatEtc ].tymed &&
  171.  pformatetcIn->dwAspect == m_vFormatEtc[ nFormatEtc ].dwAspect &&
  172.  pformatetcIn->cfFormat == m_vFormatEtc[ nFormatEtc ].cfFormat )
  173. {
  174. if ( m_vStgMedium[ nFormatEtc ].tymed == TYMED_NULL )
  175. return OnRenderData( m_vFormatEtc[ nFormatEtc ], pmedium, ( GetAsyncKeyState( m_bSwappedButtons ? VK_RBUTTON : VK_LBUTTON ) >= 0 ) ) ? S_OK : DV_E_FORMATETC;
  176. CopyMedium( pmedium, m_vStgMedium[ nFormatEtc ], m_vFormatEtc[ nFormatEtc ] );
  177. return S_OK;
  178. }
  179. }
  180. return DV_E_FORMATETC;
  181. }
  182. STDMETHOD(GetDataHere)( FORMATETC __RPC_FAR *pformatetc, STGMEDIUM __RPC_FAR *pmedium )
  183. {
  184. return E_NOTIMPL;
  185. }
  186. STDMETHOD(QueryGetData)( FORMATETC __RPC_FAR *pformatetc )
  187. {
  188. if ( pformatetc == NULL )
  189. return E_INVALIDARG;
  190. if ( !( pformatetc->dwAspect & DVASPECT_CONTENT ) )
  191. return DV_E_DVASPECT;
  192. HRESULT hResult = DV_E_TYMED;
  193. for ( int nFormatEtc = 0; nFormatEtc < (int)m_vFormatEtc.size(); nFormatEtc++ )
  194. {
  195. if ( !( pformatetc->tymed & m_vFormatEtc[ nFormatEtc ].tymed ) )
  196. {
  197. hResult = DV_E_TYMED;
  198. continue;
  199. }
  200. if ( pformatetc->cfFormat == m_vFormatEtc[ nFormatEtc ].cfFormat )
  201. return S_OK;
  202. hResult = DV_E_CLIPFORMAT;
  203. }
  204. return hResult;
  205. }
  206. STDMETHOD(GetCanonicalFormatEtc)( FORMATETC __RPC_FAR *pformatectIn, FORMATETC __RPC_FAR *pformatetcOut )
  207. {
  208. return pformatetcOut == NULL ? E_INVALIDARG : DATA_S_SAMEFORMATETC;
  209. }
  210.     
  211.     STDMETHOD(SetData)( FORMATETC __RPC_FAR *pformatetc, STGMEDIUM __RPC_FAR *pmedium, BOOL bRelease )
  212.     {
  213. if ( pformatetc == NULL || pmedium == NULL )
  214. return E_INVALIDARG;
  215. m_vFormatEtc.push_back( *pformatetc );
  216. STGMEDIUM StgMedium = *pmedium;
  217.  
  218. if ( !bRelease )
  219. CopyMedium( &StgMedium, *pmedium, *pformatetc );
  220. m_vStgMedium.push_back( StgMedium );
  221. return S_OK;
  222.     }
  223.     
  224.     STDMETHOD(EnumFormatEtc)( DWORD dwDirection, IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenumFormatEtc )
  225.     {
  226. if ( ppenumFormatEtc == NULL )
  227. return E_POINTER;
  228. switch ( dwDirection )
  229. {
  230. case DATADIR_GET: *ppenumFormatEtc = new CEnumFormatEtc( m_vFormatEtc );
  231. ( (CEnumFormatEtc*)*ppenumFormatEtc )->AddRef();
  232. return S_OK;
  233. default: *ppenumFormatEtc = NULL;
  234. return E_NOTIMPL;
  235. }
  236.     }
  237.     
  238.     STDMETHOD(DAdvise)( FORMATETC __RPC_FAR *pformatetc, DWORD advf, IAdviseSink __RPC_FAR *pAdvSink, DWORD __RPC_FAR *pdwConnection )
  239.     {
  240. return OLE_E_ADVISENOTSUPPORTED;
  241.     }
  242.     
  243.     STDMETHOD(DUnadvise)( DWORD dwConnection )
  244.     {
  245. return E_NOTIMPL;
  246.     }
  247.     
  248.     STDMETHOD(EnumDAdvise)( IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise )
  249.     {
  250. return OLE_E_ADVISENOTSUPPORTED;
  251.     }
  252.        
  253. void CopyMedium( STGMEDIUM *pMedDest, STGMEDIUM& MedSrc, FORMATETC& FmtSrc )
  254. {
  255. switch( MedSrc.tymed )
  256. {
  257. case TYMED_HGLOBAL: pMedDest->hGlobal = (HGLOBAL)OleDuplicateData( MedSrc.hGlobal, FmtSrc.cfFormat, NULL );
  258. break;
  259. case TYMED_GDI: pMedDest->hBitmap = (HBITMAP)OleDuplicateData( MedSrc.hBitmap, FmtSrc.cfFormat, NULL );
  260. break;
  261. case TYMED_MFPICT: pMedDest->hMetaFilePict = (HMETAFILEPICT)OleDuplicateData( MedSrc.hMetaFilePict, FmtSrc.cfFormat, NULL );
  262. break;
  263. case TYMED_ENHMF: pMedDest->hEnhMetaFile = (HENHMETAFILE)OleDuplicateData( MedSrc.hEnhMetaFile, FmtSrc.cfFormat, NULL );
  264. break;
  265. case TYMED_FILE: pMedDest->lpszFileName = (LPOLESTR)OleDuplicateData( MedSrc.lpszFileName, FmtSrc.cfFormat, NULL );
  266. break;
  267. case TYMED_ISTREAM: pMedDest->pstm = MedSrc.pstm;
  268. MedSrc.pstm->AddRef();
  269. break;
  270. case TYMED_ISTORAGE: pMedDest->pstg = MedSrc.pstg;
  271. MedSrc.pstg->AddRef();
  272. break;
  273. }
  274. pMedDest->tymed = MedSrc.tymed;
  275. pMedDest->pUnkForRelease = NULL;
  276. if ( MedSrc.pUnkForRelease != NULL )
  277. {
  278. pMedDest->pUnkForRelease = MedSrc.pUnkForRelease;
  279. MedSrc.pUnkForRelease->AddRef();
  280. }
  281. }
  282. virtual BOOL OnRenderData( FORMATETC& FormatEtc, STGMEDIUM *pStgMedium, BOOL bDropComplete )
  283. {
  284. return FALSE;
  285. }
  286. };
  287. class CDropTarget : public IDropTarget
  288. {
  289. public:
  290. CDropTarget( HWND hTargetWnd )
  291. {
  292. m_hTargetWnd = hTargetWnd;
  293. m_nRefCount = 0;
  294. m_bAllowDrop = FALSE;
  295. m_pDropTargetHelper = NULL;
  296. ZeroMemory( &m_FormatEtc, sizeof( FORMATETC ) );
  297. ZeroMemory( &m_StgMedium, sizeof( STGMEDIUM ) );
  298. if ( FAILED( CoCreateInstance( CLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper, (LPVOID*)&m_pDropTargetHelper ) ) )
  299. m_pDropTargetHelper = NULL;
  300. }
  301. virtual ~CDropTarget()
  302. {
  303. if ( m_pDropTargetHelper != NULL )
  304. {
  305. m_pDropTargetHelper->Release();
  306. m_pDropTargetHelper = NULL;
  307. }
  308. }
  309. protected:
  310. HWND m_hTargetWnd;
  311. int m_nRefCount;
  312. struct IDropTargetHelper *m_pDropTargetHelper;
  313. vector < FORMATETC > m_vFormatEtc;
  314. BOOL m_bAllowDrop;
  315. FORMATETC m_FormatEtc;
  316. STGMEDIUM m_StgMedium;
  317. public:
  318. // IUnknown members
  319. STDMETHOD(QueryInterface)( REFIID refiid, void FAR* FAR* ppvObject )
  320. {
  321. *ppvObject = ( refiid == IID_IUnknown || refiid == IID_IDropTarget ) ? this : NULL;
  322. if ( *ppvObject != NULL )
  323. ( (LPUNKNOWN)*ppvObject )->AddRef();
  324. return *ppvObject == NULL ? E_NOINTERFACE : S_OK;
  325. }
  326. STDMETHOD_(ULONG, AddRef)( void )
  327. {
  328. return ++m_nRefCount;
  329. }
  330. STDMETHOD_(ULONG, Release)( void )
  331. {
  332. int nRefCount = --m_nRefCount;
  333. if ( nRefCount == 0 )
  334. delete this;
  335. return nRefCount;
  336. }
  337. STDMETHOD(DragEnter)( IDataObject __RPC_FAR *pDataObject, DWORD dwKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect )
  338. {
  339. if ( pDataObject == NULL )
  340. return E_INVALIDARG;
  341. if ( m_pDropTargetHelper != NULL )
  342. m_pDropTargetHelper->DragEnter( m_hTargetWnd, pDataObject, (LPPOINT)&pt, *pdwEffect );
  343. ZeroMemory( &m_FormatEtc, sizeof( FORMATETC ) );
  344. if ( m_StgMedium.tymed != TYMED_NULL )
  345. ReleaseStgMedium( &m_StgMedium );
  346. ZeroMemory( &m_StgMedium, sizeof( STGMEDIUM ) );
  347. for ( int nFormatEtc = 0; nFormatEtc < (int)m_vFormatEtc.size(); nFormatEtc++ )
  348. {
  349. STGMEDIUM StgMedium;
  350. m_bAllowDrop = ( pDataObject->GetData( &m_vFormatEtc[ nFormatEtc ], &StgMedium ) == S_OK );
  351. if ( m_bAllowDrop )
  352. {
  353. // store drag data for later use in DragOver
  354. m_FormatEtc = m_vFormatEtc[ nFormatEtc ];
  355. m_StgMedium = StgMedium;
  356. // get client cursor position
  357. CWindow hWnd( m_hTargetWnd );
  358. CPoint point( pt.x, pt.y );
  359. hWnd.ScreenToClient( &point );
  360. *pdwEffect = OnDragEnter( m_FormatEtc, m_StgMedium, dwKeyState, point );
  361. break;
  362. }
  363. }
  364. QueryDrop( dwKeyState, pdwEffect );
  365. return S_OK;
  366. }
  367. STDMETHOD(DragOver)( DWORD dwKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect )
  368. {
  369. if ( m_pDropTargetHelper )
  370. m_pDropTargetHelper->DragOver( (LPPOINT)&pt, *pdwEffect );
  371. if ( m_bAllowDrop && m_FormatEtc.cfFormat != CF_NULL && m_StgMedium.tymed != TYMED_NULL )
  372. {
  373. // get client cursor position
  374. CWindow hWnd( m_hTargetWnd );
  375. CPoint point( pt.x, pt.y );
  376. hWnd.ScreenToClient( &point );
  377. *pdwEffect = OnDragOver( m_FormatEtc, m_StgMedium, dwKeyState, point );
  378. }
  379. QueryDrop( dwKeyState, pdwEffect );
  380. return S_OK;
  381. }
  382. STDMETHOD(DragLeave)( void )
  383. {
  384. if ( m_pDropTargetHelper )
  385. m_pDropTargetHelper->DragLeave();
  386. OnDragLeave();
  387. m_bAllowDrop = FALSE;
  388. ZeroMemory( &m_FormatEtc, sizeof( FORMATETC ) );
  389. if ( m_StgMedium.tymed != TYMED_NULL )
  390. ReleaseStgMedium( &m_StgMedium );
  391. ZeroMemory( &m_StgMedium, sizeof( STGMEDIUM ) );
  392. return S_OK;
  393. }
  394. STDMETHOD(Drop)( IDataObject __RPC_FAR *pDataObject, DWORD dwKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect )
  395.     {
  396. if ( pDataObject == NULL )
  397. return E_INVALIDARG;
  398. if ( m_pDropTargetHelper )
  399. m_pDropTargetHelper->Drop( pDataObject, (LPPOINT)&pt, *pdwEffect );
  400. if ( m_bAllowDrop && m_FormatEtc.cfFormat != CF_NULL && QueryDrop( dwKeyState, pdwEffect ) )
  401. {
  402. STGMEDIUM StgMedium;
  403. if ( pDataObject->GetData( &m_FormatEtc, &StgMedium ) == S_OK )
  404. {
  405. // get client cursor position
  406. CWindow hWnd( m_hTargetWnd );
  407. CPoint point( pt.x, pt.y );
  408. hWnd.ScreenToClient( &point );
  409. if ( !OnDrop( m_FormatEtc, StgMedium, *pdwEffect, point ) )
  410. *pdwEffect = DROPEFFECT_NONE;
  411. ReleaseStgMedium( &StgMedium );
  412. }
  413. }
  414. m_bAllowDrop = FALSE;
  415. ZeroMemory( &m_FormatEtc, sizeof( FORMATETC ) );
  416. if ( m_StgMedium.tymed != TYMED_NULL )
  417. ReleaseStgMedium( &m_StgMedium );
  418. ZeroMemory( &m_StgMedium, sizeof( STGMEDIUM ) );
  419. return S_OK;
  420.     }    
  421.     
  422.     void AddSupportedFormat( FORMATETC& FormatEtc )
  423. {
  424. m_vFormatEtc.push_back( FormatEtc );
  425. }
  426. void AddSupportedFormat( CLIPFORMAT cfFormat )
  427. {
  428. FORMATETC FormatEtc;
  429. ZeroMemory( &FormatEtc, sizeof( FORMATETC ) );
  430. FormatEtc.cfFormat = cfFormat;
  431. FormatEtc.dwAspect = DVASPECT_CONTENT;
  432. FormatEtc.lindex = -1;
  433. FormatEtc.tymed = TYMED_HGLOBAL;
  434. AddSupportedFormat( FormatEtc );
  435. }
  436. BOOL QueryDrop( DWORD dwKeyState, LPDWORD pdwEffect )
  437. {
  438. DWORD dwEffects = *pdwEffect; 
  439. if ( !m_bAllowDrop )
  440. {
  441. *pdwEffect = DROPEFFECT_NONE;
  442. return FALSE;
  443. }
  444. *pdwEffect = ( dwKeyState & MK_CONTROL ) ? ( ( dwKeyState & MK_SHIFT ) ? DROPEFFECT_LINK : DROPEFFECT_COPY ) : ( ( dwKeyState & MK_SHIFT ) ? DROPEFFECT_MOVE : 0 );
  445. if ( *pdwEffect == 0 ) 
  446. {
  447. if ( dwEffects & DROPEFFECT_COPY )
  448. *pdwEffect = DROPEFFECT_COPY;
  449. else if ( dwEffects & DROPEFFECT_MOVE )
  450. *pdwEffect = DROPEFFECT_MOVE; 
  451. else if (dwEffects & DROPEFFECT_LINK )
  452. *pdwEffect = DROPEFFECT_LINK; 
  453. else 
  454. *pdwEffect = DROPEFFECT_NONE;
  455. else if ( !( *pdwEffect & dwEffects ) )
  456. *pdwEffect = DROPEFFECT_NONE;
  457. return ( *pdwEffect != DROPEFFECT_NONE );
  458. }
  459. virtual DWORD OnDragEnter( FORMATETC& FormatEtc, STGMEDIUM& StgMedium, DWORD dwKeyState, CPoint point )
  460. {
  461. return FALSE;
  462. }
  463. virtual DWORD OnDragOver( FORMATETC& FormatEtc, STGMEDIUM& StgMedium, DWORD dwKeyState, CPoint point )
  464. {
  465. return FALSE;
  466. }
  467. virtual BOOL OnDrop( FORMATETC& FormatEtc, STGMEDIUM& StgMedium, DWORD dwEffect, CPoint point )
  468. {
  469. return FALSE;
  470. }
  471. virtual void OnDragLeave()
  472. {
  473. }
  474. };
  475. template < class T >
  476. class CDropTargetT : public CDropTarget
  477. {
  478. public:
  479. CDropTargetT( HWND hTargetWnd ) : CDropTarget( hTargetWnd )
  480. {
  481. m_pDelegate = NULL;
  482. }
  483. protected:
  484. T *m_pDelegate;
  485. public:
  486. BOOL Register( T *pDelegate )
  487. {
  488. m_pDelegate = pDelegate;
  489. return TRUE;
  490. }
  491. virtual DWORD OnDragEnter( FORMATETC& FormatEtc, STGMEDIUM& StgMedium, DWORD dwKeyState, CPoint point )
  492. {
  493. return m_pDelegate == NULL ? DROPEFFECT_NONE : m_pDelegate->OnDragEnter( FormatEtc, StgMedium, dwKeyState, point );
  494. }
  495. virtual DWORD OnDragOver( FORMATETC& FormatEtc, STGMEDIUM& StgMedium, DWORD dwKeyState, CPoint point )
  496. {
  497. return m_pDelegate == NULL ? DROPEFFECT_NONE : m_pDelegate->OnDragOver( FormatEtc, StgMedium, dwKeyState, point );
  498. }
  499. virtual BOOL OnDrop( FORMATETC& FormatEtc, STGMEDIUM& StgMedium, DWORD dwEffect, CPoint point )
  500. {
  501. return m_pDelegate == NULL ? FALSE : m_pDelegate->OnDrop( FormatEtc, StgMedium, dwEffect, point );
  502. }
  503. virtual void OnDragLeave()
  504. {
  505. if ( m_pDelegate != NULL )
  506. m_pDelegate->OnDragLeave();
  507. }
  508. };
  509. template < class T >
  510. class CDataObjectT : public CDataObject
  511. {
  512. public:
  513. CDataObjectT( CDropSource *pDropSource ) : CDataObject( pDropSource )
  514. {
  515. m_pDelegate = FALSE;
  516. }
  517. protected:
  518. T *m_pDelegate;
  519. public:
  520. BOOL Register( T *pDelegate )
  521. {
  522. m_pDelegate = pDelegate;
  523. return TRUE;
  524. }
  525. virtual BOOL OnRenderData( FORMATETC& FormatEtc, STGMEDIUM *pStgMedium, BOOL bDropComplete )
  526. {
  527. return m_pDelegate == NULL ? FALSE : m_pDelegate->OnRenderData( FormatEtc, pStgMedium, bDropComplete );
  528. }
  529. };
  530. template < class T >
  531. class CDragDrop
  532. {
  533. public:
  534. CDragDrop()
  535. {
  536. m_pDropSource = NULL;
  537. m_pDataObject = NULL;
  538. m_pDropTarget = NULL;
  539. m_hTargetWnd = NULL;
  540. }
  541. virtual ~CDragDrop()
  542. {
  543. if ( m_pDropSource != NULL )
  544. m_pDropSource->Release();
  545. if ( m_pDataObject != NULL )
  546. m_pDataObject->Release();
  547. }
  548. protected:
  549. CDropSource *m_pDropSource;
  550. CDataObjectT< T > *m_pDataObject;
  551. CDropTargetT< T > *m_pDropTarget;
  552. HWND m_hTargetWnd;
  553. public:
  554. BOOL Register( T *pDelegate, BOOL bDropSource = TRUE )
  555. {
  556. m_hTargetWnd = pDelegate->m_hWnd;
  557. // instantiate new drop target object
  558. m_pDropTarget = new CDropTargetT< T >( m_hTargetWnd );
  559. m_pDropTarget->Register( pDelegate );
  560. // register drop target
  561. if ( FAILED( RegisterDragDrop( m_hTargetWnd, m_pDropTarget ) ) )
  562. {
  563. m_pDropTarget = NULL;
  564. return FALSE;
  565. }
  566. // is this a drop target only?
  567. if ( !bDropSource )
  568. return TRUE;
  569. // instantiate new drop source object
  570. m_pDropSource = new CDropSource;
  571. m_pDropSource->AddRef();
  572. m_pDataObject = new CDataObjectT< T >( m_pDropSource );
  573. m_pDataObject->AddRef();
  574. // register drop source delegate for data render
  575. return m_pDataObject->Register( pDelegate );
  576. }
  577. BOOL Revoke()
  578. {
  579. m_pDropTarget = NULL;
  580. return ( RevokeDragDrop( m_hTargetWnd ) == S_OK );
  581. }
  582. BOOL AddTargetFormat( CLIPFORMAT cfFormat )
  583. {
  584. if ( m_pDropTarget == NULL )
  585. return FALSE;
  586. m_pDropTarget->AddSupportedFormat( cfFormat );
  587. return TRUE;
  588. }
  589. BOOL AddSourceFormat( CLIPFORMAT cfFormat )
  590. {
  591. if ( m_pDataObject == NULL )
  592. return FALSE;
  593. FORMATETC FormatEtc;
  594. ZeroMemory( &FormatEtc, sizeof( FORMATETC ) );
  595. FormatEtc.cfFormat = cfFormat;
  596. FormatEtc.dwAspect = DVASPECT_CONTENT;
  597. FormatEtc.lindex = -1;
  598. FormatEtc.tymed = TYMED_HGLOBAL;
  599. STGMEDIUM StgMedium;
  600. ZeroMemory( &StgMedium, sizeof( STGMEDIUM ) );
  601. return SUCCEEDED( m_pDataObject->SetData( &FormatEtc, &StgMedium, TRUE ) );
  602. }
  603. BOOL SetClipboard( FORMATETC& FormatEtc, STGMEDIUM& StgMedium )
  604. {
  605. if ( m_pDataObject == NULL )
  606. return DROPEFFECT_NONE;
  607. if ( FAILED( m_pDataObject->SetData( &FormatEtc, &StgMedium, TRUE ) ) )
  608. return DROPEFFECT_NONE;
  609. return ( OleSetClipboard( m_pDataObject ) == S_OK );
  610. }
  611. BOOL FlushClipboard()
  612. {
  613. return ( OleFlushClipboard() == S_OK );
  614. }
  615. DWORD DoDragDrop( SHDRAGIMAGE *pDragImage = NULL, DWORD dwValidEffects = DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK )
  616. {
  617. if ( m_pDataObject == NULL )
  618. return DROPEFFECT_NONE;
  619. IDragSourceHelper *pDragSourceHelper = NULL;
  620. // instantiate drag source helper object
  621. if ( pDragImage != NULL )
  622. {
  623. if ( FAILED( CoCreateInstance( CLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER, IID_IDragSourceHelper, (LPVOID*)&pDragSourceHelper ) ) )
  624. pDragSourceHelper = NULL;
  625. if ( pDragSourceHelper != NULL )
  626. pDragSourceHelper->InitializeFromBitmap( pDragImage, m_pDataObject );
  627. }
  628. DWORD dwEffects = DROPEFFECT_NONE;
  629. dwEffects = ::DoDragDrop( m_pDataObject, m_pDropSource, dwValidEffects, &dwEffects ) == DRAGDROP_S_DROP ? DROPEFFECT_NONE : dwEffects;
  630. // destroy drag source helper object
  631. if ( pDragSourceHelper != NULL )
  632. pDragSourceHelper->Release();
  633. return dwEffects;
  634. }
  635. };