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

Drag’n’Drop in Delphi

Drag’n’Drop aus dem Explorer

Hierbei liegt das Problem darin, dass Ereignisse, die außerhalb der Anwendung geschehen, von Delphi nicht ausgewertet werden. Das heißt, dass wir die entsprechenden Botschaften selbst auswerten müssen. Dabei benötigen wir einige Funktionen aus der Unit ShellAPI:

  • DragAcceptFiles
  • DragQueryFiles
  • DragFinish

Dateien auf die Form ziehen

Wie auch schon oben werden wir jetzt eine kleine Testanwendung programmieren. Am Ende ist es möglich, Dateien aus dem Explorer auf das Formular zu ziehen. Die Dateipfade werden in einer TListbox-Komponente aufgeführt.
Zuerst binden wir die Unit ShellAPI über den uses-Abschnitt ein.
Beim Start der Anwendung melden wir die Anwendung als Drag’n’Drop-Ziel an. Das geschieht über die ShellAPI-Funktion DragAcceptFiles. DragAcceptFiles verlangt zwei Parameter: zum einen das Handle des Steuerelements, auf das gezogen werden soll, und zum andern einen Boolean-Parameter Accept, der angibt, ob Drag’n’Drop-Vorgänge unterstützt werden sollen oder nicht:

implementation

uses ShellAPI;

procedure TForm1.FormCreate(Sender: TObject);
begin
 DragAcceptFiles(Form1.Handle, true); 
end;

Wenn wir im späteren Verlauf des Programmes Drag’n’Drop nicht mehr unterstützen möchten, können wir einfach den Accept-Parameter auf False setzen.
Um nun aber mit dem Explorer kommunizieren zu können, müssen wir eine Windows-Botschaftenmethode für WM_DROPFILES in die Klassendefinition von Form1 aufnehmen:

type 
 TForm1 = class(TForm) 
 Memo1: TMemo; 
 procedure FormCreate(Sender: TObject); 
 protected 
 procedure WMDROPFILES(var Msg: TMessage); message WM_DROPFILES; 
 private 
 { Private-Deklarationen } 
 public 
 { Public-Deklarationen } 
 end;

Die Ereignisroutine sieht wie folgt aus:

const   DF_NUMBEROFFILES = $FFFFFFFF;  
procedure TForm1.WMDROPFILES(var Msg: TMessage); 
var i, anzahl, size: Integer; 
 Dateiname: PChar; 
begin 
 inherited; 
 anzahl := DragQueryFile(Msg.WParam, DF_NUMBEROFFILES, Dateiname, 255); 
 for i := 0 to (anzahl - 1) do 
 begin 
 size := DragQueryFile(Msg.WParam, i, nil, 0) + 1; 
 Dateiname := StrAlloc(size); 
 DragQueryFile(Msg.WParam, i, Dateiname, size); 
 Listbox1.Items.Add(StrPas(Dateiname)); 
 StrDispose(Dateiname); 
 end; 
 DragFinish(Msg.WParam); 
end;

Wir verwenden mehrmals die Funktion DragQueryFile. Sie erwartet folgende Parameter:

  • Drop: Identifiert die Struktur die die Dateinamen enthält.
  • FileIndex: Index der Datei, die in den Puffer geladen werden soll. Wenn für diesen Parameter $FFFFFFFF übergeben wird, erhält man als Rückgabewert die Anzahl der Dateien.
  • FileName: PChar, in den der Dateiname geladen wird. Wird für diesen Parameter nil übergeben, erhält man als Rückgabewert die erforderliche Größe für den Dateinamen.
  • cb: Länge des Teilstückes, das gelesen werden soll

Nach der Initialisierung der Puffervariablen Dateiname bestimmen wir die Anzahl der übergebenen Dateien. Dabei muss der zweite Parameter von DragQueryFile auf $FFFFFFFF gesetzt werden. Wir übergeben DF_NUMBEROFFILES. Diese Konstante haben wir zuvor als $FFFFFFFF definiert.