Form.OnShow sauber abbrechen

ch habe ein kleines Progämmchen geschrieben, das aus dem Programmcode heraus ein modales Fenster (VCL Formular) erzeugt, um bestimmte Inhalte in einem eigenen Fenster anzuzeigen. Der Fensterinhalt stammt aus einem ActiveX Control, das der Anwender vorher installiert haben muss.

Wenn der Anwender das Control nicht installiert hat, schmeißt Deplhi in der Laderoutine (Form.onShow), in der ich die Daten aus dem ActiveX Control lese, einen Runtime-Error beim Versuch, das ActiveX Control zu instantiieren. Ich habe den Fehler mit einem Try … Except Block abgefangen. Wenn die Exception gefangen und eine Messagebox auf das Problem hingewiesen hat, möchte ich das Laden des Fensters sauber beenden. Doku konnte ich dazu leider keine finden, verschiedene Versuche auf gut Glück, wie Aufrufen von Self.Destroy, führen leider zu einem Absturz mit Schutzverletzung und/oder zu einer Endlosschleife mit allerlei Anwendungsfehlern, und es ist nicht mehr möglich, dss Programm regulär zu beenden (Taskmanager und Prozessabschuss sind notwendig).

Derzeit breche ich notgedrungen die Applikation komplett ab (Halt; bzw. Application.Terminate:wink:, aber das führt zu einer weiteren Fehlermeldung wegen Schutzverletzung - immerhin bricht das Programm danach ab.

Wie kann ich OnLoad sauber abbrechen und zum aufrufenden Formular zurückkehren?

AL.

Wie kann ich OnLoad sauber abbrechen und zum aufrufenden
Formular zurückkehren?

Das Erstellen eines Formulars innerhalb von OnLoad abzubrechen ist keine gute Idee (und funktioniert wahrscheinlich auch nicht).
Du solltest folgendermaßen vorgehen:

  1. Formular erstellen: Form1:=TForm1.Create(NIL);
  2. Daten anzeigen: Form1.Edit1.Text:=‚BlaBla‘;
  3. Wenn dabei ein Fehler auftritt, dann das Formular wieder löschen: Form1.Release;
  4. Wenn alles OK ist dann das Formular anzeigen: Form1.ShowModal;

Das Formular wird als nur angezeigt, wenn die Daten verfügbar sind.

Viel Erfolg
Joachim

Hi Nimral,

du kannst in dem exceptionblock PostQuitMessage(0); benutzen. Das beendet den aktiven Thread, also in deinem Fall die Hauptanwendung, ohne das es zu einer Schutzverletzung kommen sollte.

Gruß Mike

Hallo,

ich würde ganz anders vorgehen:

Schreib in dem modalen Fenster eine öffentliche Methode, die das ActiveX initialisiert und true oder false zurückgibt, je nachdem ob die Initialisierung geklappt hat (oder einen ordinalen Typ der weitergehende Infos zur Initialisierung codiert, zB Fehlercodes).

Aus dem Hauptformular rufst Du dann zunächst die Initialisierung auf und bei Erfolg zeigst Du das Fenster an.

begin
 if frmModal.InitAX then begin
 case frmModal.ShowModal of
 mrOK : ShowMessage('Dialog mit OK beendet');
 mrCancel: ShowMessage('Dialog wurde abgebrochen');
 end;
 end
 else begin
 ShowMessage('Kann ActiveX nicht initialisieren');
 end;

Das wäre für mich eine saubere Implementierung. Du könntest auch ganz auf einen Rückgabewert verzuchten und statt dessen im Hauptformular die Exception abfangen.

Gruß, Niels

Hab mich noch gar nicht bedankt für den Tipp. Von allen Vorschlägen war das derjenige, der das Programm ohne Schutzverletzung beendet hat, leider aber „nur“ das Gesamtprogramm. Damit war ich für den Moment mal zufrieden. Jetzt möchte ich das Problem nochmal angehen.

Da es offenbar nicht möglich ist, Form.onShow sauber zu terminieren, kann ich natürlich ein Flag setzen, dann das Form zeigen, und es dann möglichst schnell wieder beenden.

Wo könnte ich entsprechenden Code einhängen?

AL.

Hallo,

ich verstehe jetzt das Problem nicht ganz.

Hab mich noch gar nicht bedankt für den Tipp. Von allen
Vorschlägen war das derjenige, der das Programm ohne
Schutzverletzung beendet hat, leider aber „nur“ das
Gesamtprogramm. Damit war ich für den Moment mal zufrieden.

Eine Beendigung der Anwendung ist in meinem Code ja nicht enthalten.
Der Code steht im aufrufenden Fenster. Wenn die Initialisierung des ActiveX nicht funktioniert, hat das keinen Einfluss auf das aufrufende Fenster.
ich denke, Du solltest nochmal den Ablauf schildern:
Welchen Zustand hat überhaupt das aufrufende Fenster? Ist es bereits sichtbar oder nicht? Welches Ereignis im aufrufenden Fenster soll denn das andere (modale) Fenster aufrufen? etc.

Da es offenbar nicht möglich ist, Form.onShow sauber zu
terminieren,

zu welchem Formular (aufrufend oder aufgerufen) gehört das zu terminierende OnShow-Ereignis und was soll darin ablaufen?

kann ich natürlich ein Flag setzen, dann das Form
zeigen, und es dann möglichst schnell wieder beenden.

Solche Dinge kann man über Timer steuern. Das halte ich aber nicht für eine saubere Lösung.

Gruß, Niels

Hallo,

ich verstehe jetzt das Problem nicht ganz.

Ok, ich muss genauer werden.

Das Programm hat ein Hauptfenster, nennen wird es mal „MainForm“, in dem ein Treeview eine Liste von inhalten anzeigt. Sobald der Anwender auf ein Element des Treeviews klickt, geht ein neues Fenster auf (erzeugt per Programmcode, nennen wir es mal „Player“), in dem ein Inhalt (Flash-Film) angezeigt wird. Die Inhaltsanzeige macht das (importierte) Shockwave Flash ActiveX Control.

Wenn Flash nicht installiert wurde, läuft die onLoad (ich habe auch onShow probiert - selbes Resultat) Routine von Player in einen Fehler. Ich habe ihn mit try … except gefangen, und eine Messagebox angezeigt. Nun muss noch der Ladevorgang für das „Player“ Fenster irgendwie abgebrochen und zum Fenster mit dem Treeview zurückgekehrt werden. Das ist irgendwie ein prinzipielles Problem: wie beendet man das Laden eines Dialogfensters, wenn die Initialisierung bei onLoad in einen schwerwiegenden Fehler läuft.

Das Problem ist, dass man nach dem Laden des Fensters erst mal keine Kontrolle mehr hat, bis der Anwender endlich irgendein Control auslöst. Profan gesprochen müsste ich einen Einhängpunkt haben, in dem sich die Messageloop des Fensters herumtreibt, wenn es nichts zu tun gibt. onIdle würde ich sie nennen :smile: und darin dann einen Befehl, der die normale Fensterschließroutine onClose auslöst. Dein Hinweis mit dem Timer zeigt auch in diese Richtung, mir ist diese Möglichkeit auch eingefallen, aber wie bei Dir sträube sich mir da erst mal die Haare, das ist nicht sonderlich elegant.

Der unbedingte Abbruch des Mainforms, den der PostMessage(0) Aufruf bei mir auslöst, ist nur die zweitbeste Lösung. Ich hatte gehoft, er killt das „Player“ Fenster, das tut er auch, aber er killt das „Mainform“ Fenster gleich mit.

Immerhin tut er das ohne Schutzverletzung.

Ich hoffe, ich war jetzt ein wenig klarer?

AL.

Hallo,

Urlaub ist vorbei, jetzt die Lösung:

Im OnPaint-Ereignis schreibst Du ModalResult := XX; mit XX0.

Gruß, Niels