Progress Dialog + Cancel => solutions dispo ... [Delphi] - Delphi/Pascal - Programmation
Marsh Posté le 22-07-2002 à 10:30:09
Ce que j'avais fait c'est une fenêtre qui désactivait la fenêtre appelante :
procedure Execute(Sender: TForm);
begin
Sender.Enabled := False;
try
Show;
finally
Sender.Enabled := True;
end;
end;
(il me semble, faudrait que je vérifie que ça suffit)
Donc l'appelante n'était pas bloquée dans son processus, mais l'utilisateur ne pouvait plus cliquer dedans puisque bloquée.
Pour le système de Cancel tu peux faire ce que tu avais fait dans ton premier exemple j'imagine.
Pour que tout ce qui est affichage et réception des commandes de l'utilisateur se fasse bien, il faut souvent faire des Application.ProcessMessages;
Marsh Posté le 22-07-2002 à 10:48:27
Ouais, c'est une solution pour la première methode (pas de thread supplémentaire).
Je vais sans doute faire ça, mais j'aurais bien aimé faire la manip avec un thread (pour l'esthétique !).
Marsh Posté le 22-07-2002 à 11:20:27
Ton thread il sert à kedal là.... complétement inutile
Si tu veux utiliser un thread il fo que tu mettes ton traitement ds le thread (c-à-d ta boucle !!!) sinon C complétement inutile...
Marsh Posté le 22-07-2002 à 11:37:53
Poire : je me suis sans doute mal expliqué :
Le but de la manoeuvre est de faire un ShowModal sur la ProgressForm pour empecher l'utilisateur de faire n'importe quoi avec la forme appelante (dans un programme Windows classique, les ProgressDialog sont Modal). La soluce de ANTP de faire un DISABLE sur la form appelante marche, mais je voudrais faire la manip avec un thread (notes que je vais pas m'entêter 10 ans sachant que j'ai un truc qui marche, mais ça me chagrine de rester sur un semi-echec).
Si on utilise pas de thread, l'appli principale se bloque sur le ShowModal, et donc le traitement de la boucle principale est stoppé.
De plus, le code de la boucle ne peut pas être dans la ProgressForm, sinon il faudrait déclarer une ProgressForm par traitement différent (ce dialog s'affiche pour plusieurs actions, comme des ouvertures des fichiers, des ecritures, des tris, etc...).
Donc, dans le cas décrit plus haut, le thread sert à ce que les clics utlisateurs soient possible sur la ProgressForm. En effet, le ShowModal est appelé par le thread, donc c'est lui qui se bloque et pas l'appli principale qui peut alors continuer sa boucle.
Ca marche bien, mais ça rame à mort.
Marsh Posté le 22-07-2002 à 12:21:54
C toi qui me comprend pas
Moi G trés bien compris ce que tu veux faire
mais t'as pas le droit de faire un thread comme ça
t'execute le thread avec ton traitement (ta boucle) ds ton form1 et t'appel ton form2 en showmodal tjs ds ton form1
ton form1 est bloqué (il attend le résultat du form2) mais C pas grave vu que ton traitement est ds ton thread qui lui n'est pas bloqué
Toi comprendre l'idée ?
Marsh Posté le 22-07-2002 à 12:54:36
Moi y'en a comprendre, mais moi y'en a être un peu nul comparé à toi, alors moi faire toi excuses d'être aussi con.
Sauf que le traitement à réaliser ne se trouve PAS et ne peut PAS se trouver dans le thread, parceque sinon faudrait que je déclare 50 threads différents, 1 pour chaque type d'action, et ça c'est pas envisageable ... a moins de faire du CallBack.
Sinon j'comprends bien que c'est la solution idéale.
M'enfin bon, on en restera là.
PS : Sachant, et tu l'auras bien compris, que je me tappe que le code de la boucle soit exécuté en parallèle (l'utilisateur doit attendre la fin avant de faire autre chose).
Marsh Posté le 22-07-2002 à 14:20:48
Bon, disons donc que tu veux pas faire un thread vu que le traitement doit pas se faire en parallèle, et admettons donc que la solution du disable te plaise pas.
Il reste la solution du callback.
En fait, quand tu fais ton ShowModal, il ne revient pas tant que la fenêtre n'est pas fermée, ok? Mais ton application n'est pas morte, c'est juste que t'attends un joli évènement.
Soit, tu peux donc faire le traitement via ton form modal, ok? Mais tu peux pas le faire dans le form progress ca n'a aucun sens, ok? (Ca devient long pour une réponse en 2 lignes )
with TForm2.Create(nil) do
try
OnModal := TaFonction;
ShowModal;
finally
Free;
end;
T'as plus qu'a définir l'event OnModal dans ton form2, ta fonction qui sera apellée et tu l'apelles dans le Show du form2, et voila une solution à 0.02?
Marsh Posté le 22-07-2002 à 15:29:08
Bien vu Mr.
Ca tourne nickel (en plaçant le callback dans le OnActivate parceque dans le OnShow le callback se termine avant affichage de la Form2).
Tks A+.
Marsh Posté le 22-07-2002 à 15:50:07
Attention au OnActivate, il survient chaque fois que la fenêtre prend le focus (donc aussi quand on passe d'un soft à l'autre)
Marsh Posté le 22-07-2002 à 10:10:28
J'voudrais faire l'inévitable fenêtre de progression avec le bouton cancel (pas trouvé en cherchant sur le forum Delphi).
La 1ère solution consiste en un truc du style :
Application.CreateForm(TForm2, Form2);
with Form2 do
begin
Show;
for i:=1 to 100 do
begin
if (Stop) then
begin
ShowMessage('Processus interrompu par l''utilisateur';
Break;
end else
begin
ProgressBar1.StepIt;
Sleep(100);
Application.ProcessMessages;
end;
end;
end;
Form2.Free;
Sachant que la Form2 contient la ProgreesBar et un boutton Cancel qui fait passer Form2.Stop à true.
Ca marche pas trop mal, mais le fait qu'on fasse un Form2.Show et pas un ShowModal implique que l'utilisateur peut faire un peu n'importe quoi.
D'un autre côté, un Form2.ShowModal impliquerait que l'appli principale soit bloquée, or le code du traitement (ici le sleep) s'y trouve. Et il est hors de question de passer le code dans la Form2, because le ProgressDialog sert à de multiples endroits.
Donc, j'ai testé avec un Thread comme suit :
Thread := TMyThread.Create;
for i:=1 to 100 do
begin
if (Thread.Stop) then
begin
ShowMessage('Processus interrompu par l''utilisateur';
Break;
end else
begin
Thread.StepIt;
Sleep(100);
end;
end;
Thread.Free;
Avec le thread suivant :
//**********************************************************************************
constructor TMyThread.Create;
begin
inherited Create(False);
FreeOnTerminate := false;
stop := false;
Form2 := TForm2.Create(nil);
end;
//**********************************************************************************
destructor TMyThread.Destroy;
begin
Form2.Free;
inherited;
end;
//**********************************************************************************
procedure TMyThread.Execute;
begin
inherited;
Form2.ShowModal;
stop := Form2.Stop;
end;
//**********************************************************************************
procedure TMyThread.StepIt;
begin
Synchronize(Form2.ProgressBar1.StepIt);
end;
//**********************************************************************************
Seulement ça merde pas mal:
1. Ca rame grave (la form2 s'affichage supra lentement et le clic du Cancel prend des plombes avant de réagir).
2. Le Form2.Free plante dans le Destructor.
J'imagine que ce prb a été traité depuis belle lurette ?