Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Drag&Drop innerhalb eines VirtualTree und in den Explorer (https://www.delphipraxis.net/209613-drag-drop-innerhalb-eines-virtualtree-und-den-explorer.html)

Gausi 29. Dez 2021 21:40

Drag&Drop innerhalb eines VirtualTree und in den Explorer
 
Ich bin grade dabei, in Sachen Drag&Drop etwas aufzuräumen.

Folgende Situation: Ich habe mehrere VirtualStringTrees in meiner Anwendung, die eine logische Sortierung von Dateien abbilden. D.h. die Dateien sind nicht nur entsprechend ihrer Ordnerstruktur auf der Festplatte organisiert, sondern auch nach anderen Kriterien, z.B. nach vom User definierbaren "Kategorien".

Ich möchte nun
  1. Die Dateien innerhalb meiner Anwendung per Drag&Drop umsortieren. Dabei möchte ich dem User die Möglichkeit haben, Dateien in eine andere Kategorie zu kopieren oder zu verschieben.
  2. Einzelne Dateien aus meiner Anwendung heraus in einen neuen Ordner auf der Festplatte kopieren (und nur kopieren, nicht verschieben!)

Einzeln betrachtet macht mir das keine Probleme - aber die Kombination ärgert mich irgendwie. :stupid:

Wenn ich das richtig sehe, wird ja beim Beginn der OLE-Drag&Drop-Operation von der Quelle festgelegt, welche Operationen (DROPEFFECT_COPY bzw. DROPEFFECT_MOVE) erlaubt sind. D.h. es gibt keine Möglichkeit festzulegen, dass innerhalb der eigenen Anwendung ein MOVE erlaubt ist, aber nach außen nur ein COPY? Denn zu Beginn vom Drag steht das Ziel ja noch nicht fest ... :gruebel:

Die einzige Möglichkeit die ich sehe wäre, beim Start z.B. die gedrückte CTRL-Taste abzufragen und dementsprechend ein MOVE zu erlauben oder nicht. D.h. ohne Ctrl Copy/Move aber nur intern, mit Ctrl nur Copy, aber auch nach extern.

Das intern/extern würde ich über die passenden VST-Events regeln. Ich nutze jetzt für den Drop nach außen nicht mehr die sonst überall verlinkten Drag&Drop-Komponenten, sondern mache das selbst (mit großer Hilfe vom VST, versteht sich). Denn wenn ich im OnStartDrag des VST die DragDrop-Komponente fülle und
Delphi-Quellcode:
execute
aufrufe, dann kommen am Ende unter Umständen zwei Drop-Events im VST an - eine vom VST, und dann die von der DragDrop-Komponente (oder umgekehrt, auf jeden Fall führt das zu einem komischen Verhalten).

D.h. im VST.OnGetUserClipboardFormats füge ich je nach Status der CTRL-Taste (oder rechte Maustaste?) das Format CF_HDROP ein oder nicht (und setze ggf. einschränkend
Delphi-Quellcode:
VST.DragOperations := [doCopy];
), und im VST.OnRenderOLEData befülle ich das entsprechende DatenObjekt mit den Dateinamen der markierten Dateien.

Im OnDrop innerhalb der Anwendung nutze ich dann primär das interne Format (bzw. greife auf meine TDatei-Objekte zu), und ändere das Verhalten ggf., wenn auch CF_HDROP als Format vorhanden ist. Damit ist der Standard-Fall (Drag&Drop innerhalb der Anwendung) intuitiv bedienbar, und das Bonus-Feature (nur selten gebraucht) mit dem Drop in den Explorer ist mit nur einem zusätzlichen Tastendruck machbar.

Oder gibt es da eine andere Möglichkeit, die ich übersehen habe?

Redeemer 30. Dez 2021 22:55

AW: Drag&Drop innerhalb eines VirtualTree und in den Explorer
 
Zitat:

Zitat von Gausi (Beitrag 1499807)
Wenn ich das richtig sehe, wird ja beim Beginn der OLE-Drag&Drop-Operation von der Quelle festgelegt, welche Operationen (DROPEFFECT_COPY bzw. DROPEFFECT_MOVE) erlaubt sind. D.h. es gibt keine Möglichkeit festzulegen, dass innerhalb der eigenen Anwendung ein MOVE erlaubt ist, aber nach außen nur ein COPY? Denn zu Beginn vom Drag steht das Ziel ja noch nicht fest ... :gruebel:

Wenn man sich den Windows Explorer ansieht, dann müsste das aber gehen. Wenn ich im Windows Explorer eine Datei ziehe, dann sieht es ja unterschiedlich aus, je nachdem, ob das mögliche Ziel auf einem anderen oder dem gleichen Laufwerk ist. Nächste Frage ist, wer beim Windows Explorer auf Modifikationstasten (z.B. Alt für Verknüpfung) reagiert.

Gausi 31. Dez 2021 07:16

AW: Drag&Drop innerhalb eines VirtualTree und in den Explorer
 
Sowas dachte ich zuerst auch, aber die Sache mit dem Explorer ist ja anders.

Erstens ist der Explorer eine Anwendung, die natürlich selbst entscheiden kann, was sie mit den angebotenen Dateien machen möchte (d.h. je nach Userwunsch bzw. Modifier-Taste). Das kann ich innerhalb meiner Anwendung ja auch: Fange ich an zu draggen, und drücke währenddessen mal Shift und mal nicht, erscheint als Drag-Hint über meiner Zielkategorie ein "Verschieben" oder "Kopieren", bzw. kann ich im DragOver den DragEffect anpassen. Wenn dieser DragEffect dann zu einem der "AllowedEffects" passt, funktioniert der Drop - sonst nicht.
Ebenso könnte ich anhand der enthaltenen Dateien die eine oder andere Aktion vorschlagen (das macht schätze ich der Explorer bei der Standard-Aktion: Wenn Quell- und Ziel-Laufwerk gleich sind verschieben als Standard, sonst kopieren). Das mache ich bisher nicht, sollte aber möglich sein.

Der Punkt ist aber: der User kann im Explorer ja immer beides, weil der Explorer beim Start des Vorgangs dem Konstrukt mitgibt, dass man kopieren/verschieben/wasauchimmer darf. Das Ziel (oft wieder der Explorer, aber ein anderes Fenster) darf dann entscheiden, welche Aktion tatsächlich ausgeführt werden soll.

Und diese Auswahlmöglichkeit möchte ich "dynamisch" anpassen. D.h. ich suche nach einer Möglichkeit, dass die Quelle des Vorgangs beim DragOver über ein (fremdes) Ziel die erlaubten Möglichkeiten anpassen kann.

Denn ein "Move" in den Explorer (also einen anderen Ordner) wäre in meinem Anwendungsfall absolut nicht intuitiv, sondern kontraproduktiv und würde regelmäßig zu "Datenverlust" führen - weil die Dateien plötzlich nicht mehr da sind, so man sie erwarten würde.

himitsu 31. Dez 2021 09:26

AW: Drag&Drop innerhalb eines VirtualTree und in den Explorer
 
Ja, Delphi nutzt intern eine eigene/andere Implementation für das Drag&Drop,
aber es wäre nicht verboten, auch intern das gleiche D&D zu verwenden, wie für den Explorer.

Als Ziel ist es ja kein Problem, einfach Beide D&D einzubauen, also Verschieben und als Ziel für "vom" Explorer oder anderen Programmen (Mail, wobei es ja auch zwei unterschiedliche Varianten des D&D gibt und nicht alle Programme das Gleiche nutzen, wenn man aus ihnen rauskommt ... z.B. Thunderbird/Explorer gegen Outlook ... und auch nicht alle Ziele werden von Allen angenommen)


Als Drag&Drop-Source hatte ich es letztens mit "einfach" gemacht,
da es bei und meistens nur intern verschoben wird oder es von Außen rein kommt.

Sollte es doch auch mal raus gehen müssen, da wird dann nicht direkt aus dem Tree gezogen, sondern man Klickt und Zieht auf/aus einen Knopf (oder sonstwas Anderem), wo dann das aktuell Selektierte mitgenommen wird.

Gausi 31. Dez 2021 13:26

AW: Drag&Drop innerhalb eines VirtualTree und in den Explorer
 
Zitat:

Zitat von himitsu (Beitrag 1499891)
Sollte es doch auch mal raus gehen müssen, da wird dann nicht direkt aus dem Tree gezogen, sondern man Klickt und Zieht auf/aus einen Knopf (oder sonstwas Anderem), wo dann das aktuell Selektierte mitgenommen wird.

Ok, das geht ja in die Richtung, die ich auch schon angedacht habe. Nur wäre das bei mir kein eigenes GUI-Element, sondern als "hidden Feature" die Ctrl-Taste als Modifier für diese Aktion. Ich denke, ich bleibe dann bei dieser Grundrichtung. D.h. primär geht D&D nur intern, und nach extern muss der User "extra aktivieren". :)

Nach draußen ist D&D eh kein so großes Ding, Copy&Paste per Ctrl+C/Ctrl+V ist ja auch noch implementiert (und über das Kontextmenü ersichtlich). Vom Explorer rein ging bis jetzt über ein globales
Delphi-Quellcode:
DragAcceptFiles(Form.Handle, true)
und
Delphi-Quellcode:
DragQueryFile
bei
Delphi-Quellcode:
WM_DROPFILES
. Aber das baue ich auch grade etwas um, da die Aktion beim Drop jetzt davon abhängen kann, auf welchen Knoten im TreeView die Files von außen gedroppt werden.

himitsu 31. Dez 2021 20:19

AW: Drag&Drop innerhalb eines VirtualTree und in den Explorer
 
Strg und Shift hatte ich nach Außen halt schon belegt.

Außerdem merken sich Benutzer eh nie etwas und es ist besser, wenn sie einen sichtbaren Ausgangspunkt mit Hint haben. :angle2: (eigene Erfahrung)


Für Copy, Move oder Link ... genauso wie es der Explorer macht.
Aber auch hier war nun aufgefallen, dass es irgendwie garnicht so bekannt ist, das Standardverhalten des Exploreres ... war also garnicht nötig, das im eigenen Programm zu implementieren. :roll:


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:00 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz