Das ListView-Controls aus den Microsoft Common Controls eignet sich hervorragend um ungebundene Listen darzustellen. Leider verfügt das Control nur bedingt über die Möglichkeit, den Text einer Zelle zu editieren. Es kann lediglich eine Zelle in der ersten Spalte editiert werden. Doch was ist mit den übrigen Zellen? Geht nicht! Falsch, es geht doch... Dazu folgende Überlegung: Wir benötigen als erstes eine Möglichkeit festzustellen, in welche Zelle der Anwender mit der Mouse geklickt hat. Doch wie kommen wir an diese Information? Die durch das ListView zur Verfügung gestellten Eigenschaften und Ereignisse liefern uns das leider nicht. Also greifen wir wieder in die API Trickkiste. Über die SendMessage API-Funktion rufen wir den "HitTest" des Controls ab. So erhalten wir nicht nur die Mousekoordinaten, sondern auch noch direkt die Indizes für das Item und SubItem - also die Zelle unter der Mouse und somit auch den Text in der Zelle. Jetzt ist es ein leichtes den Text zu editieren Doch wie setzen wir das jetzt um? Wir benötigen dafür ein Ereignis und somit ein Klassenmodul. Das Klassenmodul kapselt das übergebene ListView, ermittelt die Zelle unter der Mouse und erzeugt das Ereignis. Die Klasse "clsLvwCellClick" Erstellen Sie ein neues Projekt und legen ein leeres Klassenmodul an. Benennen Sie die Klasse "clsLvwCellClick". Fügen Sie den folgenden Code in das Klassenmodul ein. ' **************************************************************** ' * ' * clsLvwCellClick - VB6 Klassenmodul ' * ' * Das Klassenmodul kapselt ein ListView und wertet über ' * die SendMessage API den HitTest aus. Dabei wird die ' * aktuelle Zelle unter der Mouse ermittelt. ' * ' * Eigenschaft: oListView - übergeben wird das ListView ' * aus der aufrufenden Form. ' * ' * Ereignis: CellClick - zurückgegeben wird der ButtonStatus, ' * die Zeile, die Spalte, der EditModus und ' * der CellText an die Form. ' * ' * Im Ereignis der Form kann der CellText editiert und wieder ' * an die Klasse zurückgegeben werden. Der editierte Text ' * wird dann in das ListView an die ursprüngliche Position ' * eingetragen. ' * ' * Mai 2004, www.vb-power.net und Roland Wutzke ' * ' **************************************************************** Option Explicit ' benötigte API-Deklarationen 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 ' ListView Konstanten Private Const LVM_FIRST As Long = &H1000 Private Const LVM_SUBITEMHITTEST As Long = (LVM_FIRST + 57) Private Const LVHT_ONITEM As Long = &HE ' Type Info´s Private Type POINTAPI x As Long y As Long End Type Private Type lvwInfo pApi As POINTAPI Flags As Long lItem As Long lSubItem As Long End Type ' KlassenVars Private WithEvents cListView As ListView ' Ereignis Public Event CellClick(ByVal ButtonState As Integer, _ ByVal Row As Long, ByVal Col As Long, _ EditMode As Boolean, CellText As String) ' Eigenschaften der Klasse Public Property Set oListView(ByVal vData As ListView) Set cListView = vData End Property ' -------------------------------------------------------------- ' Hauptroutine - hier wird im MouseDown Ereignis des übergebenen ' ListView Controls der Klick mit der Mouse registriert und ' verarbeitet. Dabei wird über die SendMessage API der HitTest ' des Controls abgerufen und in pLVWInfo gespeichert. Der Vorteil ' dieser Methode ist, dass zusätzlich noch die Item- und SubItem ' Indizes zurückgegeben werden. Diese werden über das Ereignis ' CellClick Row und Col an die aufrufende Form übergeben. Hierbei ' ist zu beachten, dass für Row der Index+1 erhöht wurde, damit ' Row bei 1 zu zählen beginnt. Für Col ist zu beachten, dass ' Col(1) die Spalte mit dem Item und alle weiteren Spalten Col(2-n) ' die SubItems enthalten. Mit CellText wird der Text unter der ' Mouse übergeben. Dieser kann in der aufrufenden Form editiert ' und wieder an die Klasse zurückgegeben werden. Der String wird ' anschließend in der Klasse in das ListView eingetragen. ' Gesteuert wird das über die BooleanVar EditMode, die den ' Wert=True haben muss, um den Text einzutragen. ' -------------------------------------------------------------- Private Sub cListView_MouseDown(Button As Integer, _ Shift As Integer, x As Single, y As Single) Dim pLVWInfo As lvwInfo Dim tmpX As Long Dim tmpY As Long Dim pEditMode As Boolean Dim tmpText As String ' LVWInfo vorbesetzen With pLVWInfo .pApi.x = x \ Screen.TwipsPerPixelX .pApi.y = y \ Screen.TwipsPerPixelY .Flags = LVHT_ONITEM End With ' LVWInfo über den HitTest des Listviews ermitteln Call SendMessage(cListView.hwnd, LVM_SUBITEMHITTEST, 0, pLVWInfo) ' LVWInfo auswerten With pLVWInfo ' wurde auf ein Item geklickt? If .lSubItem = 0 Then If .lItem > -1 Then ' Eigenschaften vorbesetzen tmpX = .lItem + 1 tmpY = 1 pEditMode = False tmpText = cListView.ListItems(tmpX).Text cListView.ListItems(tmpX).Selected = True ' Ereignis auslösen RaiseEvent CellClick(Button, tmpX, tmpY, pEditMode, tmpText) ' wurde ein neuer CellText zurückgegeben? If pEditMode Then cListView.ListItems(tmpX).Text = tmpText cListView.Refresh DoEvents End If End If ' wurde auf ein SubItem geklickt? ElseIf .lSubItem > 0 Then If .lItem > -1 Then ' Eigenschaften vorbesetzen tmpX = .lItem + 1 tmpY = .lSubItem pEditMode = False tmpText = cListView.ListItems(tmpX).SubItems(tmpY) cListView.ListItems(tmpX).Selected = True ' Ereignis auslösen RaiseEvent CellClick(Button, tmpX, tmpY + 1, pEditMode, tmpText) ' wurde ein neuer CellText zurückgegeben? If pEditMode Then cListView.ListItems(tmpX).SubItems(tmpY) = tmpText cListView.Refresh DoEvents End If End If End If End With End Sub ' Klasse terminieren Private Sub Class_Terminate() If Not cListView Is Nothing Then Set cListView = Nothing End If End Sub Wie wird nun die Klasse genutzt und vor allen Dingen, wie wird der CellText editiert? Alles das demonstriert Ihnen eindrucksvoll unser Beispielprojekt, das es hier zum downloaden gibt. Viel Spaß... |