====== Vega — Dialoge und Dateiauswahl ======
Dialoge sind in Vega gewöhnliche [[lyx_-_programmiersprache:vega:controls:tform|TForm]]-Fenster mit ein paar Controls darin — kein Sonderweg. Was sie besonders macht, ist allein, dass sie über ''ShowModal'' gezeigt werden: Der Aufruf kehrt erst zurück, wenn ein Ergebnis feststeht.
Jeder Dialog braucht die [[lyx_-_programmiersprache:vega:controls:tapplication|TApplication]] als erstes Argument. Wer Dialoge aus einer eigenen Unit ruft, muss ihr die Anwendung bekannt machen — sonst steigt der Aufruf **still** wieder aus.
→ [[lyx_-_programmiersprache:vega:guides|Vega-Guides]] · [[lyx_-_programmiersprache:vega:guides:komponenten|Komponenten]] · [[lyx_-_programmiersprache:vega:guides:events|Ereignisse]]
----
===== Die fertigen Dialoge =====
^ Aufruf ^ Rückgabe ^ Zweck ^
| ''ShowMessage(app, text)'' | – | Hinweis mit einem OK-Knopf |
| ''ShowMessageTitled(app, titel, text)'' | – | dasselbe mit eigenem Fenstertitel |
| ''MessageDlg(app, text, buttons)'' | ''mr*'' | Frage mit wählbaren Knöpfen |
| ''MessageDlgTitled(app, titel, text, buttons)'' | ''mr*'' | dasselbe mit Titel |
| ''ConfirmDlg(app, text)'' | ''bool'' | Ja/Nein als Wahrheitswert |
| ''InputBox(app, titel, frage, vorgabe, puffer)'' | ''bool'' | Texteingabe; das Ergebnis landet im **Puffer** |
Knöpfe (''TMsgButtons''): ''MB_OK'' (0), ''MB_OK_CANCEL'' (1), ''MB_YES_NO'' (2), ''MB_YES_NO_CANCEL'' (3).
Ergebnisse: ''mrNone'' (0, „läuft noch"), ''mrOk'' (1), ''mrCancel'' (2), ''mrYes'' (3), ''mrNo'' (4).
**''InputBox'' gibt keine Zeichenkette zurück**, sondern schreibt in einen [[lyx_-_programmiersprache:vega:controls:ttextbuffer|TTextBuffer]], den der Aufrufer stellt und wieder freigibt — eine zurückgegebene Zeichenkette wäre Speicher, den niemand mehr aufräumt. Gelesen wird mit ''AsPChar()''.
----
===== Datei-, Farb- und Schriftauswahl =====
var dlg: TOpenDialog := NewOpenDialog(); // NewSaveDialog(), NewSelectDirectoryDialog()
dlg.SetFilter("*.lyx");
if (dlg.Execute(g_app)) {
var name: pchar := dlg.FileName.AsPChar();
}
* ''TOpenDialog'', ''TSaveDialog'' und ''TSelectDirectoryDialog'' erben von ''TFileDialog'' und tragen ''InitialDir'', ''FileName'' und ''Filter'' — alle drei als ''TTextBuffer''.
* ''Execute(app)'' liefert ''true'', wenn bestätigt wurde.
* Farbe: ''ChooseColor(app, startfarbe): TColor'' aus ''Vega.ColorDlg''.
* Schrift: ''ChooseFont(app, startpfad, startgroesse): bool'' aus ''Vega.FontDlg''.
----
===== Beispiel =====
Alle sechs Dialogarten an je einem Knopf:
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.dialogs;
import vega.filedlg;
import vega.colordlg;
import vega.backend;
import vega.backendauto;
import vega.forms;
var g_app: TApplication;
var g_status: TLabel;
fn OnHinweis(sender: TControl): void {
ShowMessage(g_app, "Gespeichert.");
}
fn OnFrage(sender: TControl): void {
// MessageDlg liefert mrOk / mrCancel / mrYes / mrNo
var r: int64 := MessageDlg(g_app, "Aenderungen verwerfen?", MB_YES_NO);
if (r == mrYes) { g_status.SetCaption("verworfen"); }
else { g_status.SetCaption("behalten"); }
}
fn OnEingabe(sender: TControl): void {
// Das Ergebnis kommt ueber einen eigenen Puffer, nicht als Rueckgabewert
var puffer: TTextBuffer := new TTextBuffer();
if (InputBox(g_app, "Name", "Wie heisst das Stueck?", "ohne Titel", puffer)) {
var t: pchar := puffer.AsPChar();
g_status.SetCaption(t);
} else {
g_status.SetCaption("abgebrochen");
}
puffer.Destroy();
}
fn OnOeffnen(sender: TControl): void {
var dlg: TOpenDialog := NewOpenDialog();
dlg.SetFilter("*.lyx");
if (dlg.Execute(g_app)) {
var name: pchar := dlg.FileName.AsPChar();
g_status.SetCaption(name);
} else {
g_status.SetCaption("keine Datei gewaehlt");
}
}
fn OnFarbe(sender: TControl): void {
var c: TColor := ChooseColor(g_app, RGB(70, 130, 180));
g_status.SetCaption("Farbe gewaehlt");
}
fn OnBeenden(sender: TControl): void {
if (ConfirmDlg(g_app, "Wirklich beenden?")) { g_app.Terminate(); }
}
fn main(): int64 {
g_app := new TApplication(NewPlatformBackend());
if (!g_app.Ready) { PrintLn("Kein Fenstersystem erreichbar."); return 1; }
var f: TForm := new TForm(380, 260, "Dialoge");
g_status := new TLabel("bereit");
g_status.SetBounds(16, 16, 340, 18);
g_status.SetParent(f);
var b1: TButton := new TButton("Hinweis");
b1.SetBounds(16, 48, 160, 28);
b1.OnClick := OnHinweis;
b1.SetParent(f);
var b2: TButton := new TButton("Ja/Nein");
b2.SetBounds(196, 48, 160, 28);
b2.OnClick := OnFrage;
b2.SetParent(f);
var b3: TButton := new TButton("Eingabe");
b3.SetBounds(16, 88, 160, 28);
b3.OnClick := OnEingabe;
b3.SetParent(f);
var b4: TButton := new TButton("Datei oeffnen");
b4.SetBounds(196, 88, 160, 28);
b4.OnClick := OnOeffnen;
b4.SetParent(f);
var b5: TButton := new TButton("Farbe waehlen");
b5.SetBounds(16, 128, 160, 28);
b5.OnClick := OnFarbe;
b5.SetParent(f);
var b6: TButton := new TButton("Beenden");
b6.SetBounds(196, 128, 160, 28);
b6.OnClick := OnBeenden;
b6.SetParent(f);
if (!g_app.ShowForm(f)) { return 2; }
g_app.Run();
g_app.Shutdown();
return 0;
}
Übersetzen: ''lyxc dialoge.lyx -I . -I platform/linux -o dialoge''. Nachgemessen mit ''lyxc 1.1.3I'', übersetzt fehlerfrei.
----
===== Eigene modale Fenster =====
Ein eigener Dialog ist eine ''TForm'', die mit ''ShowModal'' statt ''ShowForm'' gezeigt wird. Das Ergebnis setzt ein Knopf-Handler über ''ModalResult'':
* ''dlg.Position := POS_MAIN_CENTER;'' setzt ihn mittig über das Hauptfenster.
* Solange ''ModalResult'' ''mrNone'' ist, läuft die modale Schleife weiter.
* Zum Schließen genügt ''dlg.ModalResult := mrOk;'' im Handler.
----
===== Suchen und Ersetzen: die nicht-modalen Dialoge =====
[[lyx_-_programmiersprache:vega:controls:tfinddialog|TFindDialog]] und [[lyx_-_programmiersprache:vega:controls:treplacedialog|TReplaceDialog]] (''Vega.FindDlg'') fallen aus der Reihe: sie laufen **nicht modal**. Der Grund liegt in ihrem Zweck — während das Fenster offen steht, soll man im Text weiterarbeiten und immer wieder „Weitersuchen“ drücken.
fn AufSuchen(sender: TFindDialog): void {
// Der Dialog kennt weder Text noch Editor — hier wird gesucht.
var was: pchar := sender.FindText.AsPChar();
var abwaerts: bool := sender.HasOption(frDown);
var gross: bool := sender.HasOption(frMatchCase);
}
var d: TFindDialog := new TFindDialog();
d.SetFindText("Bello");
d.SetOption(frMatchCase, true);
d.OnFind := AufSuchen;
d.Execute(app); // zeigt das Fenster und kehrt SOFORT zurück
^ Unterschied ^ Modale Dialoge ^ Suchen/Ersetzen ^
| Aufruf | ''ShowModal'' kehrt mit dem Ergebnis zurück | ''Execute'' kehrt sofort zurück |
| Ergebnis | Rückgabewert (''mrOk'' …) | Ereignisse ''OnFind'', ''OnReplace'', ''OnClose'' |
| Zweiter Aufruf | Neuer Durchlauf | Holt das offene Fenster nach vorn |
Optionen sind eine Bitmaske: ''frDown'' (1), ''frMatchCase'' (2), ''frWholeWord'' (4), ''frReplaceAll'' (8). „Ersetzen“ und „Alle ersetzen“ feuern **dasselbe** ''OnReplace'' — unterschieden wird allein über ''frReplaceAll''.
----
===== Fallstricke =====
* **Die Anwendung fehlt.** Dialoge in einer eigenen Unit brauchen eine gesetzte ''TApplication'' — ohne sie passiert nichts, ohne Meldung.
* **''InputBox''-Puffer nicht freigegeben.** ''new TTextBuffer()'' gehört ein ''Destroy()''.
* **Rückgabe von ''MessageDlg'' als ''bool'' gelesen.** Sie ist ein ''mr*''-Wert; ''mrOk'' ist 1, ''mrCancel'' 2 — beide sind „wahr".
* **''Execute'' eines Suchdialogs wie ''ShowModal'' behandelt.** Es kehrt sofort zurück; wer danach ein Ergebnis abfragt, liest den Stand von vorher. Die Arbeit gehört in ''OnFind''/''OnReplace''.
* **Beenden ohne Rückfrage.** ''OnClose'' mit ''CancelClose := true'' ist der Weg, das Schließen abzubrechen.
Letzte Aktualisierung: 2026-08-20 — Dialog-API gegen ''Vega/Dialogs.lyx'', ''Vega/FileDlg.lyx'', ''Vega/ColorDlg.lyx'' und ''Vega/FontDlg.lyx'' erhoben; Beispiel mit ''lyxc 1.1.3I'' übersetzt. Der Abschnitt zu ''Vega/FindDlg.lyx'' am 2026-08-20 mit ''lyxc 1.1.4B'' nachgemessen.
Codebeispiele geprüft: gegen **lyxc 1.2.5C** übersetzt (Prüflauf 2026-09-08 über die gesamte Doku: 574 Vollprogramme, 0 echte Fehler; zusätzlich 5159 Aufrufe gegen die ''pub fn''-Signaturen in ''aurum/std'' gehalten, 0 Abweichungen).