RSS
StartseiteKnowledge LibraryTop 10Impressum

Listentreffer

Feststellen, welcher Listeneintrag sich an einer bestimmten Position befindet

Das ListView Steuerelement verfügt über eine praktische HitTest-Methode, mit der man ermitteln kann, ob und welcher Eintrag sich an einer bestimmten Position befindet. Für die ListBox, FileListBox und DirListBox kann man so eine Funktion ebenfalls haben...

Das ListView Steuerelement aus den Windows Common Controls verfügt über eine HitTest-Methode, die ein ListItem zurückgibt, das sich unter den angegebenen Koordinaten befindet.

Für die Standard ListBox wird eine solche Methode nicht angeboten. Aber Sie würden diesen Artikel nicht lesen, wenn es nicht doch eine Möglichkeit gäbe, eine solche HitTest Funktion der Standard ListBox zur Seite zu stellen.

Kern dieser Funktion ist die API Funktion LBItemFromPt. Diese erwartet den Handle des ListBox Steuerelements und die X und Y Koordinaten relativ zu den Bildschirmkoordinaten. Also, müssen zu den Client-Koordinaten, die man bei den MouseDown, MouseMove und MouseUp-Ereignissen erhält, über die API Funktion ClientToScreen die Bildschirmkoordinaten ermittelt werden. Als Ergebnis der LBItemFromPt-Funktion erhält man den Index des Listeneintrags an der angegebenen Position bzw. -1, wenn sich an dieser Stelle kein Eintrag befindet.

Diese Funktion lässt sich auch ohne weiteres für die FileListBox verwenden, da diese auf der ListBox basiert, wie auch die DirListBox. Bei der DirListBox muss man sich aber zunächst einmal den Index, den man über die LBItemFromPt-Funktion erhält, zurecht biegen. Denn dieser ist weiterhin 0 basiert, während bei dem DirListBox Steuerelement Verzeichnisse des aktuellen Pfades positive Indizes erhalten, begonnen bei 0 und die übergeordneten Verzeichnisse negative Indizes, -1 für das aktuell angezeigte Verzeichnis.

Der Versatz, der sich dadurch zwischen API Index und eigentlichem Index ergibt, lässt sich durch Zählung der im Pfad vorkommenden Backslashes ermitteln. Da –1 als Kennzeichen für keinen Treffer wegfällt, wird statt dessen die Gesamtzahl der Einträge zurück gegeben, die durch die ListCount-Eigenschaft ermittelt wird.

Die Funktion ListHitTest kapselt diese Aufgaben und liefert immer den getroffenen Index zurück oder -1, wenn kein Eintrag unter den angegebenen Koordinaten zu finden ist, beziehungsweise den Wert der ListCount-Eigenschaft, wenn man diese Funktion zusammen mit einer DirListBox verwendet.

Private Type POINTAPI
  X  As Long
  Y  As Long
End Type

Private Declare Function ClientToScreen Lib "user32" ( _
        ByVal hWnd As Long, _
        ByRef lpPoint As POINTAPI _
              ) As Long
Private Declare Function LBItemFromPt Lib "comctl32" ( _
        ByVal hLB As Long, _
        ByVal X As Long, ByVal Y As Long, _
        ByVal bAutoScroll As Boolean _
              ) As Long

Public Function ListHitTest(ByRef ListBox As Object, _
                            ByVal X As Single, _
                            ByVal Y As Single) As Long
  Dim lPT     As POINTAPI
  Dim lPos    As Integer
  Dim lOffset As Integer
  Dim lPath   As String
  
  Select Case True
    Case TypeOf ListBox Is ListBox, _
         TypeOf ListBox Is FileListBox, _
         TypeOf ListBox Is DirListBox
    Case Else
      Exit Function
  End Select
  
  If (TypeOf ListBox Is DirListBox) Then
    If (Left$(ListBox.Path, 2) = "\\") Then
      lPath = ListBox.Path
      lPos = InStr(3, lPath, "\")
    Else
      lPath = IIf(Right$(ListBox.Path, 1) <> "\", _
                  ListBox.Path & "\", _
                  ListBox.Path)
      lPos = 3
    End If
  
    Do Until (lPos = 0)
      lOffset = lOffset + 1
      lPos = InStr(lPos + 1, lPath, "\")
    Loop
  End If

  With Screen
    lPT.X = X \ .TwipsPerPixelX
    lPT.Y = Y \ .TwipsPerPixelY
  End With
  
  ClientToScreen ListBox.hWnd, lPT
  
  ListHitTest = LBItemFromPt(ListBox.hWnd, lPT.X, lPT.Y, False)
  
  If (TypeOf ListBox Is DirListBox) Then
    If (ListHitTest = -1) Then
      ListHitTest = ListBox.ListCount
    Else
      ListHitTest = ListHitTest - lOffset
    End If
  End If
End Function