DragDrop.cpp
上传用户:hy_wanghao
上传日期:2007-01-08
资源大小:279k
文件大小:7k
- // DragDrop.cpp : Implementation of CFolder's drag'n'drop functions
- #include "stdafx.h"
- #include "Folder.h"
- #include "Misc.h"
- #include "DataObject.h"
- /////////////////////////////////////////////////////////////////////////////
- // CFolder
- // Check if the Window handle belongs to a CView view.
- // We can do this because we know the Windows classname of the view window.
- BOOL CFolder::_IsViewWindow(HWND hWnd)
- {
- if( !::IsWindow(hWnd) ) return FALSE;
- CResString<64> sViewClassName(IDS_CLASSNAME);
- TCHAR szClassName[64];
- ::GetClassName(hWnd, szClassName, lengthof(szClassName));
- return( _tcsicmp(szClassName, sViewClassName)==0 );
- }
- // Sends a Windows message to a possible CView window.
- // The method doesn't guarantee that the message is sent if the passed
- // HWND handle is not a CView window.
- // Returns:
- // TRUE - the message was successfully sent
- // FALSE - the window was not a CView window. Message not sent.
- BOOL CFolder::_SendViewMessage(HWND hWnd, UINT iMsg, WPARAM wParam/*=0*/, LPARAM lParam/*=0*/)
- {
- if( !_IsViewWindow(hWnd) ) return FALSE;
- ::SendMessage(hWnd, iMsg, wParam, lParam);
- return TRUE;
- }
- // Check if the IDataObject originates from this folder.
- // We use the internal ADFID clipboard format to determine this.
- BOOL CFolder::_IsDroppedPathSame(LPDATAOBJECT pDataObj)
- {
- ATLASSERT(pDataObj);
- // Query the IDataObject for the private clipboard format "AdfID".
- // Only folders from "ADF View" will know about it and return a
- // folder ID...
- DWORD dwFolderID;
- HRESULT Hr = DataObj_GetDWORD(pDataObj, _Module.m_CFSTR_ADFID, &dwFolderID);
- if( FAILED(Hr) ) return FALSE;
- return dwFolderID==m_dwFolderID; // Same ID? Then same CFolder...
- }
- // We support two kinds of clipboard formats for drops.
- // The standard HDROP and also CFSTR_FILEDESCRIPTOR. The latter
- // is also used internally by ADF View to copy Amiga files.
- // Returns:
- // S_OK - all files were successfully copied/moved
- // S_FALSE - one or more file operations were cancelled
- // E_FAIL - an error occured
- // E_INVALIDARG - no good clipformat was available
- HRESULT CFolder::_DoDrop(LPDATAOBJECT pDataObj, DWORD dwDropEffect)
- {
- VALIDATE_POINTER(pDataObj);
- // Are we trying to paste to same folder? Not allowed in this Shell Extension.
- if( _IsDroppedPathSame(pDataObj) ) return E_FAIL;
- HRESULT Hr = E_INVALIDARG;
- STGMEDIUM stgmed;
- // Check for HDROP
- FORMATETC fe1 = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
- if( SUCCEEDED( pDataObj->GetData(&fe1, &stgmed) ) ) {
- Hr = _DoDrop_HDROP(stgmed.hGlobal, dwDropEffect);
- ::ReleaseStgMedium(&stgmed);
- return Hr;
- }
- // Check for CFSTR_FILEDESCRIPTOR
- FORMATETC fe2 = { _Module.m_CFSTR_FILEDESCRIPTOR, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
- if( SUCCEEDED( pDataObj->GetData(&fe2, &stgmed) ) ) {
- Hr = _DoDrop_FILEDESCRIPTOR(stgmed.hGlobal, pDataObj, dwDropEffect);
- ::ReleaseStgMedium(&stgmed);
- return Hr;
- }
- return Hr;
- }
- HRESULT CFolder::_DoDrop_HDROP(HGLOBAL hMem, DWORD dwDropEffect)
- {
- VALIDATE_POINTER(hMem);
- HRESULT HrRes = S_OK;
- HRESULT Hr;
- // Get target path
- CShellPidlPath szPath(m_pidl);
- DWORD dwFileOpFlags = 0;
- // Iterate over HDROP information
- HDROP hDrop = (HDROP)::GlobalLock(hMem);
- if( hDrop==NULL ) return E_OUTOFMEMORY;
- UINT nFiles = ::DragQueryFile(hDrop, (UINT)-1, NULL, 0);
- for( UINT i=0; i<nFiles; i++ ) {
- // Get dragged filename
- TCHAR szFileName[MAX_PATH];
- if( ::DragQueryFile(hDrop, i, szFileName, MAX_PATH)==0 ) return E_FAIL;
- if( ::PathIsDirectory(szFileName) ) {
- //
- // Handle Directory
- //
- TCHAR szStrippedFileName[MAX_PATH];
- _tcscpy( szStrippedFileName, szFileName );
- ::PathStripPath(szStrippedFileName);
- HR( _CreateFolder(szStrippedFileName, &dwFileOpFlags) );
- if( dwDropEffect==DROPEFFECT_MOVE ) ::RemoveDirectory(szFileName); // BUG: Will/cannot not recursive delete
- }
- else {
- //
- // Handle File
- //
- TCHAR szTargetName[MAX_PATH];
- _tcscpy(szTargetName, szFileName);
- ::PathStripPath(szTargetName);
- // Move or Copy file...
- if( dwDropEffect==DROPEFFECT_MOVE ) {
- Hr = _MoveFile(szFileName, szPath, szTargetName, &dwFileOpFlags);
- }
- else {
- Hr = _CopyFile(szFileName, szPath, szTargetName, &dwFileOpFlags);
- }
- }
- if( Hr!=S_OK ) HrRes = Hr;
- // If CANCEL was chosen, exit now...
- if( dwFileOpFlags & FILEOP_CANCEL ) break;
- }
- ::GlobalUnlock(hDrop);
- return HrRes;
- }
- HRESULT CFolder::_DoDrop_FILEDESCRIPTOR(HGLOBAL hMem, IDataObject *pDataObj, DWORD dwDropEffect)
- {
- VALIDATE_POINTER(hMem);
- VALIDATE_POINTER(pDataObj);
- dwDropEffect;
- HRESULT HrRes = S_OK;
- HRESULT Hr;
- CShellPidlPath szPath(m_pidl);
- FILEGROUPDESCRIPTOR *pFGD = (FILEGROUPDESCRIPTOR *)::GlobalLock(hMem);
- if( pFGD==NULL ) return E_OUTOFMEMORY;
- DWORD dwFileOpFlags = 0;
- for( UINT i=0; i<pFGD->cItems; i++ ) {
- FILEDESCRIPTOR fd = pFGD->fgd[i];
-
- DWORD dwFlags = FILE_ATTRIBUTE_NORMAL;
- if( fd.dwFlags & FD_ATTRIBUTES ) dwFlags = fd.dwFileAttributes;
- if( dwFlags & FILE_ATTRIBUTE_DIRECTORY ) {
- //
- // Handle directory
- //
- HR( _CreateFolder(fd.cFileName, &dwFileOpFlags) );
- }
- else {
- //
- // Copy file contents
- //
- FORMATETC fe = { _Module.m_CFSTR_FILECONTENTS, NULL, DVASPECT_CONTENT, i, TYMED_ISTREAM };
- STGMEDIUM stgmed;
- HR( pDataObj->GetData(&fe, &stgmed) );
- // This drag operation gives us an IStream back. To be able to reuse the
- // copy/move code, we write the IStream contents to a file and pass
- // it on. When the temporary file has been copied to the Amiga file system,
- // we delete it again.
- CComQIPtr<IStream> spStream( stgmed.pstm );
- if( spStream==NULL ) return E_POINTER;
- CTemporaryFile f;
- TCHAR szFileName[MAX_PATH];
- if( f.Create(szFileName, MAX_PATH)==FALSE ) return E_FAIL;
- BYTE buf[512];
- DWORD dwRead;
- while( spStream->Read(&buf, sizeof(buf), &dwRead), dwRead!=0 ) {
- f.Write(buf, dwRead);
- }
- f.Close();
- // Set new file's attributes
- ::SetFileAttributes(szFileName, dwFlags);
- // Copy the new temporary file to the Amiga disk
- // (Use _CopyFile() and do the delete ourselves, because _MoveFile() may be
- // cancelled and might not delete the file)
- Hr = _CopyFile(szFileName, szPath, fd.cFileName, &dwFileOpFlags);
- // Be sure we can delete the temporary file again.
- // (Note the file is deleted when CTemporaryFile goes out of scope)
- ::SetFileAttributes(szFileName, FILE_ATTRIBUTE_NORMAL);
- }
- if( Hr!=S_OK ) HrRes = Hr;
- // If CANCEL was chosen, exit now...
- if( dwFileOpFlags & FILEOP_CANCEL ) break;
- }
- ::GlobalUnlock(hMem);
- return HrRes;
- }