Unit1.pas 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. unit Unit1;
  2. interface
  3. uses
  4. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  5. ComCtrls, ActiveX, ShellApi, ShlObj, Buttons, ExtCtrls, DropSource,
  6. StdCtrls, DropTarget, CommCtrl, FileCtrl, DragDrop, DragDropFile;
  7. type
  8. TFormMain = class(TForm)
  9. ListView1: TListView;
  10. Panel1: TPanel;
  11. ButtonClose: TButton;
  12. StatusBar1: TStatusBar;
  13. DropFileSource1: TDropFileSource;
  14. Label2: TLabel;
  15. procedure FormCreate(Sender: TObject);
  16. procedure ListView1MouseDown(Sender: TObject; Button: TMouseButton;
  17. Shift: TShiftState; X, Y: Integer);
  18. procedure ButtonCloseClick(Sender: TObject);
  19. procedure DropFileSource1Drop(Sender: TObject; DragType: TDragType;
  20. var ContinueDrop: Boolean);
  21. procedure FormDestroy(Sender: TObject);
  22. procedure DropFileSource1AfterDrop(Sender: TObject;
  23. DragResult: TDragResult; Optimized: Boolean);
  24. private
  25. TempPath: string; // path to temp folder
  26. ExtractedFiles: TStringList;
  27. procedure ExtractFile(FileIndex: integer; Filename: string);
  28. procedure RemoveFile(FileIndex: integer);
  29. public
  30. { Public declarations }
  31. end;
  32. var
  33. FormMain: TFormMain;
  34. implementation
  35. {$R *.DFM}
  36. ////////////////////////////////////////////////////////////////////////////////
  37. //
  38. // Utility methods
  39. //
  40. ////////////////////////////////////////////////////////////////////////////////
  41. procedure MakeBlankFile(const Name: string);
  42. var
  43. f : TextFile;
  44. path : string;
  45. begin
  46. path := ExtractFilePath(name);
  47. if (path <> '') then
  48. ForceDirectories(path);
  49. AssignFile(f, Name);
  50. try
  51. Rewrite(f);
  52. finally
  53. CloseFile(f);
  54. end;
  55. end;
  56. function AddSlash(const str: string): string;
  57. begin
  58. Result := str;
  59. if (Result <> '') and (Result[length(Result)] <> '\') then
  60. Result := Result+'\';
  61. end;
  62. function GetTempPath: string;
  63. var
  64. Res: DWORD;
  65. begin
  66. SetLength (Result, MAX_PATH);
  67. Res := windows.GetTempPath(MAX_PATH, PChar(Result));
  68. SetLength (Result, Res);
  69. AddSlash(Result); //append a slash if needed
  70. end;
  71. ////////////////////////////////////////////////////////////////////////////////
  72. //
  73. // Startup/Shutdown
  74. //
  75. ////////////////////////////////////////////////////////////////////////////////
  76. procedure TFormMain.FormCreate(Sender: TObject);
  77. begin
  78. // Get path to temporary directory
  79. TempPath := GetTempPath;
  80. // List of all extracted files
  81. ExtractedFiles := TStringList.Create;
  82. end;
  83. procedure TFormMain.FormDestroy(Sender: TObject);
  84. var
  85. i : integer;
  86. begin
  87. // Before we exit, we make sure that we aren't leaving any extracted
  88. // files behind. Since it is the drop target's responsibility to
  89. // clean up after an optimized drag/move operation, we might get away with
  90. // just deleting all drag/copied files, but since many ill behaved drop
  91. // targets doesn't clean up after them selves, we will do it for them
  92. // here. If you trust your drop target to clean up after itself, you can skip
  93. // this step.
  94. // Note that this means that you shouldn't exit this application before
  95. // the drop target has had a chance of actually copy/move the files.
  96. for i := 0 to ExtractedFiles.Count-1 do
  97. if (FileExists(ExtractedFiles[i])) then
  98. try
  99. DeleteFile(ExtractedFiles[i]);
  100. except
  101. // Ignore any errors we might get
  102. end;
  103. // Note: We should also remove any folders we created, but this example
  104. // doesn't do that.
  105. ExtractedFiles.Free;
  106. end;
  107. procedure TFormMain.ButtonCloseClick(Sender: TObject);
  108. begin
  109. Close;
  110. end;
  111. ////////////////////////////////////////////////////////////////////////////////
  112. //
  113. // MouseDown handler.
  114. //
  115. ////////////////////////////////////////////////////////////////////////////////
  116. // Does drag detection, sets up the filename list and starts the drag operation.
  117. ////////////////////////////////////////////////////////////////////////////////
  118. procedure TFormMain.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
  119. Shift: TShiftState; X, Y: Integer);
  120. var
  121. i ,
  122. j : integer;
  123. s : string;
  124. begin
  125. // If no files selected then exit...
  126. if (Listview1.SelCount = 0) then
  127. exit;
  128. if (DragDetectPlus(TWinControl(Sender).Handle, Point(X,Y))) then
  129. begin
  130. // Clear any filenames left from a previous drag operation...
  131. DropFileSource1.Files.Clear;
  132. // 'Extracting' files here would be much simpler but is often
  133. // very inefficient as many drag ops are cancelled before the
  134. // files are actually dropped. Instead we delay the extracting,
  135. // until we know the user really wants the files, but load the
  136. // filenames into DropFileSource1.Files as if they already exist...
  137. // Add root files and top level subfolders...
  138. for i := 0 to Listview1.Items.Count-1 do
  139. if (Listview1.Items[i].Selected) then
  140. begin
  141. // Note that it isn't nescessary to list files and folders in
  142. // sub folders. It is sufficient to list the top level sub folders,
  143. // since the drag target will copy/move the sub folders and
  144. // everything they contain.
  145. // Some target applications might not be able to handle this
  146. // optimization or it might not suit your purposes. In that case,
  147. // simply remove all the code between [A] and [B] below .
  148. // [A]
  149. j := pos('\', Listview1.Items[i].Caption);
  150. if (j > 0) then
  151. begin
  152. // Item is a subfolder...
  153. // Get the top level subfolder.
  154. s := copy(Listview1.Items[i].Caption, 1, j-1);
  155. // Add folder if it hasn't already been done.
  156. if DropFileSource1.Files.IndexOf(TempPath + s) = -1 then
  157. DropFileSource1.Files.Add(TempPath + s);
  158. end else
  159. // [B]
  160. // Item is a file in the root folder...
  161. DropFileSource1.Files.Add(TempPath + Listview1.Items[i].Caption);
  162. end;
  163. // Start the drag operation...
  164. DropFileSource1.Execute;
  165. end;
  166. end;
  167. ////////////////////////////////////////////////////////////////////////////////
  168. //
  169. // OnDrop handler.
  170. //
  171. ////////////////////////////////////////////////////////////////////////////////
  172. // Executes when the user drops the files on a drop target.
  173. ////////////////////////////////////////////////////////////////////////////////
  174. procedure TFormMain.DropFileSource1Drop(Sender: TObject; DragType: TDragType;
  175. var ContinueDrop: Boolean);
  176. var
  177. i : integer;
  178. begin
  179. // If the user actually dropped the filenames somewhere, we would now
  180. // have to extract the files from the archive. The files should be
  181. // extracted to the same path and filename as the ones we specified
  182. // in the drag operation. Otherwise the drop source will not be able
  183. // to find the files.
  184. // 'Extract' all the selected files into the temporary folder tree...
  185. for i := Listview1.Items.Count-1 downto 0 do
  186. if (Listview1.Items[i].Selected) then
  187. ExtractFile(i, TempPath + Listview1.Items[i].Caption);
  188. // As soon as this method returns, the destination's (e.g. Explorer's)
  189. // DropTarget.OnDrop event will trigger and the destination will
  190. // start copying/moving the files.
  191. end;
  192. ////////////////////////////////////////////////////////////////////////////////
  193. //
  194. // OnAfterDrop handler.
  195. //
  196. ////////////////////////////////////////////////////////////////////////////////
  197. // Executes after the target has returned from its OnDrop event handler.
  198. ////////////////////////////////////////////////////////////////////////////////
  199. procedure TFormMain.DropFileSource1AfterDrop(Sender: TObject;
  200. DragResult: TDragResult; Optimized: Boolean);
  201. var
  202. i, j : integer;
  203. begin
  204. // If the user performed a move operation, we now delete the selected files
  205. // from the archive.
  206. if (DragResult = drDropMove) then
  207. for i := Listview1.Items.Count-1 downto 0 do
  208. if (Listview1.Items[i].Selected) then
  209. RemoveFile(i);
  210. // If the user performed an unoptimized move operation, we must delete the
  211. // files that were extracted.
  212. if (DragResult = drDropMove) and (not Optimized) then
  213. for i := 0 to DropFileSource1.Files.Count-1 do
  214. begin
  215. if (FileExists(DropFileSource1.Files[i])) then
  216. try
  217. DeleteFile(DropFileSource1.Files[i]);
  218. // Remove the files we just deleted from the "to do" list.
  219. j := ExtractedFiles.IndexOf(DropFileSource1.Files[i]);
  220. if (j <> -1) then
  221. ExtractedFiles.Delete(j);
  222. except
  223. // Ignore any errors we might get.
  224. end;
  225. // Note: We should also remove any folders we created, but this example
  226. // doesn't do that.
  227. end;
  228. end;
  229. ////////////////////////////////////////////////////////////////////////////////
  230. //
  231. // Extract file from archive.
  232. //
  233. ////////////////////////////////////////////////////////////////////////////////
  234. // This method extracts a single file from the archive and saves it to disk.
  235. // In a "real world" application, you would create (e.g. unzip, download etc.)
  236. // your physical files here.
  237. ////////////////////////////////////////////////////////////////////////////////
  238. procedure TFormMain.ExtractFile(FileIndex: integer; Filename: string);
  239. begin
  240. // Of course, this is a demo so we'll just make phoney files here...
  241. MakeBlankFile(Filename);
  242. // Remember that we have extracted this file
  243. if (ExtractedFiles.IndexOf(Filename) = -1) then
  244. ExtractedFiles.Add(Filename);
  245. end;
  246. ////////////////////////////////////////////////////////////////////////////////
  247. //
  248. // Delete file from archive.
  249. //
  250. ////////////////////////////////////////////////////////////////////////////////
  251. // This method removes a single file from the archive.
  252. ////////////////////////////////////////////////////////////////////////////////
  253. procedure TFormMain.RemoveFile(FileIndex: integer);
  254. begin
  255. // This is just a demo, so we'll just remove the filename from the listview...
  256. Listview1.Items.Delete(FileIndex);
  257. end;
  258. end.