Home » Tutorials » VCL » Drag’n’Drop in Delphi

Drag’n’Drop in Delphi

Ein erstes Beispiel

In diesem Beispiel lernen wir, wie Drag’n’Drop grundlegend abläuft und wie man Drag’n’Drop innerhalb der eigenen Anwendung in Delphi umsetzt. Zur Demonstration werden wir den Inhalt eines Editierfeldes in ein Bezeichnungsfeld legen.
Zu allererst platzieren wir eine TEdit- und eine TLabel-Komponente auf dem Formular.

Code

Um einen vollständigen Drag’n’Drop-Vorgang zu programmieren, müssen wir vier Eventhandler besetzen. Diese vier Eventhandler entsprechen den vier Abschnitten einer Drag’n’Drop-Operation:

  1. Eine Drag’n’Drop-Operation startet, wenn man mit gedrückter linker Maustaste eine kleine Bewegung macht.
  2. Wenn man mit gedrückter Maustaste über eine Komponente fährt, kann diese die gezogenen Elemente akzeptieren oder ablehnen.
  3. Beim Loslassen der linken Maustaste nach einer Bewegung werden die Elemente abgelegt, sofern sie akzeptiert werden.
  4. Beim Beenden einer Drag’n’Drop-Operation erhält die Quelle eine Botschaft, ob der Vorgang erfolgreich war oder fehlgeschlagen ist.

1. Start der Drag’n’Drop-Operation – BeginDrag-Methode der Quelle aufrufen

Wenn wir Edit1 im Objektinspektor betrachten, wird uns die DragMode-Eigenschaft auffallen. DragMode bestimmt, wie das Steuerelement Drag’n’Drop-Operationen beginnt. DragMode kann folgende Werte annehmen:

  • dmManual (Default): Drag’n’Drop-Funktionen sind zur Laufzeit deaktiviert.
  • dmAutomatic: Mit jedem Klick auf die Komponente wird eine Drag’n’Drop-Operation gestartet.

Der einfachste Weg wäre jetzt, wenn wir einfach DragMode auf dmAutomatic setzen würden. Dabei ist jedoch zu beachten, dass dann mit jedem Klick auf das Edit-Feld auch eine Drag’n’Drop-Operation gestartet wird. Deshalb belassen wir DragMode besser auf dmManual und schreiben eine Ereignisbehandlungsroutine für das OnMouseDown-Event von Edit1:

procedure TForm1.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer); 
begin 
  if Button = mbLeft then Edit1.BeginDrag(False); 
  // Immediate-Parameter: False, damit Drag'n'Drop erst nach einer 
  // winzigen Mausbewegung beginnt 
end;

Wenn wir als Parameter True übergeben, hat das dieselbe Auswirkung wie Setzen der DragMode-Eigenschaft auf dmAutomatic. False bewirkt, dass die Drag’n’Drop-Operation erst nach einer winzigen Mausbewegung beginnt. So sind auch normale Klicks in das Editierfeld möglich. Natürlich können wir bei Steuerelementen, die nicht mit normalen Klicks umgehen können müssen, DragMode auch auf dmAutomatic setzen.

2. Akzeptieren des gezogenen Elements – OnDragOver-Event des Ziels auswerten

Label1 empfängt ein OnDragOver-Ereignis, wenn der Inhalt von Edit1 über Label1 gezogen wird. Um dem Benutzer anzuzeigen, dass das Ablegen möglich ist, soll der Mauszeiger geändert werden. Das erreichen wir durch Setzen des Variablenparameters Accept auf True:

procedure TForm1.Label1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); 
begin 
  if (Source is TEdit) then 
    Accept := True; 
end;

Bemerkung: Wenn wir nur Edit1 als Quelle akzeptieren möchten, müssen wir stattdessen folgenden Code verwenden:

 if (Source = Edit1) then 
    Accept := True;

Mit Hilfe des Parameters State können wir auswerten, ob das gezogene Element in das Zielobjekt hineinbewegt wird (State = dsDragEnter) oder hinausbewegt wird (State = dsDragLeave).

3. Ablegen des Elements – OnDragDrop-Event des Ziels auswerten

Ein akzeptiertes Element kann, durch Loslassen der Maustaste, abgelegt werden. Was dabei passieren soll, schreiben wir in die OnDragDrop-Ereignisbehandlungsroutine der Zielkomponente:

procedure TForm1.Label1DragDrop(Sender, Source: TObject; X, Y: Integer); 
begin 
  if (Source is TEdit) then 
    Label1.Caption := TEdit(Source).Text; 
end;

4. Beenden der Drag’n’Drop-Operation – OnEndDrag-Event der Quelle auswerten

Die Quelle (in diesem Fall Edit1) erhält beim Loslassen der Maustaste über ihr OnEndDrag-Ereignis eine Benachrichtigung, ob der Ziehvorgang erfolgreich abgeschlossen werden konnte:

procedure TForm1.Edit1EndDrag(Sender, Target: TObject; X, Y: Integer); 
begin 
  if (Target = nil) then 
    MessageBeep(0); 
  // Wenn Drag'n'Drop-Operation nicht erfolgreich abeschlossen wurde... 
end;