Buchempfehlung
Mikrocomputertechnik mit Controllern der Atmel AVR-RISC-Familie
Mikrocomputertechnik mit Controllern der Atmel AVR-RISC-Familie
Umfassend, aber leicht verständlich führt dieses Buch in die Programmierung von ATMEL AVR Mikrocontrollern ein. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Tutorial

Windows Drag und Drop Tutorial

von MitgliedstephanbrunkerSeite 5 von 12

Der Code für IDropTarget

Nachdem wir jetzt das Interface haben, müssen wir das nur noch in unser Programm einbauen. Wenn wir jetzt für IUnknown, IDataObject und IDropTarget jeweils eigene Dateien erzeugen, sehen die Includes so aus:

#Include "windows.bi"
#Include "win\commctrl.bi"
#Include "win\shellapi.bi"
#Include "win\commdlg.bi"
#Include "vbcompat.bi"
#Include "win\ole2.bi"
#Include "win\shlobj.bi"
#Include "win\winbase.bi"
#Include "windows-fix.bi"

#Undef RegisterDragDrop
#Include "IUnknown.bas"
#Include "IDataObject.bas"
#Include "IDropTarget.bas"
Declare Function RegisterDragDrop Alias "RegisterDragDrop" (ByVal As HWND, ByVal As IDropTarget Ptr ) As HRESULT

'Include our own *.bi
#Include "Dialog.bi"

Wir müssen zuerst einmal die *.bi für OLE und ein paar andere Sachen laden. Da für die Interfaces eine vordefinierte Implementation vorhanden ist, wurden diese mit #Undef freigegeben. Weil sich die Datentypen damit ändern, definiert man RegisterDragDrop am besten auch noch mal neu, sonst meckert der Compiler, da der IDropTarget Ptr von vor der Neudefinition ein anderer ist als der danach. Ob wir das vorne bei den includes haben oder direkt vor und nach den neuen Typen in den jeweiligen Dateien, ist Geschmackssache. pDropTarget kommt als shared in unsere *.bi.

Beim Programmstart kommen dann folgende Anweisungen dazu:

OleInitialize(NULL)

...

'DragDrop: Formats to accept and create the interface for it
Dim fmtetc (0 To 0) As FORMATETC
With fmtetc(0)
            .cfFormat   = CF_HDROP
            .tymed      = TYMED_HGLOBAL
            .dwAspect   = DVASPECT_CONTENT
            .ptd        = NULL
            .lindex     = -1
End With
pDropTarget = New IDROPTARGET(hLSV1,fmtetc() )

'tell OLE that the Listview is a drop target and associate a interface
RegisterDragDrop(hLSV1, pDropTarget)

OLE will in dem Fall zuerst initialisiert werden, dann legen wir das Format fest, dass wir als Drop akzeptieren wollen und erzeugen das Interface mit NEW als Pointer, den wir dann mit RegisterDragDrop an OLE übergeben. Das müssen wir natürlich am Programmende alles wieder freigeben. Das Interface löscht sich selbst, wenn wir unsere eigene Referenz freigeben und es bei OLE deregistrieren:

RevokeDragDrop(hLSV1)
pDropTarget->Release()
OleUninitialize()

Bleibt dann nur noch die DataDrop-Funktion, die wir aus dem Interface heraus aufgerufen haben.

Function DataDrop (ByVal hWin As HWND, ByVal pfmtetc As FORMATETC Ptr, ByVal pstgmed As STGMEDIUM Ptr) As Integer

    Select Case hWin
        Case hLSV1
        'drop on our Listview
                Select Case pfmtetc->cfFormat
                    Case CF_HDROP
                        'get the HDROP handle:
                        Dim dropfiles As HDROP = GlobalLock(pstgmed->hGlobal)
                        Dim tempstring As ZString * MAX_PATH
                        Dim As String filepath,filetitle
                        Dim As Integer index,i,j
                        'get number of files dropped
                        index = DragQueryFile(dropfiles,-1,@tempstring,SizeOf(tempstring))
                        'get file and break it up into Path and Filename
                        For i=0 To index-1
                            DragQueryFile(dropfiles,i,@tempstring,SizeOf(tempstring))
                            filepath=Left(tempstring,InStrRev(tempstring,"\"))
                            filetitle=LTrim(tempstring,filepath)
                            AddListViewRow(hLSV1,filepath,filetitle,hLarge1,hSmall1)
                        Next i
                        'Unlock the Global Memory:
                        GlobalUnlock(pstgmed->hGlobal)

                    Case Else
                        'if we accept other formats ...
                        'implement here
                End Select

    End Select
    Return TRUE
End Function

Die Funktion ist aber ziemlich analog dessen, was wir bei der WM_DROPFILES Message schon hatten. Wenn wir am Anfang mehrere Formate freigegeben haben, müssen wir die natürlich auch im Drop auswerten. An der ganzen Vorgehensweise ist nichts außergewöhnlich, außer dass vielleicht alles über GLOBAL Memory läuft, was bedeutet, das wir den erhaltenen Pointer mit GlobalLock reservieren müssen und nach Gebrauch wieder freigeben. Um zu zeigen, wie man mehrere verschiedene Drops akzeptieren kann und das CF_TEXT-Format vorzustellen, gibt es eine zweite Version des Codes mit einer zusätzlichen Editbox, die CF_TEXT akzeptiert. Da dieses Format einen Null-terminierten Pointer ins GlobalMemory stellt, kann man den direkt für SetWindowText verwenden.

Die zwei Varianten des Programms:
Externer Link!DragDrop2.zip
Externer Link!DragDrop2a.zip

Und wenn wir jetzt nicht nur Drops akzeptieren wollen, sondern selbst die Quelle sein wollen? Dazu müssen wir uns gleich drei zusätzliche Interfaces ansehen: IDropSource, IDataObject und IEnumFormatEtc .

 

Gehe zu Seite Gehe zu Seite  1  2  3  4  5  6  7  8  9  10  11  12  
Zusätzliche Informationen und Funktionen
  Bearbeiten Bearbeiten  

  Versionen Versionen