123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471 |
- unit FileOperator;
- {
- +------------------------------------------------------------------------------+
- | TFileOperator Component Version 1.02 / 1999 |
- +------------------------------------------------------------------------------+
- | Author: Ingo Eckel |
- | |
- | Based on the TFileOperator component written by Glen Why 1996 |
- | Enhancements: uses TStringList as operands, undo functionality implemented. |
- +------------------------------------------------------------------------------+
- | Description: |
- | This component encapsulates the ShFileOperation API of Microsoft Windows. |
- | Performs a copy, move, rename, or delete operation on a file system object. |
- | It also allows to undo the last operation, if a copy or move operation |
- | was performed. |
- +------------------------------------------------------------------------------+
- | Properties: |
- | |
- | OperandFrom: |
- | Stringlist, that contains the names of the source files, |
- | wildcard filename (*.*) is accepted. |
- | |
- | OperandTo: |
- | Stringlist that specifies the destination for the moved, |
- | copied or renamed file. Should be the target directory, when |
- | performing a copy or move operation. |
- | |
- | WantMappingHandle: True, if shFileOperation should create a filename- |
- | mapping of the processed files. This mapping is allocated by |
- | shFileOperation and will be automatically deallocated by the |
- | component. |
- | |
- | Operation: |
- | -foCopy Copies the files specified by OperandFrom to the location |
- | specified by OperandTo. |
- | -foDelete Deletes the files specified by OperandFrom (OperandTo |
- | ignored). |
- | -foMove Moves the files specified by OperandFrom to the location |
- | specified by OperandTo. |
- | -foRename Renames the files specified by OperandFrom. |
- | |
- | Options: |
- | -foAllowUndo Preserves undo information, if possible. |
- | -foConfirmMouse Not implemented. |
- | -foFilesOnly Performs the operation only on files if a wildcard |
- | filename (*.*) is specified. |
- | -foMultiDestFiles Indicates that the OperandTo member specifies multiple|
- | destination files (one for each source file) rather |
- | than one directory where all source files are |
- | to be deposited. |
- | Note: not compatible with undo operation. |
- | -foNoConfirmation Responds with "yes to all" for any dialog box that |
- | is displayed. |
- | -fofNoConfirmMkDir Does not confirm the creation of a new directory |
- | if the operation requires one to be created. |
- | -foRenameOnCollision Gives the file being operated on a new name |
- | (such as "Copy #1 of...") in a move, copy, |
- | or rename operation if a file of the target name |
- | already exists. |
- | Note: not compatible with undo operation. |
- | -foSilent Does not display a progress dialog box. |
- | -foSimpleProgress Displays a progress dialog box, but does not show |
- | the filenames. |
- | |
- | Title: String to use as the title for a progress dialog box. |
- | This member is used only if Options includes fofSimpleProgress. |
- | |
- | OperationAborted: Value that receives True if the user aborted any file |
- | operations before they were completed or FALSE otherwise. |
- | |
- | LastOperandFrom Stringlist of last performed value of Operandfrom. |
- | |
- | LastOperandTo Stringlist of last performed value of OperandTo. |
- | |
- | LastOperation Value of last performed operation. |
- | |
- | WantMappingHandle After execution should a file mapping be returned. |
- | Works only, when option foMultiDestFiles used. |
- | Note: don't know, how to use this. |
- | |
- | NameMappings Pointer to namemappings, if property wantmapping- |
- | handle set. |
- +------------------------------------------------------------------------------+
- | Methods: |
- | |
- | Function Execute : Boolean; |
- | Performs the copy, move, rename, or delete operation. |
- | Returns zero if successful or nonzero value if an error occurs. |
- | |
- | Function UndoExecute : Boolean; |
- | Reverses the last copy, move or rename operation. |
- | Note: works currently only, if only a single OperandTo is used. This |
- | OperandTo must be the target directory. |
- | |
- | Function CanUndo : Boolean; |
- | Returns TRUE, if undo of last operation is possible. |
- | |
- | Procedure ClearUndo; |
- | Clears the preserved undo informations. After that, CanUndo allways |
- | returns false. |
- +------------------------------------------------------------------------------+
- | Events: |
- +------------------------------------------------------------------------------+
- }
- {==============================================================}
- interface
- {==============================================================}
- uses
- Windows, Classes, Forms, Controls, ShellAPI, BaseUtils, SysUtils;
- Type
- TFileOperation = ( foCopy, foDelete, foMove, foRename );
- TFileOperationFlag = ( foAllowUndo, foConfirmMouse, foFilesOnly,
- foMultiDestFiles, foNoConfirmation, foNoConfirmMkDir,
- foRenameOnCollision, foSilent, foSimpleProgress);
- TFileOperationFlags = set of TFileOperationFlag;
- {==============================================================}
- TFileOperator = class( TComponent )
- {==============================================================}
- private
- {==============================================================}
- FData : TShFileOpStruct;
- FFrom : TStringList;
- FTo : TStringList;
- FLastFrom : TStringList;
- FLastTo : TStringList;
- FLastOperation : TFileOperation;
- fLastFlags : TFileOperationFlags;
- fCanUndo : Boolean;
- Procedure SetOperation( Value :TFileOperation );
- Function GetOperation :TFileOperation;
- Function GetWantMappingHandle :Boolean;
- Procedure SetWantMappingHandle ( Value :Boolean );
- Procedure SetFlags( Value :TFileOperationFlags );
- Function GetFlags :TFileOperationFlags;
- Function GetOperFlag( F :Cardinal ) :Boolean;
- Procedure SetOperFlag( F :Cardinal; V :Boolean );
- Procedure ReadData( Reader :TReader );
- Procedure WriteData( Writer :TWriter );
- Procedure SwapStringList(Var FromL, ToL : TStringList);
- Function GetOperationAborted: Bool;
- {==============================================================}
- protected
- {==============================================================}
- Procedure DefineProperties( Filer :TFiler ); override;
- {==============================================================}
- public
- {==============================================================}
- Property OperationAborted : Bool Read GetOperationAborted;
- Property OperandFrom : TStringList Read fFrom Write fFrom;
- Property OperandTo : TStringList Read FTo Write fTo;
- Property CanUndo : Boolean Read fCanUndo;
- Property LastOperation : TFileOperation Read fLastOperation;
- Property LastOperandFrom : TStringList Read fLastFrom;
- Property LastOperandTo : TStringList Read fLastTo;
- Constructor Create(aOwner :TComponent); Override;
- Destructor Destroy; override;
- Function Execute : Boolean;
- Function UndoExecute : Boolean;
- Procedure ClearUndo;
- {==============================================================}
- published
- {==============================================================}
- Property Operation : TFileOperation Read GetOperation Write SetOperation Stored false;
- Property Flags : TFileOperationFlags Read GetFlags Write SetFlags Stored false;
- Property WantMappingHandle :Boolean Read GetWantMappingHandle Write SetWantMappingHandle Stored false;
- end;
- const
- FileOperatorDefaultFlags = [foAllowUndo, foNoConfirmMkDir];
- procedure Register;
- {==============================================================}
- implementation
- {==============================================================}
- uses
- PasTools;
- { TFileOperator }
- procedure TFileOperator.SetOperation( Value :TFileOperation );
- begin
- with FData do
- case Value of
- foCopy : wFunc := FO_COPY;
- foDelete : wFunc := FO_DELETE;
- foRename : wFunc := FO_RENAME;
- foMove : wFunc := FO_MOVE;
- end;
- end; {SetOperation}
- function TFileOperator.GetOperation :TFileOperation;
- begin
- result := foCopy;
- case FData.wFunc of
- FO_COPY : result := foCopy;
- FO_DELETE : result := foDelete;
- FO_RENAME : result := foRename;
- FO_MOVE : result := foMove;
- end;
- end; {GetOperation}
- function TFileOperator.GetWantMappingHandle :Boolean;
- begin
- result := GetOperFlag( FOF_WANTMAPPINGHANDLE );
- end;
- procedure TFileOperator.SetWantMappingHandle ( Value :Boolean );
- begin
- SetOperFlag( FOF_WANTMAPPINGHANDLE, Value );
- end;
- procedure TFileOperator.SetFlags( Value :TFileOperationFlags );
- begin
- SetOperFlag( FOF_ALLOWUNDO, foAllowUndo in Value );
- SetOperFlag( FOF_CONFIRMMOUSE, foConfirmMouse in Value );
- SetOperFlag( FOF_FILESONLY, foFilesOnly in Value );
- SetOperFlag( FOF_MULTIDESTFILES, foMultiDestFiles in Value );
- SetOperFlag( FOF_NOCONFIRMATION, foNoConfirmation in Value );
- SetOperFlag( FOF_NOCONFIRMMKDIR, foNoConfirmMkDir in Value );
- SetOperFlag( FOF_RENAMEONCOLLISION, foRenameOnCollision in Value );
- SetOperFlag( FOF_SILENT, foSilent in Value );
- SetOperFlag( FOF_SIMPLEPROGRESS, foSimpleProgress in Value );
- end; {SetFlags}
- function TFileOperator.GetFlags :TFileOperationFlags;
- begin
- result := [];
- if GetOperFlag( FOF_ALLOWUNDO ) then include( result, foAllowUndo );
- if GetOperFlag( FOF_CONFIRMMOUSE ) then include( result, foConfirmMouse );
- if GetOperFlag( FOF_FILESONLY ) then include( result, foFilesOnly );
- if GetOperFlag( FOF_MULTIDESTFILES ) then include( result, foMultiDestFiles );
- if GetOperFlag( FOF_NOCONFIRMATION ) then include( result, foNoConfirmation );
- if GetOperFlag( FOF_NOCONFIRMMKDIR ) then include( result, foNoConfirmMkDir );
- if GetOperFlag( FOF_RENAMEONCOLLISION ) then include( result, foRenameOnCollision );
- if GetOperFlag( FOF_SILENT ) then include( result, foSilent );
- if GetOperFlag( FOF_SIMPLEPROGRESS ) then include( result, foSimpleProgress );
- end; {GetFlags}
- function TFileOperator.GetOperFlag( F :Cardinal ):boolean;
- begin
- result := ( FData.fFlags and F ) <> 0;
- end;
- procedure TFileOperator.SetOperFlag( F :Cardinal; V :Boolean );
- begin
- with FData do
- if V then
- fFlags := fFlags or F
- else fFlags := fFlags and ( not F );
- end;
- procedure TFileOperator.DefineProperties( Filer :TFiler );
- begin
- Inherited DefineProperties( Filer );
- Filer.DefineProperty( 'data', ReadData, WriteData, true );
- end;
- procedure TFileOperator.ReadData( Reader :TReader );
- begin
- Reader.Read( FData, SizeOf( FData ) );
- end;
- procedure TFileOperator.WriteData( Writer :TWriter );
- begin
- writer.write( FData, SizeOf( FData ) );
- end;
- Constructor TFileOperator.Create(aOwner :TComponent);
- begin
- inherited Create(aOwner);
- fFrom := TStringList.Create;
- fTo := TStringList.Create;
- fLastFrom := TStringList.Create;
- fLastTo := TStringList.Create;
- fCanUndo := False;
- FData.fFlags := 0;
- Flags := FileOperatorDefaultFlags;
- end; {Create}
- function TFileOperator.Execute : Boolean;
- Var SFrom : String;
- sTo : String;
- Function ConvertOperand(List : TStringList) : String;
- Var i : Integer;
- Begin
- Result := '';
- For i := 0 to Pred(List.Count) Do
- Begin
- // SHFileOperation does not support long paths anyway
- Result := Result + ApiPath(List[i]);
- SetLength(Result, Succ(Length(Result)));
- Result[Length(Result)] := #0;
- End;
- SetLength(Result, Succ(Length(Result)));
- Result[Length(Result)] := #0;
- End; {ConvertOperand}
- begin {Execute}
- SFrom := ConvertOperand(FFrom);
- STo := ConvertOperand(FTo);
- FData.pFrom := PChar( SFrom );
- FData.pTo := PChar( STo );
- IF (Owner is TWinControl) And TWinControl(Owner).HandleAllocated Then
- FData.Wnd := GetParentForm(TWinControl(Owner)).Handle
- Else
- FData.Wnd := Application.Handle;
- Try
- IF Assigned(FData.hNameMappings) Then
- shFreeNameMappings(THandle(FData.hNameMappings));
- Finally
- FData.hNameMappings := NIL;
- End;
- Try
- Try
- IF Operation = foRename Then
- Result := RenameFile(FFrom[0], FTo[0])
- Else
- Result := ShFileOperation( FData ) = 0;
- Finally
- IF GetOperFlag(FOF_ALLOWUNDO) And
- Not GetOperFlag(FOF_MULTIDESTFILES) And
- Not GetOperFlag(FOF_RENAMEONCOLLISION) And
- (Operation <> foDelete) Then
- Begin
- SwapStringList(fLastFrom, fFrom);
- SwapStringList(fLastTo, fTo);
- fLastFlags := Flags;
- fCanUndo := True;
- fLastOperation := Operation;
- End
- Else
- Begin
- FLastFrom.Clear;
- FLastTo.Clear;
- fCanUndo := False;
- End;
- FFrom.Clear;
- FTo.Clear;
- End;
- Except
- Result := False;
- End;
- end; {Execute}
- destructor TFileOperator.Destroy;
- begin
- IF Assigned(FFrom) Then
- FFrom.Free;
- IF Assigned(FTo) Then
- FTo.Free;
- IF Assigned(FLastFrom) Then
- FLastFrom.Free;
- IF Assigned(FLastTo) Then
- FLastTo.Free;
- IF Assigned(FData.hNameMappings) Then
- shFreeNameMappings(THandle(FData.hNameMappings));
- inherited Destroy;
- end; {Destroy}
- Procedure TFileOperator.SwapStringList(Var FromL, ToL : TStringList);
- Var StrL : TStringList;
- Begin
- StrL := FromL;
- FromL := ToL;
- ToL := StrL;
- End; {SwapStringList}
- Function TFileOperator.GetOperationAborted: Bool;
- Begin
- Result := FData.fAnyOperationsAborted;
- End;
- Function TFileOperator.UndoExecute : Boolean;
- Var SaveFlags : TFileOperationFlags;
- SaveOperation : TFileOperation;
- i : Integer;
- Begin
- Result := False;
- IF Not fCanUndo Or
- (fLastFrom.Count = 0) Or
- (FLastTo.Count <> 1) Then
- Exit;
- SaveFlags := Flags;
- SaveOperation := Operation;
- Flags := fLastFlags;
- Case SaveOperation OF
- foCopy : IF fLastTo.Count = 1 Then
- Begin
- Operation := foDelete;
- Flags := Flags - [foAllowUndo] + [foNoConfirmation];
- OperandFrom.Clear;
- For i := 0 To fLastFrom.Count - 1 Do
- OperandFrom.Add(IncludeTrailingPathDelimiter(fLastTo[0]) + ExtractFilename(fLastFrom[i]));
- Result := Execute;
- End;
- foMove : IF fLastTo.Count = 1 Then
- Begin
- Operation := foMove;
- Flags := Flags + [foAllowUndo, foNoConfirmation];
- OperandFrom.Clear;
- OperandTo.Clear;
- OperandTo.Add(ExtractFilePath(fLastFrom[0]));
- For i := 0 To fLastFrom.Count - 1 Do
- OperandFrom.Add(IncludeTrailingPathDelimiter(fLastTo[0]) + ExtractFilename(fLastFrom[i]));
- Result := Execute;
- End;
- foRename: IF (FLastFrom.Count = 1) And (FLastTo.Count = 1) Then
- Begin
- Operation := foRename;
- Flags := Flags + [foAllowUndo, foNoConfirmation];
- OperandFrom.Clear;
- OperandTo.Clear;
- OperandFrom.Add(fLastTo[0]);
- OperandTo.Add(fLastFrom[0]);
- Result := Execute;
- End;
- End; {Case}
- Flags := SaveFlags;
- Operation := SaveOperation;
- End; {UndoExecute}
- Procedure TFileOperator.ClearUndo;
- Begin
- fCanUndo := False;
- fLastFrom.Clear;
- fLastTo.Clear;
- End; {ClearUndo}
- procedure Register;
- begin
- {MP}RegisterComponents( {'Tools'}'DriveDir', [ TFileOperator ] );
- end;
- end.
|