|
Es ist ja schön und gut, dass Sie in einem
ListView-Steuerelement im Report-Modus mehrere Spalten (ListSubItems)
einfügen können. Weniger gut und schön ist, dass Sie keine
Informationen darüber erhalten, ob ein ListSubItem angeklickt wird.
Genau so wenig werden Sie darüber informiert, ob das Icon bzw.
ReportIcon oder der Text eines ListItems bzw. eines ListSubItems
angeklickt wird. Die HitTest-Funktion des ListView-Steuerelements
liefert nur unvollständige Informationen.
Das API hat da schon mehr an Informationen zu bieten - Sie
brauchen sie nur noch auszuwerten. Das heißt, Sie können sich das
sparen, denn die hier vorgestellte Funktion ListItemHitTest erledigt
das für Sie.
Sie übergeben der Funktion im ersten Parameter das betreffende
ListView-Steuerelement und im zweiten und dritten Parameter die X-
und Y-Koordinaten, die Sie etwa in den Mouse-Ereignissen des
ListView-Steuerelements übermittelt bekommen. Im letzten optionalen
Parameter können Sie noch festlegen, ob ein gefundenes ListItem
automatisch selektiert werden soll.
Konnte anhand der Koordinaten die Zeile eines ListItems ermittelt
werden, wird es im Parameter ListItem zurückgegeben. Befindet sich
sogar ein ListSubItem unter den Koordinaten, wird dieses im
Parameter ListSubItem zurückgegeben. Im Parameter Part erhalten Sie
die Information darüber, welcher Teil eines ListItems bzw.
ListSubItems getroffen wurde: Text, Icon, CheckBox oder WhiteSpace
(letzteres bezeichnet den leeren Bereich einer Zeile jenseits der
letzten Spalte).
Der Rückgabewert der Funktion lautet lhsNone, wenn kein ListItem
ermittelt werden konnte (Koordinaten unterhalb der untersten Zeile
bzw. keine ListItems vorhanden). Er lautet lhsListItem, wenn der
Treffer in der Spalte des ListItems selbst liegt. Wird ein
ListSubItem getroffen, lautet der Rückgabewert lhsListSubItem.
Selbst wenn die Spalten vom Anwender umsortiert werden
(Eigenschaft AllowColumnReorder des ListView-Steuerelements gleich
True), gibt die Funktion die richtigen ListSubItems zurück. Sie ist
auch unabhängig von den Einstellungen der Eigenschaften CheckBoxes
und FullRowSelect.
Private Const LVM_FIRST As Long = &H1000
Private Const LVM_SUBITEMHITTEST As Long = (LVM_FIRST + 57)
Private Const LVM_GETITEMRECT = (LVM_FIRST + 14)
Private Const LVHT_ONITEMICON As Long = &H2
Private Const LVHT_ONITEMLABEL As Long = &H4
Private Const LVHT_ONITEMSTATEICON As Long = &H8
Private Const LVHT_ONITEM As Long = _
(LVHT_ONITEMICON Or LVHT_ONITEMLABEL Or LVHT_ONITEMSTATEICON)
Private Const LVIR_BOUNDS = 0
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Type LVHITTESTINFO
pt As POINTAPI
Flags As Long
Item As Long
SubItem As Long
End Type
Private Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, lParam As Any) As Long
Public Enum ListItemHitTestSuccessConstants
lhsNone
lhsListItem
lhsListSubItem
End Enum
Public Enum ListItemHitTestPartConstants
lhpNone
lhpText
lhpIcon
lhpCheckBox
lhpWhiteSpace
End Enum
Public Function ListItemHitTest(ListView As ListView, _
ByVal X As Single, ByVal Y As Single, ListItem As ListItem, _
ListSubItem As ListSubItem, Part As ListItemHitTestPartConstants, _
Optional ByVal SelectListItem As Boolean) _
As ListItemHitTestSuccessConstants
Dim nHITTESTINFO As LVHITTESTINFO
Dim nListItem As ListItem
Dim l As Long
Dim nRect As RECT
Set ListItem = Nothing
Set ListSubItem = Nothing
Part = lhpNone
With ListView
If .View <> lvwReport Then
Exit Function
End If
If .ListItems.Count = 0 Then
Exit Function
End If
With nHITTESTINFO
.pt.X = (X \ Screen.TwipsPerPixelX)
.pt.Y = (Y \ Screen.TwipsPerPixelY)
.Flags = LVHT_ONITEM
End With
SendMessage .hwnd, LVM_SUBITEMHITTEST, 0, nHITTESTINFO
End With
Select Case nHITTESTINFO.Item
Case Is > -1
Set nListItem = ListView.ListItems(nHITTESTINFO.Item + 1)
Case Else
With ListView
For l = .GetFirstVisible.Index To .ListItems.Count
Set nListItem = .ListItems(l)
With nListItem
Select Case Y
Case .Top To .Top + .Height
Exit For
Case Else
Set nListItem = Nothing
End Select
End With
Next 'l
End With
If nListItem Is Nothing Then
Exit Function
Else
nRect.Left = LVIR_BOUNDS
SendMessage ListView.hwnd, LVM_GETITEMRECT, _
nListItem.Index - 1, nRect
Select Case X \ Screen.TwipsPerPixelX
Case nRect.Left To nRect.Right
Part = lhpText
Case Else
Part = lhpWhiteSpace
End Select
End If
End Select
If nHITTESTINFO.SubItem > 0 Then
Set ListSubItem = nListItem.ListSubItems(nHITTESTINFO.SubItem)
ListItemHitTest = lhsListSubItem
Else
ListItemHitTest = lhsListItem
End If
Select Case nHITTESTINFO.Flags
Case LVHT_ONITEMSTATEICON
Part = lhpCheckBox
Case LVHT_ONITEMICON
If ListSubItem Is Nothing Then
Part = lhpIcon
Else
If Len(ListSubItem.ReportIcon) Then
Part = lhpIcon
Else
Part = lhpText
End If
End If
Case LVHT_ONITEMLABEL
Part = lhpText
End Select
If SelectListItem Then
nListItem.Selected = True
End If
Set ListItem = nListItem
End Function
|