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;
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:
- FrmProgress.Update;
- FrmProgress.Refresh;
- 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;
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;
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;