Seite 1 von 2

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

Verfasst: 15.01.2007 21:34
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

Verfasst: 15.01.2007 21:44
von Vallan
Cool das hab ich schon öfter gesucht.

Verfasst: 15.01.2007 21:58
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:

Verfasst: 15.01.2007 22:18
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

Verfasst: 16.01.2007 21:32
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:

Verfasst: 16.01.2007 21:45
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

Verfasst: 16.01.2007 22:03
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

Verfasst: 16.01.2007 22:05
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:

Verfasst: 16.01.2007 22:19
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)

Verfasst: 18.01.2007 02:33
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.