How do you drag a file from the Explorer shell into the VirtualTreeView control in a Delphi application?

VirtualTreeView has extensive drag and drop support for Mike Lischke, and I use TVirtualStringTree, which has some drag and drop events, but I can’t figure out how to get it to accept some drag-and-drop shell files from the Windows Explorer shell into my application . I want to upload files when they are dragged onto the drop control.

I tried using a third-party code set from Anders Melander to handle the drag and drop, but since VirtualTreeView already registers itself as a drag target, I cannot use this.

edit: I found a simple way: disable toAcceptOLEDrop in VT.TreeOptions.MiscOptions. It would be great if anyone knew how to use VirtualTreeView without using the third-party OLE-shell-drag-drop library and using the extensive OLE drag and drop support to retrieve the list of files being dragged from the shell.

+7
delphi drag-and-drop windows-shell virtualtreeview
source share
2 answers

My implementation (works fine with Delphi 2010. Must add ActiveX, ShellApi for compilation):

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; 
+9
source share

I use this method to capture (receive) files dragged into TWinControl from Explorer.
You can check it out for your control. The standard TTreeView works fine.

Add ShellAPI to use.

In the private section:

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

In OnCreate of your form:

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

And these two procedures:

 // 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; 

I hope this is helpful to you.

Sincerely.

+3
source share

All Articles