====== Vega — Mehrere Fenster und modale Abläufe ====== Eine Anwendung ist nicht auf ein Fenster festgelegt. [[lyx_-_programmiersprache:vega:controls:tapplication|TApplication]] verwaltet beliebig viele; das **erste** gezeigte wird zum Hauptfenster (''IsMainForm''), und dessen Ende beendet üblicherweise das Programm. Zwei Wege, ein Fenster zu zeigen: ^ Aufruf ^ Verhalten ^ | ''app.ShowForm(f)'' | Fenster geht auf, der Aufruf kehrt **sofort** zurück; alle Fenster bleiben bedienbar | | ''app.ShowModal(f)'' | Der Aufruf kehrt erst zurück, wenn ''f.ModalResult'' gesetzt ist; er liefert diesen Wert | → [[lyx_-_programmiersprache:vega:guides|Vega-Guides]] · [[lyx_-_programmiersprache:vega:guides:dialoge|Dialoge]] · [[lyx_-_programmiersprache:vega:guides:events|Ereignisse]] ---- ===== Weitere Fenster zur Laufzeit ===== Ein zweites Fenster ist eine gewöhnliche [[lyx_-_programmiersprache:vega:controls:tform|TForm]], die im Handler entsteht — kein Sonderweg: var w: TForm := new TForm(260, 140, "Fenster 2"); … g_app.ShowForm(w); Vom Control zurück zu seinem Fenster führt ''Owner'' (seit dem Komponenten-Split ein [[lyx_-_programmiersprache:vega:controls:tcomponent|TComponent]]; ''OwnerControl()'' liefert dasselbe schon als [[lyx_-_programmiersprache:vega:controls:tcontrol|TControl]]): fn OnNebenSchliessen(sender: TControl): void { var f: TForm := sender.Owner as TForm; f.Close(); } Damit kommt **ein** Handler mit beliebig vielen gleichartigen Fenstern aus — statt für jedes eine eigene Modulvariable zu führen. ''Close()'' liefert ''false'', wenn ein ''OnClose''-Handler mit ''CancelClose := true'' abgebrochen hat. Das eigentliche Zerstören übernimmt ''TApplication''. ---- ===== Eigene modale Dialoge ===== Ein modaler Dialog ist eine ''TForm'', die über ''ShowModal'' gezeigt wird. Beendet wird er, indem ein Handler ''ModalResult'' setzt: fn OnDlgOk(sender: TControl): void { g_dlg.ModalResult := mrOk; } … var r: int64 := g_app.ShowModal(g_dlg); if (r == mrOk) { … } * Solange ''ModalResult'' ''mrNone'' (0) ist, läuft die modale Schleife. * Schließt der Benutzer das Fenster über den Fensterrahmen, wird ''mrCancel'' daraus. * ''Position := POS_MAIN_CENTER'' setzt den Dialog mittig über das Hauptfenster. * Dialoge dürfen sich gegenseitig öffnen — eine Rückfrage aus einem Dialog heraus ist zulässig, das vorige modale Fenster wird danach wieder eingetragen. ---- ===== Beispiel ===== Hauptfenster, beliebig viele Nebenfenster, ein eigener modaler Dialog mit Rückgabewert: unit Main; import std.io; import Vega.Types; import Vega.Events; import Vega.Canvas; import Vega.Theme; import Vega.Control; import Vega.Font; import Vega.Strings; import Vega.Lists; import Vega.Style; import Vega.StdCtrls; import Vega.Edits; import Vega.Backend; import Vega.BackendAuto; import Vega.Forms; var g_app: TApplication; var g_haupt: TForm; var g_stand: TLabel; var g_zahl: int64; // --- Ein weiteres, nicht-modales Fenster ------------------------------------ fn OnNebenSchliessen(sender: TControl): void { // Owner ist der Weg vom Control zurueck zu seinem Fenster var f: TForm := sender.Owner as TForm; f.Close(); } fn OnNeuesFenster(sender: TControl): void { g_zahl := g_zahl + 1; var w: TForm := new TForm(260, 140, StrConcat("Fenster ", IntToStr(g_zahl))); var l: TLabel := new TLabel("Ein zweites Fenster."); l.SetBounds(16, 16, 220, 18); l.SetParent(w); var b: TButton := new TButton("Schliessen"); b.SetBounds(16, 60, 120, 28); b.OnClick := OnNebenSchliessen; b.SetParent(w); // ShowForm, nicht ShowModal: das Hauptfenster bleibt bedienbar g_app.ShowForm(w); } // --- Ein eigener modaler Dialog --------------------------------------------- var g_dlgFeld: TEdit; var g_dlg: TForm; fn OnDlgOk(sender: TControl): void { g_dlg.ModalResult := mrOk; } fn OnDlgAbbruch(sender: TControl): void { g_dlg.ModalResult := mrCancel; } fn OnFrage(sender: TControl): void { g_dlg := new TForm(300, 150, "Name eingeben"); g_dlg.Position := POS_MAIN_CENTER; var l: TLabel := new TLabel("Wie soll es heissen?"); l.SetBounds(16, 16, 260, 18); l.SetParent(g_dlg); g_dlgFeld := new TEdit("ohne Titel"); g_dlgFeld.SetBounds(16, 44, 260, 26); g_dlgFeld.SetParent(g_dlg); var ok: TButton := new TButton("OK"); ok.SetBounds(96, 90, 84, 28); ok.OnClick := OnDlgOk; ok.SetParent(g_dlg); var ab: TButton := new TButton("Abbruch"); ab.SetBounds(192, 90, 84, 28); ab.OnClick := OnDlgAbbruch; ab.SetParent(g_dlg); // ShowModal kehrt erst zurueck, wenn ModalResult gesetzt ist var r: int64 := g_app.ShowModal(g_dlg); if (r == mrOk) { var t: pchar := g_dlgFeld.GetText(); g_stand.SetCaption(t); } else { g_stand.SetCaption("abgebrochen"); } } // --- Hauptfenster ----------------------------------------------------------- fn OnHauptSchliessen(sender: TControl): void { g_app.Terminate(); } fn main(): int64 { g_app := new TApplication(NewPlatformBackend()); if (!g_app.Ready) { PrintLn("Kein Fenstersystem erreichbar."); return 1; } g_zahl := 0; g_haupt := new TForm(360, 200, "Hauptfenster"); g_stand := new TLabel("bereit"); g_stand.SetBounds(16, 16, 320, 18); g_stand.SetParent(g_haupt); var b1: TButton := new TButton("Neues Fenster"); b1.SetBounds(16, 56, 150, 28); b1.OnClick := OnNeuesFenster; b1.SetParent(g_haupt); var b2: TButton := new TButton("Modaler Dialog"); b2.SetBounds(180, 56, 150, 28); b2.OnClick := OnFrage; b2.SetParent(g_haupt); var b3: TButton := new TButton("Beenden"); b3.SetBounds(180, 104, 150, 28); b3.OnClick := OnHauptSchliessen; b3.SetParent(g_haupt); // Das ERSTE gezeigte Fenster wird zum Hauptfenster if (!g_app.ShowForm(g_haupt)) { return 2; } g_app.Run(); g_app.Shutdown(); return 0; } Übersetzen: ''lyxc fenster.lyx -I . -I platform/linux -o fenster''. Nachgemessen mit ''lyxc 1.1.3I'', übersetzt fehlerfrei. ---- ===== Wann modal, wann nicht ===== ^ Fall ^ Weg ^ | Rückfrage, deren Antwort der Ablauf sofort braucht | ''ShowModal'' | | Eigenschaften eines Objekts bearbeiten, Ergebnis übernehmen oder verwerfen | ''ShowModal'' | | Zweites Dokument, Werkzeugpalette, Protokollfenster | ''ShowForm'' | | Fortschrittsanzeige, die den Ablauf nicht anhalten soll | ''ShowForm'' | Modale Fenster halten den aufrufenden Zweig an — was in einem Handler passiert, blockiert bis zur Antwort. Für lange Arbeiten ist das der falsche Weg; dort gehört ein nicht-modales Fenster plus Zeitgeber hin. ---- ===== Fallstricke ===== * **''ModalResult'' nie gesetzt.** Der Dialog lässt sich nur noch über den Fensterrahmen schließen; die modale Schleife läuft bis dahin weiter. * **Das Hauptfenster ist das erste gezeigte.** Wer versehentlich einen Dialog zuerst zeigt, macht ihn zum Hauptfenster — mit dessen Ende endet die Anwendung. * **Fenster als lokale Variable.** Die ''TForm'' muss so lange leben, wie sie sichtbar ist; im Handler angelegte Fenster gehören der Anwendung, nicht dem Handler-Rahmen. * **''Terminate()'' statt ''Close()''.** ''Terminate'' beendet die ganze Anwendung, ''Close'' nur das eine Fenster. Letzte Aktualisierung: 2026-08-19 — Verhalten von ''ShowForm''/''ShowModal''/''Close'' gegen ''Vega/Forms.lyx'' erhoben; Beispiel mit ''lyxc 1.1.3I'' übersetzt.