I have found examples of CopyFileEx with progress, but I need to copy some files from a folder with overall progress.
Can anybody provide info how to do this? Or is there good alternative (component, function)?
Big thanks for help!!!
Here is my solution without WinApi.
First, a procedure for copying one file:
procedure CopyFileWithProgress(const AFrom, ATo: String; var AProgress: TProgressBar);
var
FromF, ToF: file;
NumRead, NumWritten, DataSize: Integer;
Buf: array[1..2048] of Char;
begin
try
DataSize := SizeOf(Buf);
AssignFile(FromF, AFrom);
Reset(FromF, 1);
AssignFile(ToF, ATo);
Rewrite(ToF, 1);
repeat
BlockRead(FromF, Buf, DataSize, NumRead);
BlockWrite(ToF, Buf, NumRead, NumWritten);
if Assigned(AProgress) then
begin
AProgress.Position := AProgress.Position + DataSize;
Application.ProcessMessages;
end;
until (NumRead = 0) or (NumWritten <> NumRead);
finally
CloseFile(FromF);
CloseFile(ToF);
end;
end;
Now, gathering files from directory and calculating their total size for progress. Please note that the procedure requires an instance of TStringList class where will be stored file paths.
procedure GatherFilesFromDirectory(const ADirectory: String;
var AFileList: TStringList; out ATotalSize: Int64);
var
SR: TSearchRec;
begin
if FindFirst(ADirectory + '\*.*', faDirectory, sr) = 0 then
begin
repeat
if ((SR.Attr and faDirectory) = SR.Attr) and (SR.Name <> '.') and (SR.Name <> '..') then
GatherFilesFromDirectory(ADirectory + '\' + Sr.Name, AFileList, ATotalSize);
until FindNext(SR) <> 0;
FindClose(SR);
end;
if FindFirst(ADirectory + '\*.*', 0, SR) = 0 then
begin
repeat
AFileList.Add(ADirectory + '\' + SR.Name);
Inc(ATotalSize, SR.Size);
until FindNext(SR) <> 0;
FindClose(SR);
end;
end;
And finally the usage example:
procedure TfmMain.btnCopyClick(Sender: TObject);
var
FileList: TStringList;
TotalSize: Int64;
i: Integer;
begin
TotalSize := 0;
FileList := TStringList.Create;
try
GatherFilesFromDirectory('C:\SomeSourceDirectory', FileList, TotalSize);
pbProgress.Position := 0;
pbProgress.Max := TotalSize;
for i := 0 to FileList.Count - 1 do
begin
CopyFileWithProgress(FileList[i], 'C:\SomeDestinationDirectory\' + ExtractFileName(FileList[i]), pbProgress);
end;
finally
FileList.Free;
end;
end;
Experimenting with buffer size my improve performance. However it is quite fast as it is now. Maybe even faster than copying with this bloated Vista/Win 7 dialogs.
Also this is quick solution which I wrote few years ago for other forum, it might contain some bugs. So use at own risk ;-)
Add up the file size for all the files before you start. Then you can manually convert the progress for each individual file into an overall progress.
Or use SHFileOperation
and get the native OS file copy progress dialogs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With