Vega — Ereignisse und ihre Handler

Ein Handler ist in Vega eine freie Funktion, deren Signatur zum Ereignistyp passt. Zugewiesen wird sie wie ein Wert: b.OnClick := OnKlick; — ohne Klammern, denn zugewiesen wird die Funktion, nicht ihr Ergebnis.

Ein nicht gesetzter Handler ist 0. Vega prüft das vor jedem Aufruf; ein Ereignis ohne Handler passiert einfach nicht.

Erste Anwendung · Eigenschaften · Komponenten


Die Handler-Typen

Typ Signatur Verwendet von
TNotifyEvent fn(sender: TControl): void OnClick, OnDblClick, OnMouseEnter, OnMouseLeave, OnResize, OnFocusIn, OnFocusOut, OnChange, OnSelect
TMouseEvent fn(sender: TControl, x: int64, y: int64, button: int64): void OnMouseDown, OnMouseUp, OnMouseMove, OnContextPopup
TKeyEvent fn(sender: TControl, key: int64, modifiers: int64): void OnKeyDown, OnKeyUp
TCharEvent fn(sender: TControl, cp: int64): void OnChar — das Zeichen (Unicode-Codepoint), nicht die Taste
TWheelEvent fn(sender: TControl, delta: int64): void OnMouseWheel+1 hoch, -1 runter
TPaintEvent fn(sender: TControl, canvas: TCanvas): void OnPaint
TDragOverEvent fn(sender, source: TControl, x, y: int64): bool OnDragOver — Rückgabe true heißt „ich nehme es an„
TDragDropEvent fn(sender, source: TControl, x, y: int64): void OnDragDrop
TDragEndEvent fn(sender, target: TControl, x, y: int64): void OnEndDragtarget ist 0, wenn nirgends abgelegt wurde
TTimerEvent fn(sender: TControl): void TTimer.OnTimer

Die Mauskoordinaten sind relativ zum Control, nicht zum Fenster.


Ereignisse des Formulars

Ereignis Wann
OnCreate Einmal, nachdem das Fenster steht
OnShow / OnHide Jedes Mal beim Erscheinen/Verschwinden
OnActivate / OnDeactivate Fenster bekommt/verliert den Fokus
OnClose Vor dem Schließen — setzt der Handler f.CancelClose := true, bleibt das Fenster offen („Wirklich beenden?“)
OnDestroy Beim Schließen, nach OnClose
OnResize Größenänderung — hier gehören ApplyLayout() verschachtelter Container und die Menübreite hinein

Für Tastenkürzel, die überall gelten sollen: f.KeyPreview := true und f.OnKeyDownForm — dann sieht das Formular die Taste vor dem fokussierten Element.


Beispiel

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_status: TLabel;
var g_feld: TEdit;

// TNotifyEvent: fn(sender: TControl): void
fn OnKlick(sender: TControl): void {
  g_status.SetCaption("Klick auf: ");
  var b: TButton := sender as TButton;
  g_status.SetCaption(StrConcat("Klick auf: ", b.Caption));
}

// TMouseEvent: fn(sender, x, y, button): void — Koordinaten sind
// relativ zum Control, nicht zum Fenster.
fn OnMaus(sender: TControl, x: int64, y: int64, button: int64): void {
  g_status.SetCaption(StrConcat(StrConcat("Maus ", IntToStr(x)), StrConcat("/", IntToStr(y))));
}

// TKeyEvent: fn(sender, key, modifiers): void
fn OnTaste(sender: TControl, key: int64, modifiers: int64): void {
  if (key == KEY_ESCAPE) { g_app.Terminate(); }
  if ((modifiers & MOD_CTRL) != 0 && key == KEY_RETURN) {
    g_status.SetCaption("Strg+Enter");
  }
}

// TNotifyEvent am Eingabefeld: der Sender ist das Feld selbst
fn OnAenderung(sender: TControl): void {
  var e: TEdit := sender as TEdit;
  g_status.SetCaption(e.GetText());
}

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

  var f: TForm := new TForm(400, 220, "Ereignisse");
  f.OnKeyDown := OnTaste;

  g_status := new TLabel("bereit");
  g_status.SetBounds(12, 12, 360, 18);
  g_status.SetParent(f);

  g_feld := new TEdit("tippen…");
  g_feld.SetBounds(12, 40, 240, 24);
  g_feld.OnChange := OnAenderung;
  g_feld.SetParent(f);

  var b: TButton := new TButton("Drueck mich");
  b.SetBounds(12, 80, 140, 28);
  b.OnClick := OnKlick;
  b.OnMouseMove := OnMaus;
  b.SetParent(f);

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

Nachgemessen mit lyxc 1.1.3I: übersetzt fehlerfrei (lyxc events.lyx -I . -I platform/linux -o events).


Der sender

Jeder Handler bekommt das auslösende Element als TControl. Wer mehr braucht, castet:

fn OnAenderung(sender: TControl): void {
    var e: TEdit := sender as TEdit;
    g_status.SetCaption(e.GetText());
}

Damit lässt sich ein Handler an mehrere Elemente hängen; sender.Tag oder sender.Name unterscheidet sie dann. Das spart die Sorte Code, die sich sonst zwanzigmal wiederholt.


Tasten und Modifikatoren

Sondertasten kommen als KEY_*-Konstanten aus Vega.Events: KEY_RETURN (13), KEY_ESCAPE (27), KEY_TAB (9), KEY_LEFT (256), KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_HOME, KEY_END, KEY_DELETE (127), KEY_BACKSPACE (8).

Modifikatoren sind eine Bitmaske: MOD_SHIFT (1), MOD_CTRL (2), MOD_ALT (4), MOD_SUPER (8):

if ((modifiers & MOD_CTRL) != 0 && key == KEY_RETURN) { … }

Für getippten Text ist OnChar der richtige Weg — OnKeyDown unterscheidet A und a nicht.


Fallstricke

  • Kein Methodenzeiger. Ein Handler ist eine freie Funktion; auf Elemente greift er über Modulvariablen zu.
  • Klammern weglassen. b.OnClick := OnKlick; — mit OnKlick() würde die Funktion aufgerufen und ihr Ergebnis zugewiesen.
  • Nach eigenen Zustandsänderungen Invalidate(). Der Handler bekommt kein automatisches Neuzeichnen.
  • OnMouseMove feuert oft. Dort nichts rechnen, was teuer ist; nur merken und im Paint verwenden.

Letzte Aktualisierung: 2026-08-19 — Handler-Typen gegen Vega/Control.lyx und Vega/Forms.lyx abgeglichen, Beispiel mit lyxc 1.1.3I übersetzt.