Drag&Drop »»» auch für Anfänger geeignet (mit Anleitung)

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Drag&Drop »»» auch für Anfänger geeignet (mit Anleitung)

Beitrag von AND51 »

Hallo!

Habe in mein Programm eine Drag&Drop Funktion eingebaut, die ich auch nicht vorenthalten möchte. Das Besondere: Ich habe den Code gut dokumentiert, man könnte sagen, an den Kommentierungen habe ich länger gesessen, als an dem Code. :lol:
Das Tolle daran: Es funktioniert sogar (Tests erfolgreich). :mrgreen:


Außerdem habe ich die Prozedur so einfach gehalten, dass man als Parameter nur eine selbst definierte LinkedList des Typs "String" übergeben muss; der Rückgabewert ist die Anzahl tatsächlich gedroppter Dateien.


Benutzung:
  • 1. Schritt:
    Definiere eine LinkedList vom Typ String und mach dein Fenster Drag&Drop fähig, das geht so:

    Code: Alles auswählen

    NewList GedroppteDateien.s()
    
    DragAcceptFiles_(WindowID(#Mein_Fenster), #True)
    Dies kannst du jederzeit wiederrufen, indem du '#False' einsetzt. Dann kann man keine Dateien mehr auf dein Fenster ziehen. Du kannst dies so oft tun, wie du möchtest.

  • 2. Schritt:
    Reagiere auf die Nachricht '#WM_DROPFILES'. Wenn WindowEvent() oder WaitWindowEvent() die Nachricht '#WM_DROPFILES' zurückgibt, musst du die Procedure aufrufen, die ich unten gepostet habe. Übergebe dieser Prozedur die LinkedList, die du definiert hast! Die Prozedur übernimmt dann alle weitere Arbeit.

    Code: Alles auswählen

    Repeat
         If WaitWindowEvent() = #WM_DROPFILES
              getDroppedFiles(GedroppteDateien())
         EndIf
    ForEver
  • 3. Schritt:
    Freuen! Denn nun enthält deine LinkedList alle Dateien, die auf den Fenster gezogen wurden. Diese LinkedList kannst du beispielsweise mit ForEach/Next durchblättern und debuggen. Die Procedure, die ich unten poste, gibt übrigens auch die Anzahl gedroppter Dateien zurück, falls benötigt.
So, und hier kommt noch die Prozedur selbst:

Code: Alles auswählen

Procedure.l getDroppedFiles(List.s())
	ClearList(List()) ; delete old files
	Protected *hDrop=EventwParam() ; get drop-handle
	Protected numDrop=DragQueryFile_(*hDrop, $FFFFFFFF, 0, 0) ; get amount of dropped files
	Protected n, filenameLen, buffer$
	For n=0 To numDrop-1
		filenameLen=DragQueryFile_(*hDrop, n, 0, 0) ; get length of the current file name
		If filenameLen
			buffer$=Space(filenameLen+1) ; prepare needed buffer (manually calculate terminating null!)
			DragQueryFile_(*hDrop, n, @buffer$, filenameLen+1) ; transfer current filename into buffer
			AddElement(List()) ; transfer filename from buffer to linked list
				List()=buffer$
		EndIf
	Next
	DragFinish_(*hDrop) ; release memory used by the drag&drop function
	ProcedureReturn CountList(List()) ; return amount of files dropped
EndProcedure
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
Vallan
Beiträge: 223
Registriert: 20.01.2006 19:34
Kontaktdaten:

Beitrag von Vallan »

Cool das hab ich schon öfter gesucht.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Vallan hat geschrieben:Cool das hab ich schon öfter gesucht.
Entsprechenden Code gibts seid Jahren im CodeArchiv. Nicht so schön wie
AND51 sein Beispiel, aber enthält alles, was da zu Wissen ist.

PS: PB 4.1 soll richtiges Drag & Drop unterstützen, also auch für Gadgets usw.
Hoffentlich wirds auch umgesetzt :wink:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

> Entsprechenden Code gibts seid Jahren im CodeArchiv. Nicht so schön wie AND51 sein Beispiel, aber enthält alles, was da zu Wissen ist.
Stimmt. Aber ich möchte manchmal das selbst programmieren, damit ich's auch mal selbst lerne.
In diesem konkreten dachte ich: "Warum nicht mit der Community teilen?"

Im Übrigen habe ich noch nie einen Code gesehen, der wirklich so einfach ist, wie meine: Man muss ja nur eine LinkedList übergeben, die gefüllt wird. :)

> PB 4.1 soll richtiges Drag & Drop unterstützen, also auch für Gadgets usw.
Ich hoffe es sehr und bin dafür! :D
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
al90
Beiträge: 1103
Registriert: 06.01.2005 23:15
Kontaktdaten:

Beitrag von al90 »

Sieht vielversprechend aus. :allright:

Mal ne frage: Klappt damit auch das kopieren von einem ListIconGadget
zum anderen? Habs jetzt nicht probiert da ich keine LinkedLists, sondern
Arrays benutze. Sonst müsste ich es umschreiben. Wäre aber schonmal
ein guter ansatz für die v1.1 zu P.F.M. :wink:
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Ich habe es getestet und statt der WindowID eine GadgetID (vom ListIconGadget) eingetragen, weil ich es lieber für ein ListIcon hätte, aber es klappt leider nicht... :|

Ich habe den Code selbst aus dem englischen Forum als Vorlage genommen und mit einigem API-Gewälze habe ich diese einfache Procedure draus gestrickt.

Wenn du es nehmen möchtest, bitte! Du darfst es auch umschreiben, genau wie den byterechner und die Tausendertrennzeichen. Kannst alles machen, was du willst, brauchst auch keine Lizenzgebühren abdrücken :lol: oder mich mit in die About-Box setzen (obwohl das schon schön wäre *träum*). :)

@ Tausendertrennzeichen: Hier gibt es eine API-Funktion. Habe ich schon erfolgreich getestet, das englische Forum hat's auch ganz schon drauf! http://www.purebasic.fr/english/viewtopic.php?t=25401

@ Drag&Drop: Habe gefragt, ob das mit einem speziellen Gadget geht. Habe den Link extra für dich rausgesucht und gerade gesehen, dass es eine Antwort von "srod" gibt: http://www.purebasic.fr/english/viewtop ... ht=#177695
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

AND51 hat geschrieben:Ich habe es getestet und statt der WindowID eine GadgetID (vom ListIconGadget) eingetragen, weil ich es lieber für ein ListIcon hätte, aber es klappt leider nicht... :|
Komisch, bei mir klappts :D
Hier ist drop für Grid (verbessertes ListIconGadget) in Verwendung:
http://www.purebasic.fr/german/viewtopic.php?t=11602
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
al90
Beiträge: 1103
Registriert: 06.01.2005 23:15
Kontaktdaten:

Beitrag von al90 »

AND51 hat geschrieben:Ich habe es getestet und statt der WindowID eine GadgetID (vom ListIconGadget) eingetragen, weil ich es lieber für ein ListIcon hätte, aber es klappt leider nicht... :|
Das ist schade. :(
Aber um ehrlich zu sein, hatte ich schon fast mit problemen gerechnet.
Vor einiger zeit wollte ich sowas mal in PBSC einbauen. (D&D vom Desktop in StrgGadgets)
Klappte soweit auch ganz gut. Das problem war halt nur das ich nicht
abfragen konnte in welchem Gadget es geDropt wurde. :roll:
machen, was du willst, brauchst auch keine Lizenzgebühren abdrücken :lol:
Ich kann Dir eine Freeversion des PFM anbieten. :mrgreen:
oder mich mit in die About-Box setzen (obwohl das schon schön wäre *träum*). :)
Wäre es in DOCs auch akzeptabel für dich ? Die AboutBox wollte ich
eigentlich nicht mehr weiter auffüllen. :wink:
@ Tausendertrennzeichen: Hier gibt es eine API-Funktion. Habe ich schon erfolgreich getestet, das englische Forum hat's auch ganz schon drauf! http://www.purebasic.fr/english/viewtopic.php?t=25401
Interessannt. Im moment brauche ich aber nichts weiter in dieser richtung
da ich eine eigene Proc dazu gemacht habe.
@ Drag&Drop: Habe gefragt, ob das mit einem speziellen Gadget geht. Habe den Link extra für dich rausgesucht und gerade gesehen, dass es eine Antwort von "srod" gibt: http://www.purebasic.fr/english/viewtop ... ht=#177695
Sehr entgegenkommend. Besten Dank! :allright:
Werd ich gleich mal vorbeischauen. Muss nur noch schnell testen ob mein
E-Übersetzer noch läuft. :mrgreen:
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Code: Alles auswählen

Procedure OpenWindow_Window_0()
  If OpenWindow(0, 585, 213, 283, 234, "#Window_0", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_TitleBar)
    If CreateGadgetList(WindowID(0))
      ListIconGadget(0, 15, 10, 255, 210, "Gadget_0", 100, #PB_ListIcon_AlwaysShowSelection|#PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect)
    EndIf
  EndIf
EndProcedure

OpenWindow_Window_0()
DragAcceptFiles_(GadgetID(0), 1)

Define.l Buffer = AllocateMemory(1000)
Define *DropHandle

Repeat
  Event = WaitWindowEvent()
  Select Event
  
    Case #WM_DROPFILES
      *DropHandle = EventwParam()
      If *DropHandle
        DragQueryFile_(*DropHandle, 0, Buffer, 1000)
        DragFinish_(*DropHandle)
        Debug PeekS(Buffer)
      EndIf
      
      
    Case #PB_Event_Gadget
      EventGadget = EventGadget()
      EventType = EventType()
      If EventGadget = 0
      EndIf

    Case #PB_Event_CloseWindow
      EventWindow = EventWindow()
      If EventWindow = 0
        Break
      EndIf
  EndSelect
ForEver

FreeMemory(Buffer)
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Arachnophobia
Beiträge: 57
Registriert: 03.02.2005 05:57
Wohnort: Berlin
Kontaktdaten:

Beitrag von Arachnophobia »

Es kann hier in der Tat Probleme geben.
Ich habe lange an einem vergleichbaen Fehler in meinem eigenen Code gesucht bis mir aufgefallen ist, dass wenn sich z.B. ein für Drag & Drop vorgesehenes ListIconGadget innerhalb eines FrameGadgets befindet die Message den Empfänger nicht erreicht.
Abhilfe schafft in diesem Zusammenhang z.B. mit SetParent_() das FrameGadget als Parent des ListIconGadget zu setzen.
Antworten