====== 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.