Vega — Menüs, Werkzeugleiste, Befehle, Hinweise

Derselbe Befehl steht in einer Anwendung meist an drei Stellen: im Menü, auf der Werkzeugleiste und hinter einem Tastenkürzel. Vega hat dafür TAction — den Befehl als eigenes Ding. Beschriftung, Kürzel, Hinweistext und der gesperrte Zustand stehen einmal dort und gelten überall, wo er verknüpft ist.

Vega-Guides · Komponenten · Ereignisse


var mm: TMainMenu := new TMainMenu();
var mDatei: TMenuItem := mm.Add("Datei");
mDatei.Add("Neu").OnClick := OnNeu;
mDatei.AddSeparator();
mDatei.Add("Beenden").OnClick := OnBeenden;
mDatei.Item(2).SetShortcut(113, MOD_CTRL);     // Strg+Q
f.SetMenu(mm);

Add liefert den neuen Eintrag zurück — daher die kurze Schreibweise. Untermenüs entstehen, indem man an einem Eintrag wieder Add ruft. Auf bestehende Einträge kommt man über Item(index); Checked und Enabled setzen den Zustand.

Die Menüleiste nimmt am Layout nicht teil: sie liegt auf 0/0 und wird zuletzt gezeichnet. Zwei Folgen — Platz darunter selbst freihalten (f.MenuHeight()) und im OnResize die Breite nachziehen (f.Menu.Width := f.Width).

Ein Kontextmenü ist ein TPopupMenu, zugewiesen über PopupMenuPtr.


Werkzeugleiste

var tb: TToolBar := new TToolBar();
tb.SetBounds(0, f.MenuHeight(), 520, 34);
tb.ButtonWidth := 120;
tb.SetParent(f);

var t1: TButton := new TButton("");
t1.Width := 0;              // 0 = die Leiste bestimmt die Breite
t1.SetParent(tb);
tb.ArrangeButtons();

TToolBar ordnet ihre Kinder selbst an: ButtonWidth, ButtonHeight, Spacing, Flat, ShowCaptions, Wrapable. Ein Knopf mit Width := 0 übernimmt die Vorgabebreite der Leiste; ein Knopf mit eigener Breite behält sie. ArrangeButtons() nach dem Befüllen.


Befehle (TAction)

g_al := new TActionList();
g_app.AddActionList(g_al);

var aSp: TAction := g_al.Add("Speichern");
aSp.SetHint("Schreibt die Datei");
aSp.SetShortcut(83, MOD_CTRL);          // Strg+S
aSp.OnExecute := TueSpeichern;          // fn(action: TAction): void
aSp.OnUpdate  := PruefeSpeichern;       // setzt action.Enabled

Verknüpft wird in beide Richtungen:

  • aSp.LinkMenuItem(mDatei.Add(„“)) — der Eintrag bekommt Beschriftung, Kürzel und Zustand vom Befehl; deshalb der leere Text.
  • aSp.LinkControl(knopf as TControl) — dasselbe für einen Knopf.

OnUpdate läuft, bevor die Oberfläche gezeigt wird. Dort steht eine Bedingung, und Menüeintrag wie Knopf werden gemeinsam gesperrt — statt an jeder Stelle dieselbe Prüfung zu wiederholen.

Ein TAction trägt außerdem Checked, Visible, ImageIndex und Tag.


Hinweise (Hints)

Jedes Control hat Hint und ShowHint. Gesetzt wird der Text mit SetHint(„…“); ShowHint := false schaltet ihn für einen Bereich ab — auch für dessen Kinder. Die Anzeige selbst übernimmt der THintController der Anwendung; ein Klick räumt den Hinweis sofort weg.

Ein TAction gibt seinen Hint an alles weiter, was mit ihm verknüpft ist.


Beispiel

Ein Befehl, drei Bedienwege — Menü, Leiste, Tastenkürzel — plus Kontextmenü und Hinweistext:

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.Layout;
import Vega.Menus;
import Vega.Actions;
import Vega.Backend;
import Vega.BackendAuto;
import Vega.Forms;

var g_app: TApplication;
var g_form: TForm;
var g_al: TActionList;
var g_status: TLabel;
var g_geaendert: bool;

// Ein Befehl fuehrt aus …
fn TueSpeichern(action: TAction): void {
  g_geaendert := false;
  g_status.SetCaption("gespeichert");
}

// … und sagt selbst, wann er verfuegbar ist. OnUpdate laeuft vor dem
// Anzeigen — Menueeintrag UND Knopf werden gemeinsam gesperrt.
fn PruefeSpeichern(action: TAction): void {
  action.Enabled := g_geaendert;
}

fn TueAendern(action: TAction): void {
  g_geaendert := true;
  g_status.SetCaption("geaendert");
}

fn TueBeenden(action: TAction): void {
  g_app.Terminate();
}

// Ein Menueeintrag ohne Befehl bekommt einen gewoehnlichen TNotifyEvent.
fn OnKontext(sender: TControl): void {
  g_status.SetCaption("aus dem Kontextmenue");
}

fn main(): int64 {
  g_app := new TApplication(NewPlatformBackend());
  if (!g_app.Ready) { PrintLn("Kein Fenstersystem erreichbar."); return 1; }

  g_form := new TForm(520, 240, "Menue, Leiste, Befehle");
  g_geaendert := false;

  g_al := new TActionList();
  g_app.AddActionList(g_al);

  var aSp: TAction := g_al.Add("Speichern");
  aSp.SetHint("Schreibt die Datei");
  aSp.SetShortcut(83, MOD_CTRL);            // Strg+S
  aSp.OnExecute := TueSpeichern;
  aSp.OnUpdate := PruefeSpeichern;

  var aAe: TAction := g_al.Add("Aendern");
  aAe.SetHint("Markiert das Dokument als geaendert");
  aAe.OnExecute := TueAendern;

  var aEn: TAction := g_al.Add("Beenden");
  aEn.SetShortcut(81, MOD_CTRL);            // Strg+Q
  aEn.OnExecute := TueBeenden;

  // Menue: der Eintrag bekommt Beschriftung, Kuerzel und Zustand vom Befehl
  var mm: TMainMenu := new TMainMenu();
  var mDatei: TMenuItem := mm.Add("Datei");
  aSp.LinkMenuItem(mDatei.Add(""));
  aAe.LinkMenuItem(mDatei.Add(""));
  mDatei.AddSeparator();
  aEn.LinkMenuItem(mDatei.Add(""));
  g_form.SetMenu(mm);

  // Werkzeugleiste: Width auf 0 heisst "die Leiste bestimmt die Breite"
  var tb: TToolBar := new TToolBar();
  tb.SetBounds(0, g_form.MenuHeight(), 520, 34);
  tb.ButtonWidth := 120;
  tb.SetParent(g_form);

  var t1: TButton := new TButton("");
  t1.Width := 0;
  t1.SetParent(tb);
  aSp.LinkControl(t1 as TControl);

  var t2: TButton := new TButton("");
  t2.Width := 0;
  t2.SetParent(tb);
  aAe.LinkControl(t2 as TControl);
  tb.ArrangeButtons();

  g_status := new TLabel("bereit");
  g_status.SetBounds(16, 100, 480, 18);
  g_status.SetHint("Zeigt, was zuletzt geschah");
  g_status.SetParent(g_form);

  // Kontextmenue am Fenster
  var pm: TPopupMenu := new TPopupMenu();
  pm.Add("Was war zuletzt?").OnClick := OnKontext;
  g_form.PopupMenuPtr := pm as int64;

  if (!g_app.ShowForm(g_form)) { return 2; }
  g_app.Run();
  g_app.Shutdown();
  return 0;
}

Übersetzen: lyxc befehle.lyx -I . -I platform/linux -o befehle. Nachgemessen mit lyxc 1.1.3I, übersetzt fehlerfrei.


Fallstricke

  • AddActionList vergessen. Ohne sie läuft kein OnUpdate und kein Kürzel.
  • Beschriftung doppelt gepflegt. Wer den Menüeintrag mit Text anlegt und einen Befehl verknüpft, hat zwei Wahrheiten. Mit Befehl: Add(„“).
  • ArrangeButtons() vergessen. Die Leiste bleibt leer aussehend, obwohl die Knöpfe da sind.
  • Platz unter der Menüleiste. Sie nimmt am Layout nicht teil; ohne eigenen Streifen liegt die erste Zeile darunter.

Letzte Aktualisierung: 2026-08-19 — API gegen Vega/Menus.lyx, Vega/Layout.lyx, Vega/Actions.lyx und Vega/Hints.lyx erhoben; Beispiel mit lyxc 1.1.3I übersetzt.