View Form with animation (gif) while a while runs

Asked

Viewed 3,133 times

6

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) which 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 the components Progressbar and Gauge using a Timer, but I was also unsuccessful. To illustrate 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;
  • 2

    Should this form prevent access to other windows? Would it be like a splash screen? if an interesting example is put here later.

3 answers

5

With ProgressBar and Gauge you probably did not succeed because you would need to be updating the FrmProgress.

Because with ProgressBar and/or Gauge? I don’t know what the behavior of an animated gif is like at Delphi. I already tried to put once, it was not native the use of animated gifs and then replace by other forms, usually ProgressBar or Gauge because I always need to give feedback on processing time.

To update the form I know three ways:

  1. Frmprogress.Update;
  2. Frmprogress.Refresh;
  3. Application.Processmessages.

The first two (Update and Refresh) you apply only on the form (Frmprogress) and only it processes 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 latter, the Application.ProcessMessages you send an order to the entire system to process all information that has not yet been processed on the display.

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

About your problem, I don’t know what is done in this method IsRunningProcess and not because you use it in a while, but actually it can be used to implement one of those methods I showed you and then remove the program print "locked".

Seria:

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 don’t know what you have in your job IsRunningProcess, but I would venture to say that FrmProgress.Show; and FrmPrincipal.Hide; would not need to be inside the while. I believe it’s unnecessary processing.

Try it like 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;
  • The Gauge no FrmProgress is displayed when using the procedures (Refresh, Update or Repaint), is still "frozen", and no progress is displayed.

  • 1

    Using the Application.ProcessMessages the progress is displayed.

  • 1

    I tested your suggestion and it also works by putting the FrmProgress.Show and the FrmPrincipal.Hide, but I do not believe that the procedure IsRunningProcess is locking the entire application, since with the Application.ProcessMessages works perfectly.

3

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

procedure frmProgress.onDeActivate(Sender: TObject)
begin
    If frmProgress.CanFocus then
      frmProgress.SetFocus;
end;
  • Using the Application.Messages works perfectly, but I didn’t understand what you meant when applying the SetFocus the form, since the procedure OnDeactivate the form will no longer be active, so an error will occur when setting the focus to the inactive window.

  • Missed a Canfocus , I will correct!

  • The purpose of Setfocus is to make sure that as long as Firm is active, if someone clicks outside it, it returns the focus, similar to a modal, @zapSys

0

Delegate the processing to a thread in the background. You can do this using German 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;

Browser other questions tagged

You are not signed in. Login or sign up in order to post.