CListCtrl Dateien via Drag & Drop zu Windows Explorer



  • Hallo,

    Ich schreibe seit längerem an einem Explorer ersatzt und es gibt da noch ein paar Dinge die unbedingt rein müssen, die ich aber auf den Tod nicht hinbekomme.

    Das woran ich mir schon am längsten die Zähne ausbeise ist das "Draggen" von Files aus meinem Explorer in den Windows Explorer (oder eben jedes andere Programm das dieses Format beherscht).

    Das empfangen von Files vom Windows Explorer ist kein Problem aber das ist für mich auch eher zweitranging.

    Drag & Drop mit OLE objekten habe ich bereits hinbekommen. Nach langem suchen habe ich auch endlich den Typ gefunden den der Windows Explorer benutzt (CF_HDROP). Allerdings habe ich keine Ahnung wie ich die Daten in den Globalen speicher schreiben muss, damit der Windows Explorer versteht welche Dateien er empfangen soll.

    Es gibt ja auf Code Guru ein Beispiel wie man Dateinamen in die Zwischenablage kopieren muß, damit der Explorer damit klarkommt. Das hat auch geklappt. Ich dachte bei Drag & Drop wärs auch nicht anders aber pustekuchen. So habe ich den Code Momentan:

    void CDDListCtrl::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) 
    {
        NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    
        char sFiles[] = "C:\\Temp\\file1.t0xt\0"
            "C:\\Temp\\file2.txt";
    
        DROPFILES dobj = { 20, { 0, 0 }, 0, 1 };
        int nLen = sizeof(sFiles);
        int nGblLen = sizeof(dobj) + nLen*2 + 5;//lots of nulls and multibyte_char
        HGLOBAL hGbl = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, nGblLen);
        char* sData = (char*)::GlobalLock(hGbl);
        memcpy( sData, &dobj, 20 );
        char* sWStr = sData+20;
        for( int i = 0; i < nLen*2; i += 2 )
        {
            sWStr[i] = sFiles[i/2];
        }
    
    //  delete sFiles;
    
        m_COleDataSource.CacheGlobalData(CF_HDROP, hGbl);           
    
        // Set drag/drop source rectangle (screen coord)
        SetDragSourceRect();
    
        DROPEFFECT dropEffect =
           m_COleDataSource.DoDragDrop(DROPEFFECT_COPY|DROPEFFECT_MOVE,NULL);  
    }
    

    Wäre wirklich klasse wenn mir jemand weiterhelfen könnte denn ich bin jetzt entgültig mit meinem Latein am Ende.

    Vielen Dank im voraus
    GeorgeHomes



  • Der Datenpuffer muss so aussehen:
    String1\0String2\0String3\0String4\0\0

    Das Aneinanderfügen dürfte doch nicht das Problem sein, oder doch?



  • Vielen dank für die Schnelle antwort.

    Ich hab jetzt mal dafür gesorgt das in sFiles am Schluß noch ne Doppelnull steht aber das hat leider nichts bewirkt. Oder meinst du das die Daten so direkt in sData schreiben soll? Das habe ich jetzt auch mal ausprobiert aber irgendwie haut das bei mir nicht so hin wies soll.



  • Beispiel:

    CStringArray arFiles;  // hier stehen deine Dateinamen drin
    UINT nGblLen=1;
    for( int i=0; i<arFiles.GetCount(); i++)
      nGblLen += arFiles[i].GetLength()+1;
    nGblLen *= sizeof(TCHAR);
    HGLOBAL hGbl = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, nGblLen);
    LPTSTR pszData = (LPTSTR)::GlobalLock(hGbl);
    for( int i=0; i<arFiles.GetCount(); i++)
    {
      CopyMemory( pszData, (LPCTSTR)arFiles[i], arFiles[i].GetLength()*sizeof(TCHAR));
      pszData += arFiles[i].GetLength()+1;
    }
    GlobalUnlock( hGbl);
    m_COleDataSource.CacheGlobalData(CF_HDROP, hGbl);
    


  • Na Gott Sei dank jetzt hab ichs auch endlich hinbekommen.

    Vielen Dank nochmal.



  • Zusatz:
    Ich weiss nicht, welches Format der Explorer verlangt. Möglicherweise ist es unter WinNT/2K nämlich UNICODE und unter Win98 MULTIBYTE. Einfach mal ausprobieren, falls es benötigt wird!


Anmelden zum Antworten