/VSTDragDrop_win.pas
Pascal | 128 lines | 96 code | 12 blank | 20 comment | 7 complexity | d43a87d8c6c768c97184f4d9a0e616b6 MD5 | raw file
1{*******************************************************} 2{ } 3{ Functions for VirtualTree Drag&Drop implementation } 4{ } 5{*******************************************************} 6 7unit VSTDragDrop_win; 8 9interface 10 11uses 12 VirtualTrees, 13 vstUtils, 14 ActiveX, ShellAPI, Classes, Types, Windows; 15 16type 17 { Implements the drag&drop functions called by the files tree in frmMain 18 VSTDragDrop is called on dropping a file (or any content), identifies the 19 dropped content and calles AddItem ultimately 20 GetFileListFromObj is a helper function to transfer an IDataObject into 21 filepath strings, which will get added to a passed StringList } 22 TDragEvent = class 23 procedure VSTDragDrop(Sender: TBaseVirtualTree; 24 Source: TObject; DataObject: IDataObject; Formats: TFormatArray; 25 Shift: TShiftState; Pt: TPoint; var Effect: Integer; Mode: TDropMode); 26 27 procedure GetFileListFromObj(const DataObj: IDataObject; 28 FileList: TStringList); 29 end; 30 31 32implementation 33 34uses ComObj; 35 36procedure TDragEvent.VSTDragDrop(Sender: TBaseVirtualTree; 37 Source: TObject; DataObject: IDataObject; Formats: TFormatArray; 38 Shift: TShiftState; Pt: TPoint; var Effect: Integer; Mode: TDropMode); 39var 40 I, j: Integer; 41 MyList: TStringList; 42begin 43 MyList := TStringList.Create; 44 Sender.BeginUpdate; 45 try 46 for i := 0 to High(formats) - 1 do 47 begin 48 if Formats[i] = CF_HDROP then // Explorer drop 49 begin 50 GetFileListFromObj(DataObject, MyList); 51 52 //here we have all filenames 53 for j:=0 to MyList.Count - 1 do 54 begin 55 if Mode = dmOnNode then 56 begin 57 AddItem(Sender,Sender.DropTargetNode,MyList.Strings[j]); 58 end else 59 begin 60 AddItem(Sender,nil,MyList.Strings[j]); 61 end; 62 end; 63 end else 64 if Formats[i] = CF_VIRTUALTREE then // VirtualTree drop 65 begin 66 case Mode of 67 dmNowhere: Sender.ProcessDrop(DataObject,nil,Effect,amAddChildLast); 68 dmAbove: Sender.ProcessDrop(DataObject,Sender.DropTargetNode,Effect,amInsertBefore); 69 dmOnNode: 70 begin; 71 if not IsFile(Sender,Sender.DropTargetNode) then 72 Sender.ProcessDrop(DataObject,Sender.DropTargetNode,Effect,amAddChildLast); 73 end; 74 dmBelow: Sender.ProcessDrop(DataObject,Sender.DropTargetNode,Effect,amInsertAfter); 75 end; 76 end; 77 end; 78 finally 79 MyList.Free; 80 Sender.SortTree(0,sdAscending,true); 81 Sender.EndUpdate; 82 end; 83end; 84 85procedure TDragEvent.GetFileListFromObj(const DataObj: IDataObject; 86 FileList: TStringList); 87var 88 FmtEtc: TFormatEtc; // specifies required data format 89 Medium: TStgMedium; // storage medium containing file list 90 DroppedFileCount: Integer; // number of dropped files 91 I: Integer; // loops thru dropped files 92 FileNameLength: Integer; // length of a dropped file name 93 FileName: String; // name of a dropped file 94 Buffer: Array [0..MAX_PATH] of Char; 95begin 96 // Get required storage medium from data object 97 FmtEtc.cfFormat := CF_HDROP; 98 FmtEtc.ptd := nil; 99 FmtEtc.dwAspect := DVASPECT_CONTENT; 100 FmtEtc.lindex := -1; 101 FmtEtc.tymed := TYMED_HGLOBAL; 102 OleCheck(DataObj.GetData(FmtEtc, Medium)); 103 try 104 try 105 // Get count of files dropped 106 DroppedFileCount := DragQueryFile(Medium.hGlobal, $FFFFFFFF, nil, 0); 107 // Get name of each file dropped and process it 108 for I := 0 to Pred(DroppedFileCount) do 109 begin 110 // get length of file name, then name itself 111 FileNameLength := DragQueryFile(Medium.hGlobal, I, @buffer, sizeof(buffer)); 112 FileName := buffer; 113 //SetLength(FileName, FileNameLength); 114 //DragQueryFileW(Medium.hGlobal, I, PWideChar(FileName), FileNameLength + 1); 115 // add file name to list 116 FileList.Append(FileName); 117 end; 118 finally 119 // Tidy up - release the drop handle 120 // don't use DropH again after this 121 DragFinish(Medium.hGlobal); 122 end; 123 finally 124 ReleaseStgMedium(Medium); 125 end; 126end; 127 128end.