Delphi 显示耗时进程的进度

Delphi 显示耗时进程的进度,delphi,user-interface,dialog,Delphi,User Interface,Dialog,对不起,我的英语不好。。。 使用Delphi7,我想创建一个对话框窗口,当我不得不运行缓慢的进程时,显示我的应用程序中正在发生的事情。 我的想法是做一些我可以使用的事情,比如: with TMyDialog.Create do begin //call the time consuming method here Free; end; 当我创建对话框时,将显示一个带有动画或其他内容的窗口,并在耗时的方法结束后消失(在free方法上)-如果我可以手动更新该对话框中的进度,那就太好了,如果

对不起,我的英语不好。。。 使用Delphi7,我想创建一个对话框窗口,当我不得不运行缓慢的进程时,显示我的应用程序中正在发生的事情。 我的想法是做一些我可以使用的事情,比如:

with TMyDialog.Create do
begin
  //call the time consuming method here
  Free;
end;
当我创建对话框时,将显示一个带有动画或其他内容的窗口,并在耗时的方法结束后消失(在free方法上)-如果我可以手动更新该对话框中的进度,那就太好了,如果该过程向我提供以下信息:

with TMyDialog.Create do
begin
  while time_consuming_method do
  begin
    UpdateStatusOnMyDyalog();
  end;
  Free;
end;
但通常情况下,它只是一个动画来显示正在发生的事情


是否有人做过类似的事情,了解某个组件,或者对以最干净、最简单的方式完成它的最佳方式有什么建议?

您需要在单独的线程中运行耗时的进程,并让该线程使用同步向主UI线程报告其进度

这将向您展示如何启动一个新线程,并让该线程执行同步进度报告


--jeroen

您需要在一个单独的线程中运行耗时的进程,并让该线程使用同步将其进度报告给主UI线程

这将向您展示如何启动一个新线程,并让该线程执行同步进度报告


--jeroen

以这种方式报告进度是很常见的(例如,使用进度条)


您的“耗时流程”需要接收回调函数,该函数将在每次有进度报告时调用,或者,如果您愿意将其与用户界面设计更紧密地绑定,则需要接收对某种组件的引用,该组件将知道如何更新。这可以是一个进度条,它将步进,一个列表框或备忘录字段,它将接收状态更新的新行,一个标签控件,它的标题将得到更新,等等。

以这种方式报告进度是很常见的(例如,使用进度条)


您的“耗时流程”需要接收回调函数,该函数将在每次有进度报告时调用,或者,如果您愿意将其与用户界面设计更紧密地绑定,则需要接收对某种组件的引用,该组件将知道如何更新。这可以是一个进度条,它将步进,一个列表框或备忘录字段,它将接收带有状态更新的新行,一个标签控件,它的标题将得到更新,等等。

做这件事的不好但简单的方法是调用
应用程序。处理消息
更新窗口(句柄)
(更新表单)并在
耗时的方法中增加一个进度条。一个稍微好一点的方法是将您的
耗时方法
封装到一个带有OnProgress事件的类中。最后,正如其他人所建议的那样,您可以为您的
耗时的方法使用一个单独的线程,这是最强大的技术,但学习曲线最差。

最糟糕但简单的方法是调用
应用程序。ProcessMessages
更新域(句柄)
(更新表单)并在
耗时的方法中增加一个进度条。一个稍微好一点的方法是将您的
耗时方法
封装到一个带有OnProgress事件的类中。最后,正如其他人建议的那样,您可以为您的
耗时方法使用单独的线程,这是最强大的技术,但学习曲线最差。

在长时间操作中显示进度取决于几个因素(限制):

  • 已定义/未定义的进度(您知道, 可以计算一下,有多少步骤 手术时间(星期五)
  • 可中断性/分段(您需要) 将能够或不得不中断 刷新进度的操作 (向用户发送)
  • 该操作是线程可执行的(您可以 将操作置于线程中)
对于已定义的进度,通常显示分段进度条,对于未定义的进度条,通常显示样式为“字幕”的动画或进度条

主要考虑的是操作是否分段/可中断。因为如果不是,并且您不处理它,您的应用程序将冻结,直到操作完成。 搜索文件是分段操作的一个示例。找到的每个文件都是一个段,它使您能够向用户显示进度,并刷新显示

例如:

TFrmUndefinedProgress = class(TForm)
private
   FCallbackProc           : TNotifyEvent;
protected
   procedure WndProc(var Message:TMessage); override;
public
   constructor Create(aCallbackProc: TNotifyEvent);
  procedure UpdateProgress(const aStr : string; aPercent : integer); 
...
constructor TFrmUndefinedProgress.Create(aCallbackProc: TNotifyEvent);
begin
   inherited Create(nil);
   FCallbackProc     := aCallbackProc;
end;
...
procedure TFrmUndefinedProgress.FormShow(Sender: TObject);
begin
   Update;
   PostMessage(Handle, WM_START_UNDEFPROG, 0, 0); 
end;
将消息发送到窗体OnShow上的窗口过程,以确保首先呈现该过程

procedure TFrmUndefinedProgress.WndProc(var Message: TMessage);
begin
   if (Message.Msg = WM_START_UNDEFPROG) then begin
      if Assigned(FCallbackProc) then
         FCallbackProc(Self); --> Call your callback procedure
   PostMessage(Handle, WM_CLOSE, 0, 0); --> close when finished
   end
   else
   inherited;
end;
如果你在你的表格中做了一个常规的程序

procedure ShowUndefinedProgress(aCallbackProc : TNotifyEvent);
var
   FrmUndefinedProgress : TFrmUndefinedProgress;
begin
   FrmUndefinedProgress := nil;
   try
      FrmUndefinedProgress         := TFrmUndefinedProgress.Create(aCallbackProc);
      FrmUndefinedProgress.ShowModal;
   finally
      FreeAndNil(FrmUndefinedProgress);
   end;
end;
然后,您可以这样调用进度表:

ShowUndefinedProgress(HandleSomeOperation);
在那里你通过你的aCallbackProc。 你把你的手术放在里面:

procedure TForm1.HandleSomeOperation(Sender: TForm);
var
   aProgress : TFrmUndefinedProgress;
begin
   --> Do something
   aProgress := TFrmUndefinedProgress(Sender);
   aProgress .UpdateProgress(SomeMessage, Percent);
更新找到的每个文件的显示

如果您有一个需要很长时间的操作,但是您无法中断它,那么您应该将它放入一个线程中

  • 创建TThread对象的后代
  • 重写它的执行方法
  • 在里面做你的事 并使用它:
  • 创建表单
  • 在电视上播放一些动画
  • 然后运行你的线程
  • 线程结束时关闭

在长时间操作期间显示进度取决于几个因素(限制):

  • 已定义/未定义的进度(您知道, 可以计算一下,有多少步骤 手术时间(星期五)
  • 可中断性/分段(您需要) 将能够或不得不中断 刷新进度的操作 (向用户发送)
  • 该操作是线程可执行的(您可以 将操作置于线程中)
对于已定义的进度,通常显示分段进度条,对于未定义的进度条,通常显示样式为“字幕”的动画或进度条

主要考虑的是操作是否分段/可中断。因为如果是n