Delphi 使用progressbar删除文件
我试图在删除文件时使用progressbar,以下是我的代码:Delphi 使用progressbar删除文件,delphi,Delphi,我试图在删除文件时使用progressbar,以下是我的代码: procedure TForm1.Timer1Timer(Sender: TObject); var i:Integer; begin i:=i+1; ProgressBar.Max:=DeleteList.Count - i ; //Files = 8192 DeleteFile(GetIniString('List', 'File' + IntToStr(i),'','FileLi
procedure TForm1.Timer1Timer(Sender: TObject);
var
i:Integer;
begin
i:=i+1;
ProgressBar.Max:=DeleteList.Count - i ; //Files = 8192
DeleteFile(GetIniString('List', 'File' + IntToStr(i),'','FileLists.ini'));
ProgressBar.Position:=ProgressBar.Position+1;
end;
如果确实希望在删除文件时在UI中显示某些进度,则应使用线程:
- 创建一个线程,删除文件
- 然后从UI轮询删除线程的进度
使用线程时要小心,不要从删除线程中访问UI部件(如progressbar)。这样的事情至少应该同步。使用线程或IFileOperation都需要相当陡峭的学习曲线。以下是几种可能性: t目录方法 在Jerry Dodge的提示下,我决定添加一个使用TDirectory的示例 获取文件列表并以某种方式进行处理,例如删除列表中的文件 它会显示一条周期性进度消息-请参见
如果i mod 100=0则语句
在ProcessFiles
方法中。不幸的是,我找不到一个展示的方式
由于AFAIC TDirectory,在列表构建阶段出现一条周期性消息
不暴露必要的钩子来执行此操作
procedure TForm2.ProcessFileList(FileList : TStringList);
var
i : Integer;
S : String;
begin
for i := 0 to FileList.Count - 1 do begin
// do something with FileList[i], e.g. delete it
S := FileList[i];
DeleteFile(S);
// Display progress
if i mod 100 = 0 then // do something to show progress
Caption := Format('Files processed: %d ', [i]);
// OR, you could use i and FileList.Count to set a trackbar % complete
end;
Caption := Format('Processed: %d files', [FileList.Count]);
end;
procedure TForm2.GetFileList(const Path : String; FileList : TStringList);
var
Files : Types.TStringDynArray;
i : Integer;
begin
Files := TDirectory.GetFiles('C:\Temp');
FileList.BeginUpdate;
try
for i:= 0 to Length(Files) - 1 do
FileList.Add(Files[i]);
finally
FileList.EndUpdate;
end;
end;
procedure TForm2.Button1Click(Sender: TObject);
var
FileList : TStringList;
begin
FileList := TStringList.Create;
try
GetFileList('C:\Temp', FileList);
ProcessFileList(FileList);
Memo1.Lines.Text := FileList.Text;
finally
FileList.Free;
end;
end;
显然,这种方法比使用
传统的特定于Windows的方法,以牺牲一些灵活性为代价,
具有跨平台的优势
i操作方法(特定于Windows)
Windows API具有检索和处理文件列表的功能,例如在一个目录中,在TurboPower S/Ware的SysTools库(仿古版)v.3中,曾经有一个简单易用的包装,包括一个进度动画,但我不确定这个包装是否能进入更高的公共域版本。从表面上看,如果可以的话,也可以使用IFileOperation界面来实现,但谷歌还没有想出一个简单的例子。请注意,关于这一点的答案包含注释“”
我试图自己做这件事,但很快就不知所措了。雷米·勒博(Remy Lebeau)对我被卡住时发布的问题的回答说明了如何做到这一点,但在我的技能水平上,上面的t目录方法似乎要简单得多
传统(D7)方法(特定于Windows)
根据我的经验,如果您只希望处理几十万个文件,您应该能够做到这一点,通过将文件添加到TStringList中,然后使用以下代码进行处理,在运行过程中显示进度:
procedure GetFileList(const Path : String; Recurse : Boolean; FileList : TStringList);
// Beware that the following code is Windows-specific
var
FileCount : Integer;
procedure GetFilesInner(sPath : String);
var
Path,
AFileName,
Ext: String;
Rec: TSearchRec;
Done: Boolean;
begin
Path := IncludeTrailingBackslash(sPath);
if FindFirst(Path + '*.*', faAnyFile, Rec) = 0 then begin
Done := False;
while not Done do begin
if (Rec.Name <> '.') and (Rec.Name <> '..') then begin
AFileName := Path + Rec.Name;
Ext := LowerCase(ExtractFileExt(AFileName));
if not ((Rec.Attr and faDirectory) = faDirectory) then begin
inc(FileCount);
if FileCount mod 100 = 0 then
//show progress in GUI
;
FileList.Add(AFileName)
end
else begin
if Recurse then
GetFilesInner(AFileName);
end;
end;
Done := FindNext(Rec) <> 0;
end;
FindClose(Rec);
end;
end;
begin
FileCount := 0;
FileList.BeginUpdate;
FileList.Sorted := True;
FileList.Duplicates := dupIgnore; // don't add duplicate filenames to the list
GetFilesInner(Path);
FileList.EndUpdate;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
FileList : TStringList;
FileName : String;
i : Integer;
begin
FileList := TStringList.Create;
try
GetFileList('d:\aaad7', True, FileList);
for i := 0 to FileList.Count - 1 do begin
FileName := FileList[i];
// do something with FileName, e.g. delete the file
if i mod 100 = 0 then
// display progess e.g. by
Caption := IntToStr(i);
end;
Memo1.Lines := FileList;
finally
FileList.Free;
end;
end;
procedure-GetFileList(const-Path:String;Recurse:Boolean;FileList:TStringList);
//请注意,以下代码是特定于Windows的
变量
FileCount:整数;
过程GetFilesInner(sPath:String);
变量
路径
阿菲尔名字,
外部:字符串;
Rec:TSearchRec;
完成:布尔;
开始
路径:=包含轨道反斜杠(sPath);
如果FindFirst(路径+'*.*',faAnyFile,Rec)=0,则开始
完成:=错误;
未完即开始
如果是(Rec.Name'')和(Rec.Name'..'),则开始
AFileName:=路径+记录名;
Ext:=小写(ExtractFileExt(AFileName));
如果不是((Rec.Attr和faDirectory)=faDirectory),则开始
公司(文件计数);
如果FileCount mod 100=0,则
//在GUI中显示进度
;
FileList.Add(文件名)
结束
否则开始
如果再次发生,那么
GetFilesInner(AFileName);
结束;
结束;
完成:=FindNext(Rec)0;
结束;
FindClose(Rec);
结束;
结束;
开始
文件计数:=0;
FileList.BeginUpdate;
FileList.Sorted:=True;
FileList.Duplicates:=dupIgnore;//不要向列表中添加重复的文件名
GetFilesInner(路径);
FileList.EndUpdate;
结束;
程序TForm1.按钮2单击(发送方:TObject);
变量
文件列表:TStringList;
文件名:字符串;
i:整数;
开始
FileList:=TStringList.Create;
尝试
GetFileList('d:\aaad7',True,FileList);
对于文件列表中的i:=0。计数-1是否开始
FileName:=文件列表[i];
//对文件名执行某些操作,例如删除文件
如果我mod 100=0,那么
//显示进度,例如通过
标题:=IntToStr(i);
结束;
备注1.行:=文件列表;
最后
文件列表。免费;
结束;
结束;
如果[…]mod[…]=0,则可以在语句中显示两个阶段的进度,无论您希望如何
顺便说一句,这段代码是奥尔尼打算让你开始的。我不得不感谢Jerry Dodge提醒我,在Delphi的最新版本中,通过TDirectory.GetFiles方法内置了类似的功能,因此如果您对跨平台和/或采用Unicode感兴趣,您最好研究TDirectory和非Windows特定例程(如TrailingPathDelim)的详细信息。您遇到了什么问题?你真正的问题是什么?我的问题是,有没有可能用像FOF_simpleprogressbar这样的Tprogressbar删除文件?到目前为止,你做了哪些尝试?哪里出错了?在Windows上使用IFileOperation您的代码似乎出错了。变量i
在调用Timer1Timer
之间不保留其值,因为它是在堆栈上分配的;如果看起来是这样,那只是因为幸运的介入堆栈使用。另外,从Ini文件读取文件名是一种非常缓慢的方法:相反,将要删除的文件的名称保存在stringlist中,并从中获取名称。如何从Ul和第二个窗口对其进行轮询将不起作用hide@AkA然后,您可以使用计时器从线程中“读取”进度……线程:=TThread.CreateAnonymousThread(过程begin DeleteFolder('I:\J.A\Script\Output\Files');end);线程。开始;对于OP想要的东西来说,这种方法可能是不必要的复杂-参见@DavidHeffernan的评论。@MartynA可能是真的,但开发者在创建此类东西后遇到的第一件事是,当程序运行时,ui会被阻塞并且不会被更新