Difference between revisions of "Drag and Drop/de"

From Free Pascal wiki
Jump to navigationJump to search
m (Fixed syntax highlighting; deleted category included in page template)
 
(12 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
{{Drag and Drop}}
 
{{Drag and Drop}}
 +
<br>
 +
Zurück zu den [[Additional information/de|Zusätzlichen Informationen]].<br>
 
<br>
 
<br>
 
__TOC__
 
__TOC__
 
<br>
 
<br>
Dieser Artikel beschäftigt sich mit der Windowsprogrammierung.<br>
+
Dieser Artikel beschäftigt sich mit der Windows- und der Linuxprogrammierung.<br>
Dieser Artikel bezieht sich auf Lazarus Version 1.0.8 und höher.<br>
+
Dieser Artikel bezieht sich auf Lazarus Version 1.0.10 und höher.<br>
 
<br>
 
<br>
 
=Grundlegendes zu Drag and Drop=
 
=Grundlegendes zu Drag and Drop=
 
Drag and Drop ist eine Methode zur Bedienung grafischer Benutzeroberflächen.<br>
 
Drag and Drop ist eine Methode zur Bedienung grafischer Benutzeroberflächen.<br>
Bei einem Drag and Drop Vorgang sind immer zwei Objekte beteiligt. Das sendende Objekt und das entgegenehmende Objekt.<br>
+
Bei einem Drag and Drop Vorgang sind immer zwei Objekte beteiligt. Das sendende Objekt und das entgegennehmende Objekt.<br>
 +
<br>
 +
 
 +
=Drag and Drop innerhalb eines Formulars=
 
<br>
 
<br>
Damit ein Objekt senden kann benötigt es genau ein Ereignis:<br>
+
Damit ein Objekt senden kann, benötigt es genau ein Ereignis:<br>
 
* OnMouseDown
 
* OnMouseDown
 
<br>
 
<br>
Damit ein Objekt empfangen kann benötigt es zwei Ereignise:<br>
+
Damit ein Objekt empfangen kann, benötigt es zwei Ereignise:<br>
 
* OnDragDrop
 
* OnDragDrop
 
* OnDragOver
 
* OnDragOver
 
<br>
 
<br>
<br>
+
==Das OnMouseDown-Ereignis des sendenden Objekts==
=Drag and Drop innerhalb eines Formulars=
 
==Das OnMouseDown Ereignis des sendenden Objekts==
 
 
Beispiele wie ein OnMouseDown-Ereignis des sendenden Objektes aussehen kann:<br>
 
Beispiele wie ein OnMouseDown-Ereignis des sendenden Objektes aussehen kann:<br>
 
===Beispiel für ein Edit===
 
===Beispiel für ein Edit===
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
procedure TForm1.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
 
procedure TForm1.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
 
   Shift: TShiftState; X, Y: integer);
 
   Shift: TShiftState; X, Y: integer);
Line 32: Line 35:
 
<br>
 
<br>
 
===Beispiel für ein Memo===
 
===Beispiel für ein Memo===
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
procedure TForm1.Memo1MouseDown(Sender: TObject; Button: TMouseButton;
 
procedure TForm1.Memo1MouseDown(Sender: TObject; Button: TMouseButton;
 
   Shift: TShiftState; X, Y: Integer);
 
   Shift: TShiftState; X, Y: Integer);
Line 43: Line 46:
 
==Die Ereignisse OnDragDrop, OnDragOver und EndDrag des empfangenden Objekts==
 
==Die Ereignisse OnDragDrop, OnDragOver und EndDrag des empfangenden Objekts==
 
===Beispiel für ein Edit, wenn ein Edit der Sender ist===
 
===Beispiel für ein Edit, wenn ein Edit der Sender ist===
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
// Auswerten, ob es sich um den richtigen Sendertyp handelt
 
// Auswerten, ob es sich um den richtigen Sendertyp handelt
 
// und nicht, ob es sich um den richtigen Sender handelt
 
// und nicht, ob es sich um den richtigen Sender handelt
Line 70: Line 73:
 
<br>
 
<br>
 
===Beispiel für eine Listbox, wenn ein Edit der Sender ist===
 
===Beispiel für eine Listbox, wenn ein Edit der Sender ist===
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
// Auswerten, ob es sich um den richtigen Sendertyp handelt
 
// Auswerten, ob es sich um den richtigen Sendertyp handelt
 
// und nicht, ob es sich um den richtigen Sender handelt
 
// und nicht, ob es sich um den richtigen Sender handelt
Line 97: Line 100:
 
<br>
 
<br>
 
===Beispiel für ein Treeview, wenn ein Edit der Sender ist===
 
===Beispiel für ein Treeview, wenn ein Edit der Sender ist===
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
// Auswerten, ob es sich um den richtigen Sendertyp handelt
 
// Auswerten, ob es sich um den richtigen Sendertyp handelt
 
// und nicht, ob es sich um den richtigen Sender handelt
 
// und nicht, ob es sich um den richtigen Sender handelt
Line 134: Line 137:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
<br>
 
<br>
=Drag and Drop vom Explorer auf das Formular=
+
 
 +
=Drag and Drop vom Dateimanager auf das Formular=
 +
Vorab:<br>
 +
Fast jedes Betriebsystem bringt einen oder mehrere Dateimanager mit, das heisst, dass das Funktionieren von Drag and Drop nicht mit jedem Dateimanager garantiert werden kann.<br>
 +
Dateimanager sind z. B.:<br>
 +
Explorer (Betriebsystem Windows), Nautilus (Betriebssystem Ubuntu), Dolphin, Konqueror, usw.<br>
 +
<br>
 +
Vorgehensweise:<br>
 
Zu erst muss im Objektinspektor des Formulars im Register Eigenschaft die Eigenschaft <b>AllowDropFiles</b> auf True gesetzt werden.<br>
 
Zu erst muss im Objektinspektor des Formulars im Register Eigenschaft die Eigenschaft <b>AllowDropFiles</b> auf True gesetzt werden.<br>
 
<br>
 
<br>
Line 144: Line 154:
 
<br>
 
<br>
 
Um zum Beispiel die Dateien in einer ListBox an zuzeigen, wird für das Ereignis <b>OnDropFiles</b> folgender Code benötigt:<br>
 
Um zum Beispiel die Dateien in einer ListBox an zuzeigen, wird für das Ereignis <b>OnDropFiles</b> folgender Code benötigt:<br>
<syntaxhighlight>
+
===Minimalbeispiel zu OnDropFiles===
 +
<syntaxhighlight lang=pascal>
 
procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of string);
 
procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of string);
 
var
 
var
Line 156: Line 167:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
<br>
 
<br>
 +
 +
==Ein Beispiel dass Probleme bei OnDropFiles erläutert==
 +
<br>
 +
Dieses Beispiel beschäftigt sich mit Besonderheiten editierbarer Felder und der Auswertung des Drop.<br>
 +
Dieses Beispiel beschäftigt sich auch mit Besonderheiten der Linuxprogrammierung.<br>
 
<br>
 
<br>
--[[User:Olaf|Olaf]] 05:41, 10 July 2013 (UTC)
+
===Probleme===
[[Category:Tutorials/de]]{{AutoCategory}}
+
Beim Ziehen auf ein Formular entstehen folgende Effekte:
 +
# Der Drop kann auf das Formular selbst oder ein Komponente auf dem Formular erfolgen, wo spielt keine Rolle, aber es wird kein Zielpunkt übergeben
 +
# Editierbare Felder fügen den erhaltenen Text automatisch ein! Alle Anderen nicht.
 +
# Zusätzlich fügen diese Felder automatisch eine Kennung hinzu z.B. <b>file:</b> oder <b>url:</b>
 +
# <b>Das Ereignis wird vom Formular in jedem Fall verarbeitet</b>, es ist nicht möglich den Drop durch das Editierfeld zu verweigern, abzubrechen oder umzuleiten
 +
# Wegen 2. wird u.U. doppelt eingefügt, wenn nicht geprüft wird, wo der Drop erfolgt
 +
<br>
 +
<b>Hinweis:</b> Um 'einfach' ein <b>Drop-Ereignis auf ein editierbares Element zu verhindern</b>, kann es auf <b>Readonly</b> gesetzt werden. Der Cursor zeigt dann, dass das Feld keinen Drop annimmt. Eine bessere Lösung kann ich derzeit nicht anbieten.
 +
===Aufbau des Beispiels===
 +
Das Beispiel besteht aus zwei ListView-Elementen, da diese auf den FileDrop nicht weiter reagieren, es könnten aber auch andere sein (sollten nur keine editierbaren sein). Diese Element haben sonst keine Aufgaben. Ein Memo-Element wird zur Ausgabe der Ergebnisse benutzt. Hier kann auch ein reiner Text-Drop<sup>*</sup>) aus einem Editierfeld überprüft werden (markieren und ziehen).<br>
 +
<sup>*</sup>) In wie weit meine Desktopumgebung (Debian+KDE4) hier automatismen verwendet die zu einem anderem Verhalten führen als geplant, kann ich bisher nicht nachvollziehen.<br>
 +
====Zusätzlich benötigte Units====
 +
* baseunix
 +
* types
 +
<br>
 +
====Benötigt Funktionen für Linux (basierend auf <i>baseunix</i>)====
 +
Mit Linux wird im Prizip (fast) alles als Datei behandelt. Anhand des Pfades ist zunächst nicht erkennbar was dahinter steckt.
 +
*Systemdateien: Hier kann ein Problem entstehen wenn ein Lesezugriff z.B. auf einen FIFO gemacht wird, als ob es eine normale Datei wäre: Die Datei hat KEIN ENDE. (In die Falle tappen viele Programme.)
 +
*LINKs: Gerade SymLinks führen zu einem anderen Verzeichniss, dies kann beim Folgen eines solchen zu einer endlosen Kreisbewegung führen.<br>
 +
<br>
 +
<b>Anmerkung:</b> Dateien und Verzeichnisse können ein LINK sein. Siehe Unit <b>Baseunix</b>, Beispiel zu
 +
<b>S_ISLNK</b> ; Siehe auch Linuxbefehl <b>stat</b><br>
 +
<br>
 +
Die genaue Auswertung was im Dateisystem hinter dem Pfad steckt, erfolgt mit folgenden Funktionen:
 +
<syntaxhighlight lang=pascal>
 +
//Prüfe ob StrPath ein LINK im Dateisystem ist
 +
function IsLink(const StrPath: string):Boolean;
 +
  var info: stat;
 +
  begin
 +
    fplstat(StrPath, @info);
 +
    Result := (fpS_ISLNK(info.st_mode));
 +
  end;
 +
 
 +
//Prüfe ob StrPath eine reguläre Datei ist
 +
function IsRegular(const StrPath: string):Boolean;
 +
  var info: stat;
 +
  begin
 +
    fplstat(StrPath, @info);
 +
    Result := (fpS_ISREG(info.st_mode));
 +
  end; 
 +
</syntaxhighlight>
 +
<br>
 +
===Beispiel mit Auswertung des Drop===
 +
Es erfolgt folgende Auswertung:
 +
*Gehört der übergebene Pfad zum lokalen Dateisystem
 +
*Ist es etwa eine URL z.B. WebLink <b>http://</b> oder eine Freigabe <b>smb://</b>
 +
*Auf welchem Element ist der Drop erfolgt
 +
<br>
 +
<syntaxhighlight lang=pascal>
 +
procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of String );
 +
var i,j: integer;
 +
    s: String;
 +
    p: TPoint;
 +
begin
 +
 
 +
// Auswertung des übergebenen Pfades
 +
for i:=0 to High(FileNames) do
 +
begin
 +
  s:= FileNames[i];
 +
  // Reihenfolge ist für linux wichtig !
 +
  if DirectoryExists(s) then begin
 +
    if IsLink(s) then Memo1.Lines.Add('VERZEICHNIS LINK:'+s)
 +
    else Memo1.Lines.Add('VERZEICHNIS:'+s);
 +
  end
 +
  else if FileExists(s) then begin
 +
    if      IsLink(s)    then Memo1.Lines.Add('DATEI LINK:'+s)
 +
    else if IsRegular(s) then Memo1.Lines.Add('DATEI:'+s)
 +
    else Memo1.Lines.Add('Systemdatei NICHT Lesen:'+s); // fifo, socket, usw.
 +
  end
 +
  else begin
 +
  j:= pos('://',s);
 +
  if ((j > 0)and(j < 6)) then begin // limit j< 6 hängt von zu erwartetenden Dienst ab
 +
      Memo1.Lines.Add('Eine Art von URL:'+s); // 'smb://' , 'http://' , usw.
 +
      Memo1.Lines.Add('Dienst:'+copy(s, 1,  j));
 +
      Memo1.Lines.Add('PFAD:'  +copy(s, j+3, Length(s)));
 +
  end
 +
    // Ein Drop mit Text erfolgt nur auf editierbare Felder
 +
    else Memo1.Lines.Add('TEXT:'+s); //Man kann hier also auch Text übergeben
 +
  end;
 +
 
 +
  //Auf welchem Element war der Drop: Prüfe ob die Maus über einem ListView war
 +
  p:= Mouse.CursorPos;
 +
  if PtInRect(ListView1.BoundsRect,Form1.ScreenToClient(p)) then Memo1.Lines.Add('Drop in ListView1');
 +
  if PtInRect(ListView2.BoundsRect,Form1.ScreenToClient(p)) then Memo1.Lines.Add('Drop in ListView2');
 +
end;
 +
</syntaxhighlight>
 +
Anmerkung: Die Auswertung der Mausposition erfolgt im Formularkoordinatensystem.

Latest revision as of 07:03, 14 February 2020

Deutsch (de)

Zurück zu den Zusätzlichen Informationen.


Dieser Artikel beschäftigt sich mit der Windows- und der Linuxprogrammierung.
Dieser Artikel bezieht sich auf Lazarus Version 1.0.10 und höher.

Grundlegendes zu Drag and Drop

Drag and Drop ist eine Methode zur Bedienung grafischer Benutzeroberflächen.
Bei einem Drag and Drop Vorgang sind immer zwei Objekte beteiligt. Das sendende Objekt und das entgegennehmende Objekt.

Drag and Drop innerhalb eines Formulars


Damit ein Objekt senden kann, benötigt es genau ein Ereignis:

  • OnMouseDown


Damit ein Objekt empfangen kann, benötigt es zwei Ereignise:

  • OnDragDrop
  • OnDragOver


Das OnMouseDown-Ereignis des sendenden Objekts

Beispiele wie ein OnMouseDown-Ereignis des sendenden Objektes aussehen kann:

Beispiel für ein Edit

procedure TForm1.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: integer);
begin
  if Button = mbLeft then
    Edit1.BeginDrag(False); // False, damit Drag and Drop erst nach einer Mausbewegung beginnt
end;


Beispiel für ein Memo

procedure TForm1.Memo1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbLeft then
    Memo1.BeginDrag(False);  // False, damit Drag and Drop erst nach einer Mausbewegung beginnt
end;


Die Ereignisse OnDragDrop, OnDragOver und EndDrag des empfangenden Objekts

Beispiel für ein Edit, wenn ein Edit der Sender ist

// Auswerten, ob es sich um den richtigen Sendertyp handelt
// und nicht, ob es sich um den richtigen Sender handelt
procedure TForm1.Edit2DragOver(Sender, Source: TObject; X, Y: integer;
  State: TDragState; var Accept: boolean);
begin
  if (Source is TEdit) then // Fragt den Objekttyp ab
    Accept := True; // Wenn der Objekttyp stimmt ist der Datensatz zu akzeptieren
end;

// Datenübernahme
procedure TForm1.Edit2DragDrop(Sender, Source: TObject; X, Y: integer);
begin
  if (Source is TEdit) then // Wenn der Objekttyp stimmt werden die Daten übernommen
    Edit2.Text := TEdit(Source).Text;
end;

// Fehlerauswertung
procedure TForm1.Edit2EndDrag(Sender, Target: TObject; X, Y: Integer);
begin
  if (Target = nil) then // Wenn beim Drag and Drop ein Fehlerauftritt
    Showmessage('Bei Drag and Drop ist ein Fehler aufgetreten.');
end;


Beispiel für eine Listbox, wenn ein Edit der Sender ist

// Auswerten, ob es sich um den richtigen Sendertyp handelt
// und nicht, ob es sich um den richtigen Sender handelt
procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: integer;
  State: TDragState; var Accept: boolean);
begin
  if (Source is TEdit) then // Fragt den Objekttyp ab
    Accept := True; // Wenn der Objekttyp stimmt ist der Datensatz zu akzeptieren
end; 

// Datenübernahme
procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: integer);
begin
  if (Source is TEdit) then // Wenn der Objekttyp stimmt werden die Daten übernommen
    Listbox1.Items.Add(TEdit(Source).Text); // Fügt den Text aus dem Edit hinzu
end;

// Fehlerauswertung
procedure TForm1.ListBox1EndDrag(Sender, Target: TObject; X, Y: integer);
begin
  if (Target = nil) then // Wenn beim Drag and Drop ein Fehlerauftritt
    ShowMessage('Bei Drag and Drop ist ein Fehler aufgetreten.');
end;


Beispiel für ein Treeview, wenn ein Edit der Sender ist

// Auswerten, ob es sich um den richtigen Sendertyp handelt
// und nicht, ob es sich um den richtigen Sender handelt
procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: integer;
  State: TDragState; var Accept: boolean);
begin
  if (Source is TEdit) then // Fragt den Objekttyp ab
    Accept := True; // Wenn der Objekttyp stimmt ist der Datensatz zu akzeptieren
end;

// Datenübernahme
procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: integer);
var
  tv: TTreeView;
  Knoten: TTreeNode;

begin

  tv := TTreeView(Sender);      // Sender is TreeView where the data is being dropped
  Knoten := tv.GetNodeAt(x, y);   // x,y sind die Drop Koordinaten im Baum des Treeview

  // Wenn der Objekttyp stimmt werden die Daten übernommen
  if Source is TEdit then
    // nun werden die Daten dem Knoten hizugefügt
    tv.Items.AddChild(Knoten, TEdit(Source).Text);

end;

// Fehlerauswertung
procedure TForm1.TreeView1EndDrag(Sender, Target: TObject; X, Y: integer);
begin
  if (Target = nil) then // Wenn beim Drag and Drop ein Fehlerauftritt
    ShowMessage('Bei Drag and Drop ist ein Fehler aufgetreten.');
end;


Drag and Drop vom Dateimanager auf das Formular

Vorab:
Fast jedes Betriebsystem bringt einen oder mehrere Dateimanager mit, das heisst, dass das Funktionieren von Drag and Drop nicht mit jedem Dateimanager garantiert werden kann.
Dateimanager sind z. B.:
Explorer (Betriebsystem Windows), Nautilus (Betriebssystem Ubuntu), Dolphin, Konqueror, usw.

Vorgehensweise:
Zu erst muss im Objektinspektor des Formulars im Register Eigenschaft die Eigenschaft AllowDropFiles auf True gesetzt werden.

DragDropEigenschaften.jpg

Dann wird im Objektinspektor des Formulars im Register Ereignisse das Ereignis OnDropFiles ausgewählt.

DragDropEreignisse.jpg

Um zum Beispiel die Dateien in einer ListBox an zuzeigen, wird für das Ereignis OnDropFiles folgender Code benötigt:

Minimalbeispiel zu OnDropFiles

procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of string);
var
  intI: integer = 0;
begin

  for intI := 0 to high(filenames) do
    listbox1.Items.Add(filenames[intI]);

end;


Ein Beispiel dass Probleme bei OnDropFiles erläutert


Dieses Beispiel beschäftigt sich mit Besonderheiten editierbarer Felder und der Auswertung des Drop.
Dieses Beispiel beschäftigt sich auch mit Besonderheiten der Linuxprogrammierung.

Probleme

Beim Ziehen auf ein Formular entstehen folgende Effekte:

  1. Der Drop kann auf das Formular selbst oder ein Komponente auf dem Formular erfolgen, wo spielt keine Rolle, aber es wird kein Zielpunkt übergeben
  2. Editierbare Felder fügen den erhaltenen Text automatisch ein! Alle Anderen nicht.
  3. Zusätzlich fügen diese Felder automatisch eine Kennung hinzu z.B. file: oder url:
  4. Das Ereignis wird vom Formular in jedem Fall verarbeitet, es ist nicht möglich den Drop durch das Editierfeld zu verweigern, abzubrechen oder umzuleiten
  5. Wegen 2. wird u.U. doppelt eingefügt, wenn nicht geprüft wird, wo der Drop erfolgt


Hinweis: Um 'einfach' ein Drop-Ereignis auf ein editierbares Element zu verhindern, kann es auf Readonly gesetzt werden. Der Cursor zeigt dann, dass das Feld keinen Drop annimmt. Eine bessere Lösung kann ich derzeit nicht anbieten.

Aufbau des Beispiels

Das Beispiel besteht aus zwei ListView-Elementen, da diese auf den FileDrop nicht weiter reagieren, es könnten aber auch andere sein (sollten nur keine editierbaren sein). Diese Element haben sonst keine Aufgaben. Ein Memo-Element wird zur Ausgabe der Ergebnisse benutzt. Hier kann auch ein reiner Text-Drop*) aus einem Editierfeld überprüft werden (markieren und ziehen).
*) In wie weit meine Desktopumgebung (Debian+KDE4) hier automatismen verwendet die zu einem anderem Verhalten führen als geplant, kann ich bisher nicht nachvollziehen.

Zusätzlich benötigte Units

  • baseunix
  • types


Benötigt Funktionen für Linux (basierend auf baseunix)

Mit Linux wird im Prizip (fast) alles als Datei behandelt. Anhand des Pfades ist zunächst nicht erkennbar was dahinter steckt.

  • Systemdateien: Hier kann ein Problem entstehen wenn ein Lesezugriff z.B. auf einen FIFO gemacht wird, als ob es eine normale Datei wäre: Die Datei hat KEIN ENDE. (In die Falle tappen viele Programme.)
  • LINKs: Gerade SymLinks führen zu einem anderen Verzeichniss, dies kann beim Folgen eines solchen zu einer endlosen Kreisbewegung führen.


Anmerkung: Dateien und Verzeichnisse können ein LINK sein. Siehe Unit Baseunix, Beispiel zu S_ISLNK ; Siehe auch Linuxbefehl stat

Die genaue Auswertung was im Dateisystem hinter dem Pfad steckt, erfolgt mit folgenden Funktionen:

//Prüfe ob StrPath ein LINK im Dateisystem ist
function IsLink(const StrPath: string):Boolean;
   var info: stat;
  begin
    fplstat(StrPath, @info);
    Result := (fpS_ISLNK(info.st_mode));
  end;

//Prüfe ob StrPath eine reguläre Datei ist
function IsRegular(const StrPath: string):Boolean;
   var info: stat;
  begin
    fplstat(StrPath, @info);
    Result := (fpS_ISREG(info.st_mode));
  end;


Beispiel mit Auswertung des Drop

Es erfolgt folgende Auswertung:

  • Gehört der übergebene Pfad zum lokalen Dateisystem
  • Ist es etwa eine URL z.B. WebLink http:// oder eine Freigabe smb://
  • Auf welchem Element ist der Drop erfolgt


procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of String );
 var i,j: integer;
     s: String;
     p: TPoint;
begin

// Auswertung des übergebenen Pfades
for i:=0 to High(FileNames) do
 begin
  s:= FileNames[i];
  // Reihenfolge ist für linux wichtig !
  if DirectoryExists(s) then begin
    if IsLink(s) then Memo1.Lines.Add('VERZEICHNIS LINK:'+s)
     else Memo1.Lines.Add('VERZEICHNIS:'+s);
  end
  else if FileExists(s) then begin
    if      IsLink(s)    then Memo1.Lines.Add('DATEI LINK:'+s)
    else if IsRegular(s) then Memo1.Lines.Add('DATEI:'+s)
    else Memo1.Lines.Add('Systemdatei NICHT Lesen:'+s); // fifo, socket, usw.
  end
  else begin
   j:= pos('://',s);
   if ((j > 0)and(j < 6)) then begin // limit j< 6 hängt von zu erwartetenden Dienst ab
      Memo1.Lines.Add('Eine Art von URL:'+s); // 'smb://' , 'http://' , usw.
      Memo1.Lines.Add('Dienst:'+copy(s, 1,   j));
      Memo1.Lines.Add('PFAD:'  +copy(s, j+3, Length(s)));
   end
    // Ein Drop mit Text erfolgt nur auf editierbare Felder
    else Memo1.Lines.Add('TEXT:'+s); //Man kann hier also auch Text übergeben
  end;

  //Auf welchem Element war der Drop: Prüfe ob die Maus über einem ListView war
  p:= Mouse.CursorPos;
  if PtInRect(ListView1.BoundsRect,Form1.ScreenToClient(p)) then Memo1.Lines.Add('Drop in ListView1');
  if PtInRect(ListView2.BoundsRect,Form1.ScreenToClient(p)) then Memo1.Lines.Add('Drop in ListView2');
end;

Anmerkung: Die Auswertung der Mausposition erfolgt im Formularkoordinatensystem.