Von CTreeCtrl per Drag & Drop auf Desktop

CodeFatal

Erfahrenes Mitglied
Hallo,

kann mir jemand von euch verraten, wie ich es schaffen, einen selektierten Eintrag eines CTreeCtrls auf den Desktop - oder anderen beliebigen Ordner - zu dropen? Innerhalb des CTreeCtrls kann ich bereits per Drag & Drop die Elemente verschieben. Ich kann auch bestimmte Dateien vom Desktop auf den CTreeCtrl ziehen und entsprechend verarbeiten.

Nur der Weg vom CTreeCtrl zur Datei will noch nicht.

Eine ordentliche Suche war bisher leider erfolglos.

Danke für eure Hilfe

Gruß
Michael
 

Endurion

Erfahrenes Mitglied
Au, bei sowas wird es häßlich. Das Stichwort ist DropContext. Ich habe mir vor ein paar Jahren da mal was zusammengeklaubt, um spaßhalber ein Zip-Program zu basteln. Da konnte man auch von einem ListView Dateien auf den Desktop oder Explorer ziehen. Anbei einige Basisfiles und hier der Code zum Draggen/Droppen.

Das ist der Code jetzt direkt rausgerissen, aber du müßtest dir da alles Notwendige zusammenreimen können:

Code:
            CDropSource*    pDropSource = NULL;

            POSITION pos = m_listFiles.GetFirstSelectedItemPosition();

            std::vector<tFileInfo*>    vectFileInfos;

            while ( pos )
            {
              int   iItem = m_listFiles.GetNextSelectedItem( pos );

              tFileInfo*    pFileInfo = (tFileInfo*)m_listFiles.GetItemData( iItem );

              vectFileInfos.push_back( pFileInfo );
            }

             
            CDropSource* pTempDropSource = new CDropSource;

            HRESULT hr = pTempDropSource->QueryInterface( IID_IDropSource, (void FAR* FAR*)&pDropSource );

            LPDATAOBJECT      pIDataObject;

            CDragDropDataObject*  pTempObject;

		        FORMATETC         fe;
		        STGMEDIUM         stm;

		        memset((void far *)&stm,0,sizeof(stm));
		        stm.tymed = TYMED_HGLOBAL;
		        stm.hGlobal = NULL; // data will be provided in DataObject::GetData delayed rendering

            pTempObject = new CDragDropDataObject;
		        hr = pTempObject->QueryInterface(IID_IDataObject,(void FAR* FAR*)&pIDataObject);
		        if(SUCCEEDED(hr))
		        {
			        memset((void far *)&fe,0,sizeof(fe));
        			
			        fe.tymed = TYMED_HGLOBAL;            
			        fe.ptd = NULL;            
			        fe.lindex = -1;            
			        fe.dwAspect = DVASPECT_CONTENT;

			        // set the File Contents format
              /*
			        if(bSupportFileContents)            
			        {
                    fe.cfFormat = g_cfFileContents;
                    pIDataObject->SetData(&fe,&stm,TRUE);

                    fe.cfFormat = g_cfFileGroupDescriptor;
                    pIDataObject->SetData(&fe,&stm,TRUE);
			        }

			        // set the ShellIDList format
			        if(bSupportFileName)            
			        {
                    fe.cfFormat = g_cfFileName;
                    pIDataObject->SetData(&fe,&stm,TRUE);
			        }

			        // set the ShellIDList format
			        if(bSupportShellIDList)            
			        {
				        fe.cfFormat = g_cfShellIDList;
				        pIDataObject->SetData(&fe,&stm,TRUE);
			        }
			        // set the CF_HDROP format
              */
        			
			        //if(bSupportHDROP)
			        {
				        fe.cfFormat = CF_HDROP;

                {

	                // for my sample I am assuming number of files as 2 
 	                int cnt = (int)vectFileInfos.size();
	                // allocate space for DROPFILE structure plus the number of file and one extra byte for final NULL terminator
	                stm.hGlobal = GlobalAlloc(GHND|GMEM_SHARE,(DWORD) (sizeof(DROPFILES)+(_MAX_PATH)*cnt+1));
                  /*
	                if(stm.hGlobal == NULL)
			                return hGlobal;
                      */

	                LPDROPFILES pDropFiles;
	                pDropFiles = (LPDROPFILES)GlobalLock(stm.hGlobal);
	                // set the offset where the starting point of the file start
   	                pDropFiles->pFiles = sizeof(DROPFILES);
	                // file contains wide characters
   	                pDropFiles->fWide=FALSE;

	                int CurPosition = sizeof(DROPFILES);
	                for (int i = 0;i < cnt;i++)
	                {
                    tFileInfo*    pFileInfo = vectFileInfos[i];

                    std::string   strTempFile = CreateTempFile( pFileInfo );

                    m_mapDragDropTempFiles[pFileInfo] = strTempFile;

                    lstrcpy( (LPSTR)( (LPSTR)( pDropFiles ) + CurPosition ), strTempFile.c_str() );

		                // move the current position beyond the file name copied
		                // don't forget the Null terminator (+1)
                    CurPosition += (int)strTempFile.length() + 1;
	                }
	                // final null terminator as per CF_HDROP Format specs.
	                ((LPSTR)pDropFiles)[CurPosition]=0;
	                GlobalUnlock(stm.hGlobal);
                }

                //extern HGLOBAL CreateHDrop();
                //stm.hGlobal = CreateHDrop();
				        pIDataObject->SetData(&fe,&stm,TRUE);
			        }

              pDropSource->AddListener( this );

			        // start the do drag drop
              m_bDraggingSource = true;
              DragAcceptFiles( FALSE );

              DWORD   dwEffect = 0;
			        hr = DoDragDrop( pIDataObject, pDropSource, DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK , &dwEffect );
			        if(!SUCCEEDED(hr))
			        {
        //				OutputDebugString(" Drag Drop failed \n");
			        }
			        pIDataObject->Release();

              DragAcceptFiles();
              m_bDraggingSource = false;
            }

            pDropSource->Release();

Der Listener ruft nachher eine Event-Methode auf, dort kann man auf das Drop-Ergebnis reagieren:

Code:
bool CDlgMain::ProcessEvent( const tDropEvent& Event )
{

  switch ( Event.m_Type )
  {
    case tDropEvent::DE_DROPPED:
      {
        EnterWorkMode();

        m_statusBar.SetPaneText( 0, "Extracting..." );

        tMapDragDropTempFiles::iterator   it( m_mapDragDropTempFiles.begin() );
        while ( it != m_mapDragDropTempFiles.end() )
        {
          tFileInfo*    pFileInfo = it->first;

          std::string   strTempFileName = it->second;

          /*
          dh::Log( "Erzeuge für Datei %s", pFileInfo->m_strFileName.c_str() );
          dh::Log( "-Temp %s", strTempFileName.c_str() );
          */

          if ( pFileInfo->m_bFolder )
          {
            size_t    iPos = std::string::npos;

            while ( ( iPos = strTempFileName.find( '/' ) ) != std::string::npos )
            {
              strTempFileName[iPos] = '\\';
            }

            ExtractFolder( pFileInfo, Path::RemoveFileSpec( strTempFileName ) );
          }
          else
          {
            ExtractFile( pFileInfo, Path::RemoveFileSpec( strTempFileName ) );
          }

          ++it;
        }
        m_mapDragDropTempFiles.clear();

        LeaveWorkMode();
      }
      break;
    case tDropEvent::DE_CANCELLED:
      {
        EnterWorkMode();
        tMapDragDropTempFiles::iterator   it( m_mapDragDropTempFiles.begin() );
        while ( it != m_mapDragDropTempFiles.end() )
        {
          tFileInfo*    pFileInfo = it->first;

          std::string   strTempFileName = it->second;

          DeleteFile( strTempFileName.c_str() );

          ++it;
        }
        m_mapDragDropTempFiles.clear();
        LeaveWorkMode();
      }
      break;
  }

  return true;

}
 

Anhänge

  • tut.zip
    12,1 KB · Aufrufe: 23

CodeFatal

Erfahrenes Mitglied
Hallo Endurion,

besten Dank für den Source Code und das Stichwort.
Denke das wird mir weiter helfen.

Gruß
Michael
 

Neue Beiträge