www.pudn.com > ShortCutEx.rar > DropTarget.cpp, change:2004-07-30,size:4690b


// DropTarget.cpp: implementation of the CDropTarget class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "DropTarget.h" 
 
//#include <ShlDisp.h> 
#include <shlobj.h> 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CDropTarget::CDropTarget(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; 
} 
 
CDropTarget::~CDropTarget() 
{ 
	if(m_pDropTargetHelper != NULL) 
	{ 
		m_pDropTargetHelper->Release(); 
		m_pDropTargetHelper = NULL; 
	} 
} 
 
HRESULT STDMETHODCALLTYPE CDropTarget::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; 
} 
 
DWORD STDMETHODCALLTYPE CDropTarget::Release( void) 
{ 
   long nTemp; 
   nTemp = --m_cRefCount; 
   ATLASSERT(nTemp >= 0); 
   if(nTemp==0) 
	  delete this; 
   return nTemp; 
} 
 
HRESULT STDMETHODCALLTYPE CDropTarget::DragEnter( 
    /* [unique][in] */ IDataObject __RPC_FAR *pDataObj, 
    /* [in] */ DWORD grfKeyState, 
    /* [in] */ POINTL pt, 
    /* [out][in] */ DWORD __RPC_FAR *pdwEffect) 
{ 
	if(pDataObj == NULL) 
		return E_INVALIDARG; 
 
	if(m_pDropTargetHelper) 
		m_pDropTargetHelper->DragEnter(m_hTargetWnd, pDataObj, (LPPOINT)&pt, *pdwEffect); 
 
	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 CDropTarget::DragOver(  
        /* [in] */ DWORD grfKeyState, 
        /* [in] */ POINTL pt, 
        /* [out][in] */ DWORD __RPC_FAR *pdwEffect) 
{ 
	if(m_pDropTargetHelper) 
		m_pDropTargetHelper->DragOver((LPPOINT)&pt, *pdwEffect); 
	QueryDrop(grfKeyState, pdwEffect); 
	return S_OK; 
} 
 
HRESULT STDMETHODCALLTYPE CDropTarget::DragLeave( void) 
{ 
	if(m_pDropTargetHelper) 
		m_pDropTargetHelper->DragLeave(); 
	 
	m_bAllowDrop = false; 
	m_pSupportedFrmt = NULL; 
	return S_OK; 
} 
 
HRESULT STDMETHODCALLTYPE CDropTarget::Drop( 
	/* [unique][in] */ IDataObject __RPC_FAR *pDataObj, 
    /* [in] */ DWORD grfKeyState, /* [in] */ POINTL pt,  
	/* [out][in] */ DWORD __RPC_FAR *pdwEffect) 
{ 
	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; 
} 
 
bool CDropTarget::QueryDrop(DWORD grfKeyState, LPDWORD pdwEffect) 
{   
	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; 
}