Display form with animation (gif) while a while is running

In the application I am developing I need to check if a process is running on the system, for this I use a function (isrunningprocess).

However, I would like to display a form (FormProgress) that contains a gif of loading while a specific process runs. The problem is that the animation is not shown, it seems that the form gets frozen.

I also tried with components Progressbar and gauge using a timer, but I also did not succeed. To exemplify follows a part of the code.

while IsRunningProcess('nome_do_processo') do
begin
  FrmProgress.Show;
  FrmPrincipal.Hide;
end;
FrmProgress.Close;
Application.MessageBox('Operação concluída com sucesso!', 'Ferramentas',
    MB_ICONEXCLAMATION + MB_OK);
FrmPrincipal.Visible := True;
Author: ZapSys, 2014-10-19

3 answers

With ProgressBar and Gauge you probably didn't succeed because you would need to be updating FrmProgress.

Because with ProgressBar and / or Gauge? I do not know what the behavior of an animated gif in Delphi looks like. I have tried to put once, it was not native the use of animated gifs and then replaces it with other forms, usually ProgressBar or Gauge because I always need to give a feedback of time traveled in processing.

To update the form I know three forms:

  1. FrmProgress.Update;
  2. FrmProgress.Refresh;
  3. Application.ProcessMessages.

The first two (Update and Refresh ) you apply only in the form ( FrmProgress) and only it processes the display updates. Unfortunately I don't know the difference between the two. But both make use of the Repaint method, which can also be called directly: FrmProgress.Repaint;.

In the last, Application.ProcessMessages you send an order to the system integer to process all information that has not yet been processed on the display.

For all options more in-depth information, by source, would be interesting.

About your problem, I do not know what is done in this method IsRunningProcess and nor why you use it in a while, but in fact it can be used to implement one of these methods that I showed you and then remove the print of "stuck"program.

Series:

while IsRunningProcess('nome_do_processo') do
begin
  FrmProgress.Show;
  FrmPrincipal.Hide;
  FrmProcess.Refresh;
  // ou FrmProgress.Update;
  // ou Application.ProcessMessages; // esse, em threads, costuma dar problemas
end;
FrmProgress.Close;
Application.MessageBox('Operação concluída com sucesso!', 'Ferramentas', 
  MB_ICONEXCLAMATION + MB_OK);
FrmPrincipal.Visible := True;

A suggestion for tests

I don't know what you have in your function IsRunningProcess, but I would risk saying that FrmProgress.Show; and FrmPrincipal.Hide; don't need to be inside while. I believe it is unnecessary processing.

Try This:

FrmProgress.Show;
FrmPrincipal.Hide;
while IsRunningProcess('nome_do_processo') do
begin
  FrmProgress.Refresh;
  // ou FrmProgress.Update;
  // ou Application.ProcessMessages; // esse, em threads, costuma dar problemas
end;
FrmProgress.Close;
Application.MessageBox('Operação concluída com sucesso!', 'Ferramentas', 
  MB_ICONEXCLAMATION + MB_OK);
FrmPrincipal.Visible := True;
 5
Author: ZapSys, 2014-10-20 22:24:25

An easy way to make your Form Display the rotating image would be to use Sleep and ProcessMessages, another way would be through the use of Threads

frmProgress.FormStyle := fsStayOnTop;
frmProgress.Postition := poScreenCenter;
frmProgress.Show

while IsRunningProcess('nome_do_processo') do
begin
  Sleep(200);
  Application.ProcessMessages;
end;

FrmProgress.Close;

Application.MessageBox('Operação concluída com sucesso!', 'Ferramentas', 
  MB_ICONEXCLAMATION + MB_OK);

FrmPrincipal.Visible := True;

To prevent users from interacting with the system you can further implement the following:

procedure frmProgress.onDeActivate(Sender: TObject)
begin
    If frmProgress.CanFocus then
      frmProgress.SetFocus;
end;
 3
Author: Caputo, 2014-10-20 22:10:55

Delegate processing to a background thread. You can do this using anonymous methods:

TThread.CreateAnonymousThread(procedure ()
  begin
    TThread.Synchronize (TThread.CurrentThread,
      procedure ()
      begin
      frmProgress.FormStyle := fsStayOnTop;
      frmProgress.Postition := poScreenCenter;
      frmProgress.Show
      end);
    while IsRunningProcess('nome_do_processo') do
    TThread.Synchronize (TThread.CurrentThread,
      procedure ()
      begin
          label1.text := formatFloat('#00.00% concluído...',AlgumValor);
          //Sendo que AlgumValor é uma var publica atualizada pelo 

'nome_do_processo'

end;

  end).Start;
frmProgress.close;

In the example, I monitor the progress of the process. Whenever you want to update the form call a Synchronize method.

In the example below I show a counter that updates the form every 40 numbers

TThread.CreateAnonymousThread(procedure ()
  begin
    TThread.Synchronize (TThread.CurrentThread,
      procedure ()
      begin
      frmProgress.FormStyle := fsStayOnTop;
      frmProgress.Postition := poScreenCenter;
      frmProgress.Show
      end);
    //while IsRunningProcess('nome_do_processo') do
for AlgumValor:=0 to MaxNum do
    If AlgumValor mod 40 = 0 then
        TThread.Synchronize (TThread.CurrentThread,
          procedure ()
          begin
              label1.text := formatFloat('#00.00% concluído...',AlgumValor/MaxNum);        
    end;
      end).Start;

frmProgress.close;
 0
Author: Ricardo da Rocha Vitor, 2017-01-28 09:35:06