2010-09-22 127 views
7

Mike Lischke在VirtualTreeView中有廣泛的拖放支持,我使用TVirtualStringTree,它有一些拖放事件,但我無法弄清楚如何讓它接受一個外殼拖動從Windows資源管理器中將一些文件拖放到我的應用程序中。我想要加載文件,當他們被拖到拖放控制。如何將文件從資源管理器Shell拖放到Delphi應用程序的VirtualTreeView控件中?

我試過使用第三方的Anders Melander代碼來處理拖放操作,但是因爲VirtualTreeView已經將自己註冊爲放置目標,所以我無法使用它。

編輯:我發現了一個簡單的解決方法:關閉VT.TreeOptions.MiscOptions中的接受OLEDrop。 如果有人知道如何使用VirtualTreeView而不使用第三方OLE-shell拖放庫並使用其廣泛的OLE拖放支持來提取從Shell中拖入的文件名列表,那將很酷。

回答

9

我實現(工作得很好,2010年德爾福必須添加的ActiveX,以ShellAPI的用於編譯):

procedure TfMain.vstTreeDragDrop(Sender: TBaseVirtualTree; Source: TObject; 
    DataObject: IDataObject; Formats: TFormatArray; Shift: TShiftState; 
    Pt: TPoint; var Effect: Integer; Mode: TDropMode); 
var 
    I, j: Integer; 
    MyList: TStringList; 
    AttachMode: TVTNodeAttachMode; 
begin 
    if Mode = dmOnNode then 
    AttachMode := amInsertBefore 
    else if Mode = dmAbove then 
    AttachMode := amInsertBefore 
    else if Mode = dmBelow then 
    AttachMode := amInsertAfter 
    else 
    AttachMode := amAddChildLast; 

    MyList := TStringList.Create; 
    try 
    for i := 0 to High(formats) - 1 do 
    begin 
     if (Formats[i] = CF_HDROP) then 
     begin 
     GetFileListFromObj(DataObject, MyList); 

     //here we have all filenames 
     for j:=0 to MyList.Count - 1 do 
     begin 
      Sender.InsertNode(Sender.DropTargetNode, AttachMode); 
     end; 
     end; 
    end; 
    finally 
    MyList.Free; 
    end; 
end; 

procedure TfMain.GetFileListFromObj(const DataObj: IDataObject; 
    FileList: TStringList); 
var 
    FmtEtc: TFormatEtc;     // specifies required data format 
    Medium: TStgMedium;     // storage medium containing file list 
    DroppedFileCount: Integer;   // number of dropped files 
    I: Integer;       // loops thru dropped files 
    FileNameLength: Integer;    // length of a dropped file name 
    FileName: string;     // name of a dropped file 
begin 
    // Get required storage medium from data object 
    FmtEtc.cfFormat := CF_HDROP; 
    FmtEtc.ptd := nil; 
    FmtEtc.dwAspect := DVASPECT_CONTENT; 
    FmtEtc.lindex := -1; 
    FmtEtc.tymed := TYMED_HGLOBAL; 
    OleCheck(DataObj.GetData(FmtEtc, Medium)); 
    try 
    try 
     // Get count of files dropped 
     DroppedFileCount := DragQueryFile(
     Medium.hGlobal, $FFFFFFFF, nil, 0 
     ); 
     // Get name of each file dropped and process it 
     for I := 0 to Pred(DroppedFileCount) do 
     begin 
      // get length of file name, then name itself 
      FileNameLength := DragQueryFile(Medium.hGlobal, I, nil, 0); 
      SetLength(FileName, FileNameLength); 
      DragQueryFileW(
      Medium.hGlobal, I, PWideChar(FileName), FileNameLength + 1 
      ); 
      // add file name to list 
      FileList.Append(FileName); 
     end; 
    finally 
     // Tidy up - release the drop handle 
     // don't use DropH again after this 
     DragFinish(Medium.hGlobal); 
    end; 
    finally 
    ReleaseStgMedium(Medium); 
    end; 

end; 
3

我使用這種方法來捕獲(接收)從資源管理器拖入TWinControl的文件。
你可以在你的控制器上測試它。在標準TTreeView工作正常。

添加ShellAPI使用。

在私人部分:

private 
    originalEditWindowProc : TWndMethod; 
    procedure EditWindowProc(var Msg:TMessage); 
    // accept the files dropped 
    procedure FilesDrop(var Msg: TWMDROPFILES); 

在窗體的OnCreate中:

// Assign procedures 
    originalEditWindowProc := TreeView1.WindowProc; 
    TreeView1.WindowProc := EditWindowProc; 
    // Aceptar ficheros arrastrados // Accept the files 
    ShellAPI.DragAcceptFiles(TreeView1.Handle, True); 

而且,這兩個過程是這些:

// Al arrastrar ficheros sobre el TV. On drop files to TV 
procedure TForm1.FilesDrop(var Msg: TWMDROPFILES); 
var 
    i:Integer; 
    DroppedFilename:string; 
    numFiles : longInt; 
    buffer : array[0..MAX_PATH] of char; 
begin 
    // Número de ficheros arrastrados // Number of files 
    numFiles := DragQueryFile(Msg.Drop, $FFFFFFFF, nil, 0) ; 

    // Recorrido por todos los arrastrados // Accept all files 
    for i := 0 to (numFiles - 1) do begin 

    DragQueryFile(Msg.Drop, i, @buffer, sizeof(buffer)); 

    // Proteccion 
    try 
     DroppedFilename := buffer; 

     // HERE you can do something with the file... 
     TreeView1.Items.AddChild(nil, DroppedFilename); 
    except 
     on E:Exception do begin 
     // catch 
     end; 
    end; 
    end; 
end; 


procedure TForm1.EditWindowProc(var Msg: TMessage); 
begin 
    // if correct message, execute the procedure 
    if Msg.Msg = WM_DROPFILES then begin 
    FilesDrop(TWMDROPFILES(Msg)) 
    end 
    else begin 
    // in other case do default... 
    originalEditWindowProc(Msg) ; 
    end; 
end; 

我希望這是有用的你。

問候。

相關問題