| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- unit Unit1;
- interface
- uses
- Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
- ComCtrls, ActiveX, ShellApi, ShlObj, Buttons, ExtCtrls, DropSource,
- StdCtrls, DropTarget, CommCtrl, FileCtrl, DragDrop, DragDropFile;
- type
- TFormMain = class(TForm)
- ListView1: TListView;
- Panel1: TPanel;
- ButtonClose: TButton;
- StatusBar1: TStatusBar;
- DropFileSource1: TDropFileSource;
- Label2: TLabel;
- procedure FormCreate(Sender: TObject);
- procedure ListView1MouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- procedure ButtonCloseClick(Sender: TObject);
- procedure DropFileSource1Drop(Sender: TObject; DragType: TDragType;
- var ContinueDrop: Boolean);
- procedure FormDestroy(Sender: TObject);
- procedure DropFileSource1AfterDrop(Sender: TObject;
- DragResult: TDragResult; Optimized: Boolean);
- private
- TempPath: string; // path to temp folder
- ExtractedFiles: TStringList;
- procedure ExtractFile(FileIndex: integer; Filename: string);
- procedure RemoveFile(FileIndex: integer);
- public
- { Public declarations }
- end;
- var
- FormMain: TFormMain;
- implementation
- {$R *.DFM}
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Utility methods
- //
- ////////////////////////////////////////////////////////////////////////////////
- procedure MakeBlankFile(const Name: string);
- var
- f : TextFile;
- path : string;
- begin
- path := ExtractFilePath(name);
- if (path <> '') then
- ForceDirectories(path);
- AssignFile(f, Name);
- try
- Rewrite(f);
- finally
- CloseFile(f);
- end;
- end;
- function AddSlash(const str: string): string;
- begin
- Result := str;
- if (Result <> '') and (Result[length(Result)] <> '\') then
- Result := Result+'\';
- end;
- function GetTempPath: string;
- var
- Res: DWORD;
- begin
- SetLength (Result, MAX_PATH);
- Res := windows.GetTempPath(MAX_PATH, PChar(Result));
- SetLength (Result, Res);
- AddSlash(Result); //append a slash if needed
- end;
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Startup/Shutdown
- //
- ////////////////////////////////////////////////////////////////////////////////
- procedure TFormMain.FormCreate(Sender: TObject);
- begin
- // Get path to temporary directory
- TempPath := GetTempPath;
- // List of all extracted files
- ExtractedFiles := TStringList.Create;
- end;
- procedure TFormMain.FormDestroy(Sender: TObject);
- var
- i : integer;
- begin
- // Before we exit, we make sure that we aren't leaving any extracted
- // files behind. Since it is the drop target's responsibility to
- // clean up after an optimized drag/move operation, we might get away with
- // just deleting all drag/copied files, but since many ill behaved drop
- // targets doesn't clean up after them selves, we will do it for them
- // here. If you trust your drop target to clean up after itself, you can skip
- // this step.
- // Note that this means that you shouldn't exit this application before
- // the drop target has had a chance of actually copy/move the files.
- for i := 0 to ExtractedFiles.Count-1 do
- if (FileExists(ExtractedFiles[i])) then
- try
- DeleteFile(ExtractedFiles[i]);
- except
- // Ignore any errors we might get
- end;
- // Note: We should also remove any folders we created, but this example
- // doesn't do that.
- ExtractedFiles.Free;
- end;
- procedure TFormMain.ButtonCloseClick(Sender: TObject);
- begin
- Close;
- end;
- ////////////////////////////////////////////////////////////////////////////////
- //
- // MouseDown handler.
- //
- ////////////////////////////////////////////////////////////////////////////////
- // Does drag detection, sets up the filename list and starts the drag operation.
- ////////////////////////////////////////////////////////////////////////////////
- procedure TFormMain.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- var
- i ,
- j : integer;
- s : string;
- begin
- // If no files selected then exit...
- if (Listview1.SelCount = 0) then
- exit;
- if (DragDetectPlus(TWinControl(Sender).Handle, Point(X,Y))) then
- begin
- // Clear any filenames left from a previous drag operation...
- DropFileSource1.Files.Clear;
- // 'Extracting' files here would be much simpler but is often
- // very inefficient as many drag ops are cancelled before the
- // files are actually dropped. Instead we delay the extracting,
- // until we know the user really wants the files, but load the
- // filenames into DropFileSource1.Files as if they already exist...
- // Add root files and top level subfolders...
- for i := 0 to Listview1.Items.Count-1 do
- if (Listview1.Items[i].Selected) then
- begin
- // Note that it isn't nescessary to list files and folders in
- // sub folders. It is sufficient to list the top level sub folders,
- // since the drag target will copy/move the sub folders and
- // everything they contain.
- // Some target applications might not be able to handle this
- // optimization or it might not suit your purposes. In that case,
- // simply remove all the code between [A] and [B] below .
- // [A]
- j := pos('\', Listview1.Items[i].Caption);
- if (j > 0) then
- begin
- // Item is a subfolder...
- // Get the top level subfolder.
- s := copy(Listview1.Items[i].Caption, 1, j-1);
- // Add folder if it hasn't already been done.
- if DropFileSource1.Files.IndexOf(TempPath + s) = -1 then
- DropFileSource1.Files.Add(TempPath + s);
- end else
- // [B]
- // Item is a file in the root folder...
- DropFileSource1.Files.Add(TempPath + Listview1.Items[i].Caption);
- end;
- // Start the drag operation...
- DropFileSource1.Execute;
- end;
- end;
- ////////////////////////////////////////////////////////////////////////////////
- //
- // OnDrop handler.
- //
- ////////////////////////////////////////////////////////////////////////////////
- // Executes when the user drops the files on a drop target.
- ////////////////////////////////////////////////////////////////////////////////
- procedure TFormMain.DropFileSource1Drop(Sender: TObject; DragType: TDragType;
- var ContinueDrop: Boolean);
- var
- i : integer;
- begin
- // If the user actually dropped the filenames somewhere, we would now
- // have to extract the files from the archive. The files should be
- // extracted to the same path and filename as the ones we specified
- // in the drag operation. Otherwise the drop source will not be able
- // to find the files.
- // 'Extract' all the selected files into the temporary folder tree...
- for i := Listview1.Items.Count-1 downto 0 do
- if (Listview1.Items[i].Selected) then
- ExtractFile(i, TempPath + Listview1.Items[i].Caption);
- // As soon as this method returns, the destination's (e.g. Explorer's)
- // DropTarget.OnDrop event will trigger and the destination will
- // start copying/moving the files.
- end;
- ////////////////////////////////////////////////////////////////////////////////
- //
- // OnAfterDrop handler.
- //
- ////////////////////////////////////////////////////////////////////////////////
- // Executes after the target has returned from its OnDrop event handler.
- ////////////////////////////////////////////////////////////////////////////////
- procedure TFormMain.DropFileSource1AfterDrop(Sender: TObject;
- DragResult: TDragResult; Optimized: Boolean);
- var
- i, j : integer;
- begin
- // If the user performed a move operation, we now delete the selected files
- // from the archive.
- if (DragResult = drDropMove) then
- for i := Listview1.Items.Count-1 downto 0 do
- if (Listview1.Items[i].Selected) then
- RemoveFile(i);
- // If the user performed an unoptimized move operation, we must delete the
- // files that were extracted.
- if (DragResult = drDropMove) and (not Optimized) then
- for i := 0 to DropFileSource1.Files.Count-1 do
- begin
- if (FileExists(DropFileSource1.Files[i])) then
- try
- DeleteFile(DropFileSource1.Files[i]);
- // Remove the files we just deleted from the "to do" list.
- j := ExtractedFiles.IndexOf(DropFileSource1.Files[i]);
- if (j <> -1) then
- ExtractedFiles.Delete(j);
- except
- // Ignore any errors we might get.
- end;
- // Note: We should also remove any folders we created, but this example
- // doesn't do that.
- end;
- end;
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Extract file from archive.
- //
- ////////////////////////////////////////////////////////////////////////////////
- // This method extracts a single file from the archive and saves it to disk.
- // In a "real world" application, you would create (e.g. unzip, download etc.)
- // your physical files here.
- ////////////////////////////////////////////////////////////////////////////////
- procedure TFormMain.ExtractFile(FileIndex: integer; Filename: string);
- begin
- // Of course, this is a demo so we'll just make phoney files here...
- MakeBlankFile(Filename);
- // Remember that we have extracted this file
- if (ExtractedFiles.IndexOf(Filename) = -1) then
- ExtractedFiles.Add(Filename);
- end;
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Delete file from archive.
- //
- ////////////////////////////////////////////////////////////////////////////////
- // This method removes a single file from the archive.
- ////////////////////////////////////////////////////////////////////////////////
- procedure TFormMain.RemoveFile(FileIndex: integer);
- begin
- // This is just a demo, so we'll just remove the filename from the listview...
- Listview1.Items.Delete(FileIndex);
- end;
- end.
|