Die Seite beschreibt die Muster, nach denen eine größere Vega-Anwendung entsteht — Layout, eigene Steuerelemente, Zeitgeber, Dialoge. Sie ergänzt Steuerelemente (was es gibt) um die Frage, wie man es zusammensetzt.
→ Vega VCL · Architektur · Lyx-Eigenheiten
ApplyLayout arbeitet die Kinder der Reihe nach ab; jedes ausgerichtete Kind nimmt sich seinen Rand vom Rest. Alle Ränder (AL_TOP, AL_BOTTOM, AL_LEFT) müssen deshalb vor dem AL_CLIENT-Kind angelegt werden — sonst bekommt der Rand nichts mehr ab.ApplyLayout wirkt nur eine Ebene tief. Es setzt Left/Top/Width/Height der Kinder direkt, nicht über SetBounds — ein verschachtelter Container erfährt davon nichts. Wer Container in Containern hat, ruft deren ApplyLayout im OnResize des Fensters selbst nach.ShowForm folgt ein ApplyLayout, damit schon das erste Bild stimmt und nicht erst das nach der ersten Größenänderung.Vega.BackendAuto liegt je einmal unter platform/linux und platform/win64; extern-Deklarationen binden hart, auch ungenutzt. Deshalb entscheidet der Übersetzungsaufruf, nicht der Quelltext.Dispatcher.SetFocus laufen Tastendrücke ins Leere, bis jemand hineinklickt.
Das folgende Programm zeigt alle Bausteine auf engstem Raum: eigenes Steuerelement mit Paint, Randleiste plus AL_CLIENT, Knopf mit Handler und ein Zeitgeber, der die Anzeige fortschreibt.
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.Backend;
import Vega.BackendAuto;
import Vega.Forms;
// Modulvariablen stehen ALLE oben — eine Variable, die erst nach ihrer
// ersten Verwendung deklariert wird, zerfiel bis lyxc 1.1.3D still in zwei.
var g_app: TApplication;
var g_form: TForm;
var g_anzeige: TAnzeige;
var g_zaehler: int64;
var g_timer: TTimer;
// Eigenes Steuerelement: von TControl ableiten und Paint ueberschreiben.
pub type TAnzeige = class extends TControl {
Wert: int64;
fn Create(): void {
self.Init();
self.Wert := 0;
self.Height := 40;
}
override fn Paint(canvas: TCanvas): void {
var r: TRect := self.ClientRect();
canvas.FillRect(r, RGB(240, 240, 240));
var f: TFont := DefaultFont();
f.DrawText(canvas, 8, 10, IntToStr(self.Wert), RGB(0, 0, 0));
}
}
fn OnTick(sender: TTimer): void {
g_zaehler := g_zaehler + 1;
g_anzeige.Wert := g_zaehler;
g_anzeige.Invalidate();
}
fn OnEnde(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_form := NewForm(320, 200, "Praxis");
// Reihenfolge IST das Layout: Raender zuerst, AL_CLIENT zuletzt.
var leiste: TControl := new TControl();
leiste.Height := 32;
leiste.Align := AL_BOTTOM;
g_form.AddChild(leiste);
var b: TButton := new TButton("Schliessen");
b.SetBounds(8, 4, 120, 24);
b.OnClick := OnEnde;
leiste.AddChild(b);
g_anzeige := new TAnzeige();
g_anzeige.Align := AL_CLIENT;
g_form.AddChild(g_anzeige);
if (!g_app.ShowForm(g_form)) { return 2; }
g_form.ApplyLayout();
g_timer := NewTimer(500);
g_timer.OnTimer := OnTick;
g_timer.Start();
g_app.AddTimer(g_timer);
g_app.Run();
g_app.Shutdown();
return 0;
}
Übersetzen aus der Wurzel des lyx-vcl-Repositorys:
lyxc praxis.lyx -I . -I platform/linux -o praxis
Nachgemessen mit lyxc 1.1.3I: übersetzt fehlerfrei, rund 770 KB.
Ein eigenes Element leitet von TControl ab, ruft im Konstruktor self.Init() und überschreibt Paint:
self.ClientRect() liefert die Fläche ohne Rahmen.TCanvas (FillRect) und TFont (DrawText, TextWidth, TextHeight).self.Hovered und self.Pressed stehen für Zustandsdarstellung bereit.self.CanFocus entscheidet, ob das Element Tastatureingaben bekommt.Invalidate() rufen — Vega zeichnet nicht von selbst neu.Für Elemente, deren Inhalt an Zeichenpositionen ausgerichtet sein soll (Tabellen, Editoren), ist eine selbst gezeichnete Fläche der ruhigere Weg als ein Container voller Labels: Pixelabstände wandern bei jeder Textänderung, Zeichenpositionen nicht.
g_timer := NewTimer(20); // Millisekunden
g_timer.OnTimer := OnTick;
g_timer.Start();
g_app.AddTimer(g_timer); // ohne AddTimer feuert er nie
Ein Zeitgeber läuft durch; ob sein Handler etwas tut, entscheidet der Handler. Das ist einfacher zu überblicken als ein Timer, der ständig an- und abgemeldet wird.
ShowModal braucht die Anwendung. Wer Dialoge in einer eigenen Unit hält, muss ihr die TApplication bekannt machen — sonst steigt jede Dialogaktion still wieder aus:
g_app := app; // vor dem ersten Dialogaufruf
Die Menüleiste liegt als Kind auf 0/0 und nimmt am Layout nicht teil. Zwei Folgen:
f.MenuHeight() als erstes Kind verhindert, dass sich die erste Zeile darunterlegt.SetMenu setzt die Breite einmalig aus der damaligen Fensterbreite; im OnResize gehört f.Menu.Width := f.Width nachgezogen.
Letzte Aktualisierung: 2026-08-19 — Seite neu geschrieben; Muster aus einer bestehenden Vega-Anwendung abgeleitet, Beispielprogramm mit lyxc 1.1.3I übersetzt.