示例#1
0
DWORD CMyTreeView::GetCurrentDragEffect(DWORD grfKeyState,DWORD dwCurrentEffect,POINTL *ptl)
{
	TVHITTESTINFO	tvhi;
	HTREEITEM		hItem;
	DWORD			dwEffect;
	BOOL			bOnSameDrive;

	tvhi.pt.x = ptl->x;
	tvhi.pt.y = ptl->y;
	ScreenToClient(m_hTreeView,&tvhi.pt);

	hItem = (HTREEITEM)SendMessage(m_hTreeView,TVM_HITTEST,0,(LPARAM)&tvhi);

	if(hItem != NULL)
	{
		bOnSameDrive = CheckItemLocations(m_pDataObject,hItem,0);

		dwEffect = DetermineDragEffect(grfKeyState,
			dwCurrentEffect,m_bDataAccept,bOnSameDrive);
	}
	else
	{
		dwEffect = DROPEFFECT_NONE;
	}

	return dwEffect;
}
HRESULT _stdcall CContainer::DragOver(DWORD grfKeyState,POINTL pt,DWORD *pdwEffect)
{
	TCHITTESTINFO HitTestInfo;
	BOOL bOnSameDrive;
	int iTab;

	HitTestInfo.pt.x	= pt.x;
	HitTestInfo.pt.y	= pt.y;

	ScreenToClient(m_hTabCtrl,&HitTestInfo.pt);

	iTab = TabCtrl_HitTest(m_hTabCtrl,&HitTestInfo);

	if(iTab == -1)
	{
		*pdwEffect = DROPEFFECT_NONE;
	}
	else
	{
		TCITEM tcItem;

		tcItem.mask	= TCIF_PARAM;
		TabCtrl_GetItem(m_hTabCtrl,iTab,&tcItem);

		if(iTab != m_iTabSelectedItem)
		{
			/* Set a timer. If the mouse does not move
			outside this tab before the timer expires,
			and the item is still been dragged, switch
			focus to this tab.
			The timer will be set if the tab the item
			is currently above does not match the
			tab it was above initially (when the timer
			was previously set). */
			if(iTab != m_iTabDragTab)
			{
				SetTimer(m_hTabCtrl,TABDRAG_TIMER_ID,TABDRAG_TIMER_ELAPSED,TabDragTimerProc);

				m_iTabDragTab = iTab;
			}
			else if(g_bTabDragTimerElapsed)
			{
				m_iTabSelectedItem = iTab;

				TabCtrl_SetCurSel(m_hTabCtrl,m_iTabSelectedItem);

				OnTabChangeInternal(TRUE);

				g_bTabDragTimerElapsed = FALSE;
			}
		}
		else
		{
			KillTimer(m_hTabCtrl,TABDRAG_TIMER_ID);
			m_iTabDragTab = iTab;
		}

		/* If the tab contains a virtual folder,
		then files cannot be dropped. */
		if(m_pShellBrowser[(int)tcItem.lParam]->InVirtualFolder())
		{
			*pdwEffect = DROPEFFECT_NONE;
		}
		else
		{
			bOnSameDrive = CheckItemLocations((int)tcItem.lParam);

			*pdwEffect = DetermineCurrentDragEffect(grfKeyState,
				*pdwEffect,m_bDataAccept,bOnSameDrive);
		}
	}

	m_pDropTargetHelper->DragOver((LPPOINT)&pt,*pdwEffect);

	return S_OK;
}
HRESULT _stdcall CContainer::DragEnter(IDataObject *pDataObject,
DWORD grfKeyState,POINTL pt,DWORD *pdwEffect)
{
	m_iTabDragTab = m_iTabSelectedItem;
	g_bTabDragTimerElapsed = FALSE;

	std::list<FORMATETC> ftcList;
	CDropHandler::GetDropFormats(&ftcList);

	BOOL bDataAccept = FALSE;

	/* Check whether the drop source has the type of data
	that is needed for this drag operation. */
	for each(auto ftc in ftcList)
	{
		if(pDataObject->QueryGetData(&ftc) == S_OK)
		{
			bDataAccept = TRUE;
			break;
		}
	}

	if(bDataAccept)
	{
		m_bDataAccept	= TRUE;

		GetSourceFileName(pDataObject);

		TCHITTESTINFO	tchi;
		TCITEM			tcItem;
		BOOL			bOnSameDrive;
		int				iTab;

		tchi.pt.x = pt.x;
		tchi.pt.y = pt.y;
		ScreenToClient(m_hTabCtrl,&tchi.pt);
		iTab = TabCtrl_HitTest(m_hTabCtrl,&tchi);

		if(iTab != -1)
		{
			tcItem.mask = TCIF_PARAM;
			TabCtrl_GetItem(m_hTabCtrl,iTab,&tcItem);

			bOnSameDrive = CheckItemLocations((int)tcItem.lParam);

			*pdwEffect = DetermineCurrentDragEffect(grfKeyState,
				*pdwEffect,m_bDataAccept,bOnSameDrive);
		}
		else
		{
			*pdwEffect = DROPEFFECT_NONE;
		}
	}
	else
	{
		m_bDataAccept	= FALSE;
		*pdwEffect		= DROPEFFECT_NONE;
	}

	if(grfKeyState & MK_LBUTTON)
		m_DragType = DRAG_TYPE_LEFTCLICK;
	else if(grfKeyState & MK_RBUTTON)
		m_DragType = DRAG_TYPE_RIGHTCLICK;

	m_pDropTargetHelper->DragEnter(m_hTabCtrl,pDataObject,(POINT *)&pt,*pdwEffect);

	return S_OK;
}
/* Loop through each of the dropped files. Add them to
the list of files that are to be copied. Then, copy the
files themselves in a separate background thread,
update the filename list if any files were renamed
(due to a collision), and then send the list back
to the callee.

Differences between drag and drop/paste:
 - Effect may already be specified on paste.
 - No drop point used when pasting files.
*/
void CDropHandler::CopyDroppedFiles(DROPFILES *pdf,BOOL bPreferredEffect,DWORD dwPreferredEffect)
{
	IBufferManager *pbmCopy = NULL;
	IBufferManager *pbmMove = NULL;
	list<PastedFile_t> PastedFileListCopy;
	list<PastedFile_t> PastedFileListMove;
	PastedFile_t PastedFile;
	TCHAR szFullFileName[MAX_PATH];
	TCHAR szSourceDirectory[MAX_PATH];
	DWORD dwEffect;
	BOOL bRenameOnCollision = m_bRenameOnCollision;
	int nDroppedFiles;
	int i = 0;

	pbmCopy = new CBufferManager();
	pbmMove = new CBufferManager();

	nDroppedFiles = DragQueryFile((HDROP)pdf,0xFFFFFFFF,NULL,NULL);

	for(i = 0;i < nDroppedFiles;i++)
	{
		/* Determine the name of the dropped file. */
		DragQueryFile((HDROP)pdf,i,szFullFileName,
			SIZEOF_ARRAY(szFullFileName));

		StringCchCopy(szSourceDirectory,SIZEOF_ARRAY(szSourceDirectory),szFullFileName);
		PathRemoveFileSpec(szSourceDirectory);

		/* Force files to be renamed when they are copied and pasted
		in the same directory. */
		if(lstrcmpi(m_szDestDirectory,szSourceDirectory) == 0)
		{
			bRenameOnCollision = TRUE;
		}

		if(bPreferredEffect)
		{
			dwEffect = dwPreferredEffect;
		}
		else
		{
			BOOL bOnSameDrive;

			/* If no preferred drop effect is specified,
			decide whether to copy/move files based on their
			locations. */
			bOnSameDrive = CheckItemLocations(i);

			dwEffect = DetermineCurrentDragEffect(m_grfKeyState,
			*m_pdwEffect,TRUE,bOnSameDrive);
		}

		StringCchCopy(PastedFile.szFileName,SIZEOF_ARRAY(PastedFile.szFileName),
			szFullFileName);
		PathStripPath(PastedFile.szFileName);

		if(dwEffect & DROPEFFECT_MOVE)
		{
			pbmMove->WriteListEntry(szFullFileName);
			PastedFileListMove.push_back(PastedFile);
		}
		else if(dwEffect & DROPEFFECT_COPY)
		{
			pbmCopy->WriteListEntry(szFullFileName);
			PastedFileListCopy.push_back(PastedFile);
		}
		else if(dwEffect & DROPEFFECT_LINK)
		{
			CreateShortcutToDroppedFile(szFullFileName);
		}
	}

	CopyDroppedFilesInternal(pbmCopy,&PastedFileListCopy,TRUE,bRenameOnCollision);
	CopyDroppedFilesInternal(pbmMove,&PastedFileListMove,FALSE,bRenameOnCollision);

	pbmCopy->Release();
	pbmMove->Release();
}