Sign in Join
Wiki copytemporary

Drag and Drop/de: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Drag and Drop/de

OldNewLine
1+\
2+Zurück zu den [[Additional information/de|Zusätzlichen Informationen]].\
3+\
4+\
5+Dieser Artikel beschäftigt sich mit der Windows- und der Linuxprogrammierung.\
6+Dieser Artikel bezieht sich auf Lazarus Version 1.0.10 und höher.\
7+\
8+=Grundlegendes zu Drag and Drop= Drag and Drop ist eine Methode zur Bedienung grafischer Benutzeroberflächen.\
9+Bei einem Drag and Drop Vorgang sind immer zwei Objekte beteiligt. Das sendende Objekt und das entgegennehmende Objekt.\
10+\
11+
12+# Drag and Drop innerhalb eines Formulars
13+
14+\
15+Damit ein Objekt senden kann, benötigt es genau ein Ereignis:\
16+* OnMouseDown\
17+Damit ein Objekt empfangen kann, benötigt es zwei Ereignise:\
18+* OnDragDrop
19+
20+- OnDragOver
21+
22+\
23+==Das OnMouseDown-Ereignis des sendenden Objekts== Beispiele wie ein OnMouseDown-Ereignis des sendenden Objektes aussehen kann:\
24+===Beispiel für ein Edit===
25+
26+``` pascal
27+procedure TForm1.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
28+ Shift: TShiftState; X, Y: integer);
29+begin
30+ if Button = mbLeft then
31+ Edit1.BeginDrag(False); // False, damit Drag and Drop erst nach einer Mausbewegung beginnt
32+end;
33+```
34+
35+\
36+===Beispiel für ein Memo===
37+
38+``` pascal
39+procedure TForm1.Memo1MouseDown(Sender: TObject; Button: TMouseButton;
40+ Shift: TShiftState; X, Y: Integer);
41+begin
42+ if Button = mbLeft then
43+ Memo1.BeginDrag(False); // False, damit Drag and Drop erst nach einer Mausbewegung beginnt
44+end;
45+```
46+
47+\
48+==Die Ereignisse OnDragDrop, OnDragOver und EndDrag des empfangenden Objekts==
49+
50+### Beispiel für ein Edit, wenn ein Edit der Sender ist
51+
52+``` pascal
53+// Auswerten, ob es sich um den richtigen Sendertyp handelt
54+// und nicht, ob es sich um den richtigen Sender handelt
55+procedure TForm1.Edit2DragOver(Sender, Source: TObject; X, Y: integer;
56+ State: TDragState; var Accept: boolean);
57+begin
58+ if (Source is TEdit) then // Fragt den Objekttyp ab
59+ Accept := True; // Wenn der Objekttyp stimmt ist der Datensatz zu akzeptieren
60+end;
61+
62+// Datenübernahme
63+procedure TForm1.Edit2DragDrop(Sender, Source: TObject; X, Y: integer);
64+begin
65+ if (Source is TEdit) then // Wenn der Objekttyp stimmt werden die Daten übernommen
66+ Edit2.Text := TEdit(Source).Text;
67+end;
68+
69+// Fehlerauswertung
70+procedure TForm1.Edit2EndDrag(Sender, Target: TObject; X, Y: Integer);
71+begin
72+ if (Target = nil) then // Wenn beim Drag and Drop ein Fehlerauftritt
73+ Showmessage('Bei Drag and Drop ist ein Fehler aufgetreten.');
74+end;
75+```
76+
77+\
78+===Beispiel für eine Listbox, wenn ein Edit der Sender ist===
79+
80+``` pascal
81+// Auswerten, ob es sich um den richtigen Sendertyp handelt
82+// und nicht, ob es sich um den richtigen Sender handelt
83+procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: integer;
84+ State: TDragState; var Accept: boolean);
85+begin
86+ if (Source is TEdit) then // Fragt den Objekttyp ab
87+ Accept := True; // Wenn der Objekttyp stimmt ist der Datensatz zu akzeptieren
88+end;
89+
90+// Datenübernahme
91+procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: integer);
92+begin
93+ if (Source is TEdit) then // Wenn der Objekttyp stimmt werden die Daten übernommen
94+ Listbox1.Items.Add(TEdit(Source).Text); // Fügt den Text aus dem Edit hinzu
95+end;
96+
97+// Fehlerauswertung
98+procedure TForm1.ListBox1EndDrag(Sender, Target: TObject; X, Y: integer);
99+begin
100+ if (Target = nil) then // Wenn beim Drag and Drop ein Fehlerauftritt
101+ ShowMessage('Bei Drag and Drop ist ein Fehler aufgetreten.');
102+end;
103+```
104+
105+\
106+===Beispiel für ein Treeview, wenn ein Edit der Sender ist===
107+
108+``` pascal
109+// Auswerten, ob es sich um den richtigen Sendertyp handelt
110+// und nicht, ob es sich um den richtigen Sender handelt
111+procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: integer;
112+ State: TDragState; var Accept: boolean);
113+begin
114+ if (Source is TEdit) then // Fragt den Objekttyp ab
115+ Accept := True; // Wenn der Objekttyp stimmt ist der Datensatz zu akzeptieren
116+end;
117+
118+// Datenübernahme
119+procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: integer);
120+var
121+ tv: TTreeView;
122+ Knoten: TTreeNode;
123+
124+begin
125+
126+ tv := TTreeView(Sender); // Sender is TreeView where the data is being dropped
127+ Knoten := tv.GetNodeAt(x, y); // x,y sind die Drop Koordinaten im Baum des Treeview
128+
129+ // Wenn der Objekttyp stimmt werden die Daten übernommen
130+ if Source is TEdit then
131+ // nun werden die Daten dem Knoten hizugefügt
132+ tv.Items.AddChild(Knoten, TEdit(Source).Text);
133+
134+end;
135+
136+// Fehlerauswertung
137+procedure TForm1.TreeView1EndDrag(Sender, Target: TObject; X, Y: integer);
138+begin
139+ if (Target = nil) then // Wenn beim Drag and Drop ein Fehlerauftritt
140+ ShowMessage('Bei Drag and Drop ist ein Fehler aufgetreten.');
141+end;
142+```
143+
144+\
145+
146+# Drag and Drop vom Dateimanager auf das Formular
147+
148+Vorab:\
149+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.\
150+Dateimanager sind z. B.:\
151+Explorer (Betriebsystem Windows), Nautilus (Betriebssystem Ubuntu), Dolphin, Konqueror, usw.\
152+\
153+Vorgehensweise:\
154+Zu erst muss im Objektinspektor des Formulars im Register Eigenschaft die Eigenschaft <b>AllowDropFiles</b> auf True gesetzt werden.\
155+\
156+![](/wiki-images/3/3f/DragDropEigenschaften.jpg)\
157+\
158+Dann wird im Objektinspektor des Formulars im Register Ereignisse das Ereignis <b>OnDropFiles</b> ausgewählt.\
159+\
160+![](/wiki-images/f/f1/DragDropEreignisse.jpg)\
161+\
162+Um zum Beispiel die Dateien in einer ListBox an zuzeigen, wird für das Ereignis <b>OnDropFiles</b> folgender Code benötigt:\
163+===Minimalbeispiel zu OnDropFiles===
164+
165+``` pascal
166+procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of string);
167+var
168+ intI: integer = 0;
169+begin
170+
171+ for intI := 0 to high(filenames) do
172+ listbox1.Items.Add(filenames[intI]);
173+
174+end;
175+```
176+
177+\
178+
179+## Ein Beispiel dass Probleme bei OnDropFiles erläutert
180+
181+\
182+Dieses Beispiel beschäftigt sich mit Besonderheiten editierbarer Felder und der Auswertung des Drop.\
183+Dieses Beispiel beschäftigt sich auch mit Besonderheiten der Linuxprogrammierung.\
184+\
185+===Probleme=== Beim Ziehen auf ein Formular entstehen folgende Effekte:
186+
187+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
188+2. Editierbare Felder fügen den erhaltenen Text automatisch ein! Alle Anderen nicht.
189+3. Zusätzlich fügen diese Felder automatisch eine Kennung hinzu z.B. <b>file:</b> oder <b>url:</b>
190+4. <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
191+5. Wegen 2. wird u.U. doppelt eingefügt, wenn nicht geprüft wird, wo der Drop erfolgt
192+
193+\
194+<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.
195+
196+### Aufbau des Beispiels
197+
198+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).\
199+<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.\
200+====Zusätzlich benötigte Units====
201+
202+- baseunix
203+- types
204+
205+\
206+====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.
207+
208+- 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.)
209+- LINKs: Gerade SymLinks führen zu einem anderen Verzeichniss, dies kann beim Folgen eines solchen zu einer endlosen Kreisbewegung führen.\
210+
211+\
212+<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>\
213+\
214+Die genaue Auswertung was im Dateisystem hinter dem Pfad steckt, erfolgt mit folgenden Funktionen:
215+
216+``` pascal
217+//Prüfe ob StrPath ein LINK im Dateisystem ist
218+function IsLink(const StrPath: string):Boolean;
219+ var info: stat;
220+ begin
221+ fplstat(StrPath, @info);
222+ Result := (fpS_ISLNK(info.st_mode));
223+ end;
224+
225+//Prüfe ob StrPath eine reguläre Datei ist
226+function IsRegular(const StrPath: string):Boolean;
227+ var info: stat;
228+ begin
229+ fplstat(StrPath, @info);
230+ Result := (fpS_ISREG(info.st_mode));
231+ end;
232+```
233+
234+\
235+===Beispiel mit Auswertung des Drop=== Es erfolgt folgende Auswertung:
236+
237+- Gehört der übergebene Pfad zum lokalen Dateisystem
238+- Ist es etwa eine URL z.B. WebLink <b><http://></b> oder eine Freigabe <b><smb://></b>
239+- Auf welchem Element ist der Drop erfolgt
240+
241+\
242+
243+``` pascal
244+procedure TForm1.FormDropFiles(Sender: TObject; const FileNames: array of String );
245+ var i,j: integer;
246+ s: String;
247+ p: TPoint;
248+begin
249+
250+// Auswertung des übergebenen Pfades
251+for i:=0 to High(FileNames) do
252+ begin
253+ s:= FileNames[i];
254+ // Reihenfolge ist für linux wichtig !
255+ if DirectoryExists(s) then begin
256+ if IsLink(s) then Memo1.Lines.Add('VERZEICHNIS LINK:'+s)
257+ else Memo1.Lines.Add('VERZEICHNIS:'+s);
258+ end
259+ else if FileExists(s) then begin
260+ if IsLink(s) then Memo1.Lines.Add('DATEI LINK:'+s)
261+ else if IsRegular(s) then Memo1.Lines.Add('DATEI:'+s)
262+ else Memo1.Lines.Add('Systemdatei NICHT Lesen:'+s); // fifo, socket, usw.
263+ end
264+ else begin
265+ j:= pos('://',s);
266+ if ((j > 0)and(j < 6)) then begin // limit j< 6 hängt von zu erwartetenden Dienst ab
267+ Memo1.Lines.Add('Eine Art von URL:'+s); // 'smb://' , 'http://' , usw.
268+ Memo1.Lines.Add('Dienst:'+copy(s, 1, j));
269+ Memo1.Lines.Add('PFAD:' +copy(s, j+3, Length(s)));
270+ end
271+ // Ein Drop mit Text erfolgt nur auf editierbare Felder
272+ else Memo1.Lines.Add('TEXT:'+s); //Man kann hier also auch Text übergeben
273+ end;
274+
275+ //Auf welchem Element war der Drop: Prüfe ob die Maus über einem ListView war
276+ p:= Mouse.CursorPos;
277+ if PtInRect(ListView1.BoundsRect,Form1.ScreenToClient(p)) then Memo1.Lines.Add('Drop in ListView1');
278+ if PtInRect(ListView2.BoundsRect,Form1.ScreenToClient(p)) then Memo1.Lines.Add('Drop in ListView2');
279+end;
280+```
281+
282+Anmerkung: Die Auswertung der Mausposition erfolgt im Formularkoordinatensystem.
283+
284+---
285+*From the Free Pascal wiki, page "Drag and Drop/de", as it stood on 2020-02-14 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history