Display Animated Form (GIF) while a while is executed

6

In the application I'm developing, I need to check if a process is running on the system, so I use a IsRunningProcess function.

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

I also tried the Progressbar and Gauge components using a Timer , but I was not successful either. For example, a part of the code follows.

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;
    
asked by anonymous 19.10.2014 / 19:09

3 answers

5

With ProgressBar and Gauge you probably did not 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 is. I have tried to put it once, it was not native to using animated gifs and then replaced with other shapes, usually ProgressBar or Gauge because I always need to give feedback on the processing time.

To update the form I know three ways:

  • FrmProgress.Update;
  • FrmProgress.Refresh;
  • Application.ProcessMessages.
  • The first two ( Update and Refresh ) apply only to the form ( FrmProgress ) and only it handles the display updates. Unfortunately I do not 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 one, Application.ProcessMessages sends an order to the whole system to process all information that has not yet been processed in the display.

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

    On your issue, I do not know what's done with this IsRunningProcess method, nor why you use it in while , but actually it can be used to implement one of these methods I showed you and then remove the "locked" program impression.

    It would be:

    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 testing

    I do not know what to do with your IsRunningProcess function, but I'd venture to say that FrmProgress.Show; and FrmPrincipal.Hide; need not be within while . I believe it's 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;
    
        
    20.10.2014 / 00:00
    3

    An easy way to make your form display the spinning image would be to use Sleep and ProcessMessages , otherwise it would be by using 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 still implement the following:

    procedure frmProgress.onDeActivate(Sender: TObject)
    begin
        If frmProgress.CanFocus then
          frmProgress.SetFocus;
    end;
    
        
    20.10.2014 / 16:27
    0

    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;
    
        
    28.01.2017 / 10:27