|
Vom Windows Explorer her kennen Sie es bestimmt, dass bei Drag&Drop-Operationen das gerade mit dem Mauszeiger überfahrene Element vorübergehend markiert wird. Sowohl das TreeView- als auch das ListView-Steuerelement aus den Microsoft Common Controls bieten dieses Feature von Hause aus an - über die Eigenschaft DropHighlight. Dieser Eigenschaft wird der Knoten (Node) oder das Listenelement (ListItem) zugewiesen, das gerade überfahren wird.
Beide Steuerelemente bieten mit HitTest auch die entsprechende auch Methode zum Ermitteln des gerade überfahrenen Element an. Sie übergeben der HitTest-Methode die aktuellen Koordinaten X und Y und erhalten das entsprechende Element als Rückgabewert. Wurde an den angegebenen Koordinaten kein Element gefunden, wird Nothing zurückgegeben. Weisen Sie nun die Rückgabe der Eigenschaft DropHighlight zu, haben Sie die Aufgabe schon im wesentlichen gelöst. Sowohl beim TreeeView als auch beim ListView wie auch bei den OLEDragOver-Ereignissen beider Steuerelemente könnte das so aussehen:
Private Sub TreeView1_DragOver(Source As Control, X As Single, _
Y As Single, State As Integer)
With TreeView1
Set .DropHighlight = .HitTest(X, Y)
End With
End Sub
Das Ergebnis ist schon ganz passabel: Das überfahrene Element wird markiert, und die Markierung wird gelöscht, wenn leerer Raum innerhalb des TreeViews oder ListViews überstrichen wird. So ganz befriedigend ist das allerdings noch nicht. Denn falls der Mauszeiger wieder aus dem Steuerelement herausgezogen wird, bleibt das zuletzt markierte Element markiert. Glücklicherweise liefern TreeView und ListView in beiden Ereignisvarianten (DragOver und OLEDragOver) im State-Parameter die Information darüber, ob der Mauszeiger gerade in das Steuerelement hinein gefahren worden ist (vbEnter), ob er lediglich innerhalb des Bereichs bewegt worden ist (vbOver), oder ob er gerade hinausgeschoben wird (vbLeave). Wird letztere Information übergeben, ist dies der richtige Zeitpunkt zum Löschen der Markierung, indem Sie der DropHighlight-Eigenschaft ein Nothing zuweisen.
Private Sub TreeView1_DragOver(Source As Control, X As Single, _
Y As Single, State As Integer)
With TreeView1
If State = vbLeave Then
Set .DropHighlight = Nothing
Else
Set .DropHighlight = .HitTest(X, Y)
End If
End With
End Sub
Falls der Mauszeiger jedoch nicht aus dem TreeView oder ListView hinausbewegt worden ist, sondern die Drag-Operation mit dem Ablegen dort beendet wird, muss natürlich die Markierung auch wieder zurückgesetzt werden, indem Sie wieder Nothing der DropHighlight-Eigenschaft zuweisen. Vor dieser Zuweisung sollten Sie allerdings noch schnell den aktuellen Inhalt auslesen und sich so umständliche Ermittlungen des genauen Ablageziels ersparen. Auch dies funktioniert sowohl beim TreeView als auch beim ListView bei den DragDrop- und bei den OLEDragDrop-Ereignissen gleichermaßen:
Private Sub ListView1_OLEDragDrop(Data As MSComctlLib.DataObject, _
Effect As Long, Button As Integer, Shift As Integer, X As Single, _
Y As Single)
Dim TargetListItem As ListItem
With ListView
Set TargetListItem = .DropHighlight
Set .DropHighlight = Nothing
End With
End Sub
Wenn Sie es ganz bequem haben möchten, können Sie die beiden Code-Blöcke auch in allgemeine Prozeduren und Funktionen packen und von den entsprechenden Ereignissen aus aufrufen.
Public Function LvwDragDrop(ListView As ListView) As ListItem
With ListView
Set LvwDragDrop = .DropHighlight
Set .DropHighlight = Nothing
End With
End Function
Public Sub LvwDragOver(ListView As ListView, ByVal X As Single, _
ByVal Y As Single, ByVal State As DragOverConstants)
With ListView
If State = vbLeave Then
Set .DropHighlight = Nothing
Else
Set .DropHighlight = .HitTest(X, Y)
End If
End With
End Sub
Public Function TvwDragDrop(TreeView As TreeView) As Node
With TreeView
Set TvwDragDrop = .DropHighlight
Set .DropHighlight = Nothing
End With
End Function
Public Sub TvwDragOver(TreeView As TreeView, ByVal X As Single, _
ByVal Y As Single, ByVal State As DragOverConstants)
With TreeView
If State = vbLeave Then
Set .DropHighlight = Nothing
Else
Set .DropHighlight = .HitTest(X, Y)
End If
End With
End Sub
|