Inhaltsverzeichnis

Vega — Ziehen und Ablegen

Eine Ziehgeste läuft über vier Ereignisse, verteilt auf zwei Beteiligte: das Control, an dem sie beginnt (die Quelle), und das, über dem sie endet (das Ziel).

Ereignis Wer bekommt es Signatur Aufgabe
OnStartDrag Quelle fn(sender): void Merken, was gemeint ist
OnDragOver mögliches Ziel fn(sender, source, x, y): bool true = „ich nehme das an„
OnDragDrop Ziel fn(sender, source, x, y): void Übernehmen
OnEndDrag Quelle fn(sender, target, x, y): void Aufräumen; target ist 0 bei Abbruch

Vega-Guides · Ereignisse · Listen


Die Geste beginnt

DragMode entscheidet, wie:

Wert Bedeutung
DM_MANUAL (0, Vorgabe) Nur, wenn die Anwendung BeginDrag ruft
DM_AUTOMATIC (1) Von selbst, sobald der Zeiger mit gedrückter Taste weit genug wandert

Die Vorgabe ist bewusst manuell — wie in Delphi. Sonst zöge man beim Markieren in einem Eingabefeld versehentlich den Text heraus.


Die Geste trägt keine Nutzlast

Vega reicht bei OnDragDrop nur source und die Koordinaten weiter, keinen Gegenstand. Was unterwegs ist, merkt sich die Anwendung selbst — im einfachsten Fall in einer Modulvariablen, die OnStartDrag füllt und OnEndDrag wieder leert.

Das ist ehrlicher als eine typlose Nutzlast: Quelle und Ziel wissen ohnehin, worum es geht, und der Typ bleibt der der Anwendung.

OnDragOver liefert seine Antwort als Rückgabewert — in Delphi ist das ein var-Parameter. Ein Handler, der nichts zurückgibt, lehnt damit ab, statt eine Vorbelegung stehen zu lassen, die niemand gesetzt hat.


Beispiel

Zwei Listen, zwischen denen Einträge wandern:

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.ListCtrls;
import Vega.Backend;
import Vega.BackendAuto;
import Vega.Forms;

var g_app: TApplication;
var g_links: TListBox;
var g_rechts: TListBox;
var g_status: TLabel;

// Was gerade unterwegs ist. Die Geste selbst traegt keine Nutzlast —
// wer etwas mitgeben will, merkt es sich hier.
var g_unterwegs: TTextBuffer;

fn OnBeenden(sender: TControl): void { g_app.Terminate(); }

// 1. Beginn: merken, was gemeint ist
fn OnStart(sender: TControl): void {
  var lb: TListBox := sender as TListBox;
  if (lb.ItemIndex < 0) { return; }
  var t: pchar := lb.Items.Get(lb.ItemIndex);
  g_unterwegs.SetText(t);
  g_status.SetCaption(t);
}

// 2. Ueberfahren: nimmt DIESES Control den Gegenstand an?
fn OnOver(sender: TControl, source: TControl, x: int64, y: int64): bool {
  if (source == sender) { return false; }      // nicht auf sich selbst
  return g_unterwegs.Length > 0;
}

// 3. Ablegen: uebernehmen und beim Absender entfernen
fn OnDrop(sender: TControl, source: TControl, x: int64, y: int64): void {
  var ziel: TListBox := sender as TListBox;
  var von: TListBox := source as TListBox;
  if (g_unterwegs.Length == 0) { return; }
  var t: pchar := g_unterwegs.AsPChar();
  ziel.Add(t);
  if (von.ItemIndex >= 0) { von.Delete(von.ItemIndex); }
  g_status.SetCaption("verschoben");
  g_unterwegs.Clear();
}

// 4. Ende: target ist 0, wenn nirgends abgelegt wurde
fn OnEnd(sender: TControl, target: TControl, x: int64, y: int64): void {
  if (target == 0) { g_status.SetCaption("abgebrochen"); }
  g_unterwegs.Clear();
}

fn Verbinde(lb: TListBox): void {
  lb.DragMode := DM_AUTOMATIC;      // Geste beginnt von selbst
  lb.OnStartDrag := OnStart;
  lb.OnDragOver := OnOver;
  lb.OnDragDrop := OnDrop;
  lb.OnEndDrag := OnEnd;
}

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

  g_unterwegs := new TTextBuffer();
  var f: TForm := new TForm(480, 300, "Ziehen und Ablegen");

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

  g_links := new TListBox();
  g_links.SetBounds(16, 40, 200, 200);
  g_links.Add("Bass");
  g_links.Add("Snare");
  g_links.Add("Hihat");
  Verbinde(g_links);
  g_links.SetParent(f);

  g_rechts := new TListBox();
  g_rechts.SetBounds(256, 40, 200, 200);
  Verbinde(g_rechts);
  g_rechts.SetParent(f);

  var b: TButton := new TButton("Beenden");
  b.SetBounds(336, 252, 120, 28);
  b.OnClick := OnBeenden;
  b.SetParent(f);

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

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


Muster


Fallstricke

Letzte Aktualisierung: 2026-08-19 — Ereignisse und DragMode gegen Vega/Control.lyx und Vega/Types.lyx erhoben; Beispiel mit lyxc 1.1.3I übersetzt.