Vega — Mehrere Fenster und modale Abläufe

Eine Anwendung ist nicht auf ein Fenster festgelegt. 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

Vega-Guides · Dialoge · Ereignisse


Weitere Fenster zur Laufzeit

Ein zweites Fenster ist eine gewöhnliche 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 TComponent; OwnerControl() liefert dasselbe schon als 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.