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