Autor Beitrag
Mathematiker
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: So 05.01.14 20:56 
Hallo,
bei dem einen oder anderen Programm möchte ich eine schnell laufende Animation erreichen und verzichte deshalb auf einen Timer.
Konkret läuft in einer Methode die Animation in der Form:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
procedure animation(sender:tobject);
begin
    if animationlaeuft then
    begin
       animationlaeuft:=false;
       exit;
    end
    else
    begin
       animationlaeuft:=true;
       repeat
         ... //Animation
         application.processmessages; //im Normalfall nicht bei jedem Durchlauf
         ...  
       until not animationlaeuft;
    end;
end;

procedure schliessen(sender:tobject);
begin
    if animationlaeuft then animationlaeuft:=false;
    close;
end;

Sobald die Variable animationlaeuft auf false gesetzt wird (evtl. Buttonklick) stoppt die Animation. Das funktioniert auch perfekt mit der Methode schliessen, die dann auch das Programm beendet.

Nun mein Problem: Wie kann ich erreichen, dass der Standard-Schließbutton in der Titelzeile ebenfalls die Animation stoppt und das Programm beendet?
Meine Versuche, in die Ereignisse Onclose oder Onclosequery die zwei Zeilen von schliessen einzutragen, funktionieren nicht. Während der Animation wird scheinbar keines dieser Ereignisse durch den Schließbutton ausgelöst. Ich kann soviel ich will auf den Schließbutton drücken, es passiert nichts. Beende ich mit der Methode schliessen ist dagegen alles in Ordnung.

Welches Ereignis wird denn ausgelöst, wenn ich auf den Schließbutton drücke?
Ich bin mir nicht ganz sicher, aber kann es sein, dass es unter Vista und XP noch funktionierte? Irgendwie komisch.

Beste Grüße
Mathematiker

Nachtrag: Hat sich eigentlich erledigt. Ich habe es hingekriegt mit
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm.WndProc(var msg:TMessage);
begin
    case Msg.Msg of
      WM_CLOSE: begin
                  if sofortabbruch=false then sofortabbruch:=true;
                  close;
                end  
    Else
      inherited;
    end;
end;

Aber vielleicht hat jemand ja noch eine bessere Idee.

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein


Zuletzt bearbeitet von Mathematiker am So 05.01.14 22:43, insgesamt 1-mal bearbeitet
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1600
Erhaltene Danke: 232


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: So 05.01.14 21:18 
Ich kann da leider nur aus bescheidenen Erfahrungen schöpfen.

Mit Application.Processmessages nimmt ein auch im VCL-Thread vollbeschäftigtes Formularprogramm Eingaben wahr und löst die entsprechende(n) Ereignisbehandlungsroutinen aus. Dort kann man irgendeine Variable umschalten. Diese Variable wird in der eigentlichen Berechnung (nahezu) ständig ausgewertet - so eine Art Polling (kein Eingabe-, sondern ein Variablenpolling). So läuft es in meinem "Sortierkino".

Oder man agiert mit einem Extrathread, aber das ist aufwendiger (synchronize bei Formularausgaben). Den kann man sich selbst separat beenden lassen oder von außen gewaltsam abschießen (s. mein unfertiger "Langzahlentaschenrechner"), aber das ist unelegant.

Edit: Da waren wir wohl im Geschwindigkeitswettstreit, ohne daß wir es wußten.

Edit 2: Beim X-Druck werden OnClose und OnCloseQuery ausgelöst, die Reihenfolge weiß ich jetzt aber nicht (einfach mal mit z.B. Messagesboxen oder verschiedenfrequenten Pieptösnen ausprobieren).

Für diesen Beitrag haben gedankt: Mathematiker
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 429
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: So 05.01.14 22:13 
Wenn Du im OnClick einer Schaltfläche CLOSE aufrufst,
wird über Zwischenwege Application.Terminate aufgerufen, das sendet an Windows das PostQuitMessage, die Anwendung wird von Windows beendet.

Drückst Du die Schaltfläche "Schließen" oben rechts im Fenstertitel passiert das nicht.
Zwar merkt Delphi vor, daß die Anwendung geschlossen werden soll, bleibt aber in der repeat-Schleife mit dem Processmessages "kleben".

Abhilfe:

ausblenden Delphi-Quelltext
1:
until not animationlaeuft or Application.Terminated;					

Für diesen Beitrag haben gedankt: Mathematiker
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: So 05.01.14 22:26 
Hallo,
user profile iconDelphi-Laie hat folgendes geschrieben Zum zitierten Posting springen:
Beim X-Druck werden OnClose und OnCloseQuery ausgelöst, die Reihenfolge weiß ich jetzt aber nicht (einfach mal mit z.B. Messagesboxen oder verschiedenfrequenten Pieptösnen ausprobieren).

Danke für den Tipp. Nur leider funktioniert es nicht.
Läuft die Animation, so bewirkt das Klicken auf X kein "Hineinspringen" in die Methoden von beiden Ereignissen.

user profile iconmandras hat folgendes geschrieben Zum zitierten Posting springen:
Wenn Du im OnClick einer Schaltfläche CLOSE aufrufst,
wird über Zwischenwege Application.Terminate aufgerufen, das sendet an Windows das PostQuitMessage, die Anwendung wird von Windows beendet.

Ebenfalls Danke. Das Problem ist, dass ich auch eine Idee suche (habe mich im 1.Beitrag nicht ganz konkret ausgedrückt), wenn nur ein Formular geschlossen werden soll und nicht die ganze Anwendung. Dann geht es so leider nicht.

Beste Grüße
Mathematiker

Nachtrag: Sehr ärgerlich. Die Idee mit
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm.WndProc(var msg:TMessage);
begin
    case Msg.Msg of
      WM_CLOSE: begin
                  if sofortabbruch=false then sofortabbruch:=true;
                  close;
                end  
    Else
      inherited;
    end;
end;

funktioniert in einer anderen Anwendung nicht. Dagegen bekomme ich die Meldung, dass mein WndProc die virtuelle Methode von TCustomform verbirgt. :nixweiss:

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 429
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: So 05.01.14 23:01 
Hm..
1) Kann es sein, daß Du bei der Deklaration der WndProc das override vergessen hast?
2) Ich habe (allerdings mit D6) eine Anwendung mit 2 Fenstern erstellt.
Auf dem Hauptfenster ein Button, der nur das 2. Fenster anzeigt.
2. Fenster: Ein Button der die "repeat ... processmessages" auslöst.

Wenn ich "Close" im Fenstertitel klicke passiert folgendes:
Fenster 2 wird geschlossen, Fenster 1 läßt sich nicht mehr über sein "Close" im Titel schließen.
Soweit logisch, Fenster 2 ist unsichtbar, die Schleife mit dem Repeat aber noch aktiv.

! Bei dieser Konstellation kann ich aber in der Repeat-Schleife prüfen, ob das Form noch auf "visible" steht. -> Wenn nein: Schleife beenden.
! Wenn das Form mit der processmessages-Schleife nicht das Hauptformular der Anwendung ist, werden hier wie erwartet die OnClose-Ereignisse ausgelöst über die Close-Fläche im Titel.

Für diesen Beitrag haben gedankt: Mathematiker
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: So 05.01.14 23:08 
Hallo,
user profile iconmandras hat folgendes geschrieben Zum zitierten Posting springen:
1) Kann es sein, daß Du bei der Deklaration der WndProc das override vergessen hast?

Genau das ist es und wieder typisch für mich. :autsch:
Besten Dank, denn jetzt funktioniert es mit WndProc einwandfrei.

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1600
Erhaltene Danke: 232


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: So 05.01.14 23:19 
user profile iconmandras hat folgendes geschrieben Zum zitierten Posting springen:
Wenn ich "Close" im Fenstertitel klicke passiert folgendes:
Fenster 2 wird geschlossen, Fenster 1 läßt sich nicht mehr über sein "Close" im Titel schließen.
Soweit logisch, Fenster 2 ist unsichtbar, die Schleife mit dem Repeat aber noch aktiv.


Das ist tückisch und war mir zugegenermaßen auch nicht (mehr) bewußt. Bei Programmen, die mit dem Visual-Studio erstellt wurden, beendet der X-Druck das Formular tatsächlich, auch untergeordnete Formulare (zumindest die mit C# erstellten, soweit ich mich recht entsinne). Greift man danach - z.B. in guter alter Delphi-Gewohnheit, es wieder sichtbar zu machen - erneut darauf zu, kommt natürlich irgendein Programmfehler (Exzeption o.ä.).

Unabhängig vom Formular kann man natürlich die Variable in der repeat-until-Schleife ständig abfragen und natürlich ggf. die Schleife beenden.
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Mo 06.01.14 20:32 
Hallo,
ich muss noch einmal auf das Thema zurückkommen. Durch den Hinweis von user profile iconmandras auf ein geschlossenes Fenster mit noch laufender Schleife bin ich vorsichtig geworden.
Daher habe ich Folgendes versucht:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
procedure form.animation(sender:tobject);
begin
    if animationlaeuft then animationlaeuft:=false
    else
    begin
       animationlaeuft:=true;
       schliessbar:=false;
       repeat
         ... application.processmessages; ...  
       until not animationlaeuft;
       schliessbar:=true;
    end;
end;
procedure form.WndProc(var msg:TMessage);
begin
   case Msg.Msg of
      WM_CLOSE: begin
                  if animationlaeuft then animationlaeuft:=false;
                  if schliessbar then close;
                end
    Else
      inherited;
    end;
end;

Erwartet habe ich nun, dass bei Klick auf das X (Schließen) die Animation gestoppt wird und das Fenster sich schließt. Und natürlich schließt es sich nicht!
D.h. also bei der ursprünglichen Variante
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure form.WndProc(var msg:TMessage);
begin
   case Msg.Msg of
      WM_CLOSE: begin
                  if animationlaeuft then animationlaeuft:=false;
                  close;
                end
    Else
      inherited;
    end;
end;

schließt sich das Fenster und die Schleife läuft wohl noch weiter; oder wird geschlossen, wenn das Fenster nicht mehr existiert (geht ja wohl nicht), da ich bei der Rückkehr zum aufrufenden Formular form.release aufrufe.
Dann müsste es doch aber irgendwelche Probleme geben, von harmlosen Fehlermeldungen bis gravierenden Programmabstürzen.
Aber nichts passiert. Ich habe heute auf meinem "schnellen" PC unter Win 8.1 getestet, auf einem etwas langsameren mit Win 7 (64) und auf einer "lahmen Ente" mit XP.
In allen Fällen gab es keine Schwierigkeiten, wenn ich sofort das close ohne den Test auf schliessbar aufrufe. Mit dem Test bleibt das Fenster offen.

Das verstehe ich nun nicht mehr.
Kann ich davon ausgehenden, dass die Methode WndProc in der Form ohne den Sicherheitstest, ob die Animation beendet ist, funktioniert? Irgendwie werde ich das Gefühl nicht los, dass da noch ein "böser" Fehler lauert, der zuschlägt, wenn ich es nicht erwarte.

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 06.01.14 22:37 
Wieso nicht einfach in OnCloseQuery vor der Zeile CanClose := True die Variable animationlaeuft auf False setzen?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
Procedure TFormMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose := False;

  AnimationLaeuft := False;  
  SonstigenKramErledigen;
  AlleKlassenFreigeben;

  CanClose := True;
end;


OnCloseQuery wird beim Schließen des Formulars aufgerufen. Ist das Forumlar das Hauptformular, wird das Programm beendet.


Zuletzt bearbeitet von Perlsau am Mo 06.01.14 22:38, insgesamt 1-mal bearbeitet

Für diesen Beitrag haben gedankt: Mathematiker
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Mo 06.01.14 22:50 
Hallo,
Danke für die Antwort.
user profile iconPerlsau hat folgendes geschrieben Zum zitierten Posting springen:
Wieso nicht einfach in OnCloseQuery vor der Zeile CanClose := True die Variable animationlaeuft auf False setzen? ...
OnCloseQuery wird beim Schließen des Formulars aufgerufen. Ist das Forumlar das Hauptformular, wird das Programm beendet.

Das habe ich schon ausprobiert; und jetzt noch einmal. Und genau dort liegt mein Problem.
Während der Animation kann ich noch so oft auf den X-Button klicken. OnCloseQuery wird scheinbar nicht ausgelöst, denn das Programm springt einfach nicht in die Methode hinein; obwohl es funktionieren müsste.
Allerdings funktioniert es sofort, wenn es um das Hauptformular geht, nur eben nicht bei weiteren Formularen.

Ich weiß im Moment nicht weiter. Wahrscheinlich habe ich irgendwo ein anderes Problem.

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 06.01.14 22:57 
user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
Das habe ich schon ausprobiert; und jetzt noch einmal. Und genau dort liegt mein Problem. Während der Animation kann ich noch so oft auf den X-Button klicken. OnCloseQuery wird scheinbar nicht ausgelöst, denn das Programm springt einfach nicht in die Methode hinein; obwohl es funktionieren müsste. Ich weiß im Moment nicht weiter. Wahrscheinlich habe ich irgendwo ein anderes Problem.

Wenn du die Animation nicht als eigenen Thread laufen läßt, kommt dein "Programmzeiger" ja von der Animations-Procedure gar nicht mehr zurück, sobald diese gestartet wurde ... In der Message-Queue steht zwar schon der Klick auf das Titelzeilen-X und wartet darauf, endlich dranzukommen, aber er kann erst abgearbeitet, wenn die zuvor aufgerufene Procedure beendet ist.

Für diesen Beitrag haben gedankt: Mathematiker
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Mo 06.01.14 23:06 
Hallo,
user profile iconPerlsau hat folgendes geschrieben Zum zitierten Posting springen:
Wenn du die Animation nicht als eigenen Thread laufen läßt, kommt dein "Programmzeiger" ja von der Animations-Procedure gar nicht mehr zurück, sobald diese gestartet wurde ...

Danke für den Hinweis.
Aber, deshalb wird ja in der Animation application.processmessages gerufen. Und wie weiter oben gesagt, über WndProc funktioniert es ja, aber mit dem für mich blöden Beigeschmack, dass ich der ganzen Sache nicht vertraue.

Ich vermute, dass es mit FormCloseQuery nicht so wie erwartet will, hat vielleicht etwas mit meinem nicht gerade frischem Delphi 5 und der Tatsache, dass das 2.Fenster modal ist, zu tun.

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 429
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: Di 07.01.14 00:21 
Ich habe (siehe oben) mit D6 getestet.
Meine Erkenntnisse waren:
Wenn das Form das MainForm ist klappt das ganze nicht (es wird zwar Application.Terminated gesetzt, da das Programm aber in der Repeat-Schleife "hängt" hat dies keine Auswirkungen. OnClose und OnCloseQuery wird nicht aufgerufen wenn man den "Close"-Button der Titelleiste betätigt. Über einen Extra-Button der die "Close"-Methode des Forms aufruft funktioniert es.

Wieder Close-Button der Titelleiste: Wenn das Form _nicht_ das Main Form ist wird es zwar geschlossen, die repeat-Schleife aber nicht beendet.

! Wenn das Form nicht Main Form ist, ist es egal, ob es modal ist oder nicht. Geschlossen wird es.

Der Code von Mathematiker von 19:32 ist auch nicht der Weisheit letzter Schluß:

ausblenden Delphi-Quelltext
1:
2:
      if animationlaeuft then animationlaeuft:=false;
                  if schliessbar then close;


Das kann nicht funktionieren.
Schließbar ist vorher false. Es wird erst auf true gesetzt in .animation.
.animation wird aber erst NACH diesem Code aufgerufen. Daher wird Schließbar hier immer false sein, die Methode Close daher nicht aufgerufen.

Die ursprüngliche Variante ist m.E. nach zielführend. Das explizite Aufrufen von TForm.Close klappt immer. Da wird dann auch korrekt unterschieden, ob das Form nur geschlossen (nicht Main Form) oder das Programm beendet werden soll.

Für diesen Beitrag haben gedankt: Mathematiker
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1600
Erhaltene Danke: 232


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: Di 07.01.14 00:21 
Allzu qualifiziert kann ich zu dieser Diskussion leider nichts beisteuern, aber hier:

user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
Ich vermute, dass es mit FormCloseQuery nicht so wie erwartet will, hat vielleicht etwas mit meinem nicht gerade frischem Delphi 5 und der Tatsache, dass das 2.Fenster modal ist, zu tun.


wage ich leichte Entwarnung zu geben: Schon Delphi 1, spätestens Delphi 2 hatten (ziemlich) ausgereifte Ereignisbehandlungen. Da wurde doch n.m.W. nichts mehr "korrigiert", es kamen eher / höchstens weitere Dinge hinzu.

Wie schon geschrieben, mein Sortierkino ist auch im laufenden Betrieb - dank application.processmessages - abbrechnenbar, und das kann ich in einer Version schon ab Delphi 2.0 compilieren.


Zuletzt bearbeitet von Delphi-Laie am Di 07.01.14 00:26, insgesamt 1-mal bearbeitet

Für diesen Beitrag haben gedankt: Mathematiker
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1600
Erhaltene Danke: 232


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: Di 07.01.14 00:24 
user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
Während der Animation kann ich noch so oft auf den X-Button klicken. OnCloseQuery wird scheinbar nicht ausgelöst, denn das Programm springt einfach nicht in die Methode hinein; obwohl es funktionieren müsste.


Scheinbar oder tatsächlich?

Ich pflege mir immer mit einfachen Pieptönen in solchen Fällen zu helfen.

Wenn Du in OnClose und/oder OnCloseQuery einen Breakpoint setzt, wird dann ddas Program beim X-Druck an der Stelle unterbrochen oder nicht? Auch der Breakpoint kann von der IDE nicht ignoriert werden, wenn er angesprungen wird.
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Di 07.01.14 00:32 
Hallo,
user profile iconDelphi-Laie hat folgendes geschrieben Zum zitierten Posting springen:
Scheinbar oder tatsächlich? ... Wenn Du in OnClose und/oder OnCloseQuery einen Breakpoint setzt, wird dann ddas Program beim X-Druck an der Stelle unterbrochen oder nicht?

Tatsächlich!
Den Breakpoint habe ich gesetzt und nichts passiert.
Ich habe ein älteres Programm etwas verändert und hänge es einmal 'ran. Die Plasmadarstellung ist in einem modalen Fenster, so wie meine eigentliche Animation.
Startet man nach dem Zeichnen die Farbrotation hat der X-Button "keine Wirkung" mehr.

Ich danke allen für die Mühe und Hilfe und es eilt nicht.
Ich muss jetzt erst einmal ins Bett. Morgen früh 5.30 Uhr ist die Nacht leider vorbei.

Beste Grüße
Mathematiker
Einloggen, um Attachments anzusehen!
_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 07.01.14 12:17 
Was mir als Erstes auffällt:

Du arbeitest so gerne mit Konstanten, die in Wirklichkeit KEINE sind.
Ständig weist Du den "Konstanten" andere Werte zu!
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1600
Erhaltene Danke: 232


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: Di 07.01.14 13:37 
Das ist in der Tat merkwürdig.

Um das Problem zu vereinfachen (neudeutsch: "herunterzubrechen"), erstellte ich mal ein kleines Projekt, absichtlich mit Delphi 2. Es funktioniert so, wie es m.E. funktionieren sollte. Die beiden Pieptöne in aufsteigender Frequenz beim X-Druck sollen einfach das Durchlaufen von OnCloseQuery und OnClose (in dieser Reihenfolge) anzeigen.

Drei Sachen sind jedoch bemerkenswert:

1. Obwohl erst in OnCloseQuery (oder in OnClose, funktioniert auch dort) die Abbruchbedingung der Schleife "freigeschaltet" wird, die Schleife also mindestens noch einmal angesprungen und damit das Abbrechen unterbrochen wird, funktioniert dennoch auch das Schließen des (jeweiligen) Formulares oder gar das Beenden des Programmes. Das Schließen ist also ein wahrlich komplexer Prozeß, der unterbrech- und fortsetzbar ist, wobei OnClose(Query) jeweils nur einmal durchlaufen werden.

2. Das Hauptformular und damit das Programm können nicht beendet werden, wenn die Schleife im unter- bzw. zugeordneten Formular noch läuft. Eine laufende Schleife verhindert also das Programmende.

3. Wird nach 2. das untergeordnete Formular und mit ihm seine Schleife beendet, beendet sich das Programm ohne erneuten X-Druck auf das Hauptformular. Das Programm merkt sich demnach auf mysteriöse Weise, daß es schon einmal (erfolglos) zu beenden versucht wurde.

Derlei Tücken wie hier das Nichtanspringen der OnClose-Ereignisbehandlungsprozeduren sind mir in prinzipieller Form wohlbekannt. Es gibt für jemanden wie mich, der wenig Ahnung hat, zwei Möglichkeiten, der Ursache auf die Spur zu kommen (wobei ich die erstere wegen tendenziell geringerem Aufwand bevorzuge). Entweder das problembehaftete Programm soweit vereinfachen ("herunterbrechen"), daß es einen solch simplen Charakter bekommt wie meines (zwischendurch immer wieder die Löschschaktionen dokumentieren, um die Ursache einzukreisen) oder ein simples Programm immer mehr mit Leben erfüllen (hier sind ebenfalls die Dokumentation, was hinzugefügt wird, wichtig).

Postscriptum: Den Wert boolescher Variablen über den = -Operator abzufragen, ist unelegant. Statt =false besser if not ...
Einloggen, um Attachments anzusehen!

Für diesen Beitrag haben gedankt: Mathematiker
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 07.01.14 13:50 
Ich habe mal ein paar Änderungen gemacht:

- procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); // entfällt ! da ohne Wirkung
- Button Exit1 eingefügt

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
var
  Form1: TForm1;
  zeichnenaktiv:boolean;// = false;
  rotation:boolean;// = false;
  waagerecht:boolean;// = false;
  stopp : Boolean;

implementation

{$R *.DFM}
(*
const rotation:boolean = false;
      waagerecht:boolean = false;
      zeichnenaktiv:boolean = false;
      abbruch:boolean = true;             *)



procedure TForm1.FormCreate(Sender: TObject);
begin
      zeichnenaktiv:= false;
      rotation:= false;
      waagerecht:= false;
      stopp:=false;
end;

procedure TForm1.Exit1Click(Sender: TObject);
begin
  stopp:=true;
  Form1.Close;
end;

procedure TForm1.Button2Click(Sender: TObject);
var i,j:integer;
    k,index  : integer;
begin
   if not rotation then
   begin
      //Initialisierung für Farbrotation
      cyclestart:=0;
      cb1.enabled:=false;
      button2.caption:='Stop';
      rotation:=true;
///Rotationsschleife
   repeat
   if stopp=true then exit;  //th

     cyclestart:=cyclestart+1;
...

Für diesen Beitrag haben gedankt: Mathematiker
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Di 07.01.14 14:14 
Lass doch bitte das "Form1" im Exit1Click weg. Und Vergleiche auf true müssen nicht immer das richtige Ergebnis liefern, daher "=true" im Button2Click auch mit streichen.