|
Das ListView-Steuerelement aus den Microsoft Common Controls bietet außer der Sortierung nach eine Spalte keine Möglichkeit, die Reihenfolge der ListItems zu ändern. Zum Verschieben eines ListItems einschließlich seiner ListSubItems müssen Sie es zunächst entfernen und wieder neu einfügen. Allerdings müssten Sie dabei den Inhalt eines ListItems, also die Werte seiner Eigenschaften, in einzelnen Variablen ablegen, da sich ein ListItem nicht als ein gesamtes Datenpaket extrahieren und wieder einfügen lässt. Die gleiche Mühe haben Sie, wenn Sie ein ListItem kopieren oder ausschneiden und wieder einfügen möchten.
Kompakter wird die Angelegenheit, wenn Sie benutzerdefinierte Variablen verwenden, die die Werte der Eigenschaften eines ListItems bzw. von dessen ListSubItems aufnehmen:
Public Type ListSubItemStore
Bold As String
ForeColor As Long
Key As String
ReportIcon As Variant
Tag As Variant
Text As String
ToolTipText As String
End Type
Public Type ListItemStore
Bold As Boolean
Checked As Boolean
ForeColor As Long
Ghosted As Boolean
Icon As Variant
Key As String
ListSubItems() As ListSubItemStore
Selected As Boolean
SmallIcon As Variant
Tag As Variant
Text As String
ToolTipText As String
End Type
Die Hilfsprozedur LvwGetListItemStore verpackt ein ListItem in eine solche benutzerdefinierte Variable. Vor dem Aufruf deklarieren Sie eine Variable dieses Typs und übergeben sie als ersten Parameter. Im zweiten Parameter folgt das betreffende ListView-Steuerelement. Im dritten, optionalen Parameter KeyIndexListItem können Sie den Schlüssel (Key) oder den Index des aufzunehmenden ListItems oder dieses selbst angeben. Lassen sie den Parameter weg, wird das aktuell gewählte ListItem des ListViews (SelectedItem) genommen. Setzen die den nächsten optionalen Parameter Remove auf True, wird das ListItem aus dem ListView auch gleich entfernt. Setzen Sie LockUpdate auf True, wird die Aktualisierung des ListViews unterdrückt, bis die Prozedur abgearbeitet ist. In der Prozedur wird die Ermittlung des gewünschten ListItems von der privaten Funktion zGetListItem erledigt - diese wird von weiter unten folgenden Prozeduren ebenfalls verwendet.
Private Declare Function LockWindowUpdate Lib "user32" _
(ByVal hwndLock As Long) As Long
Public Sub LvwGetListItemStore(ListItemStore As ListItemStore, _
ListView As ListView, Optional KeyIndexListItem As Variant, _
Optional ByVal Remove As Boolean, _
Optional ByVal LockUpdate As Boolean)
Dim nListItem As ListItem
Dim nKeyIsListItem As Boolean
Dim nListSubItem As ListSubItem
Dim i As Integer
With ListView
If LockUpdate Then
LockWindowUpdate .hWnd
End If
With .ListItems
Set nListItem = zGetListItem(ListView, KeyIndexListItem)
If Not (nListItem Is Nothing) Then
With nListItem
ListItemStore.Bold = .Bold
ListItemStore.Checked = .Checked
ListItemStore.ForeColor = .ForeColor
ListItemStore.Ghosted = .Ghosted
ListItemStore.Icon = .Icon
ListItemStore.Key = .Key
ListItemStore.Selected = .Selected
ListItemStore.SmallIcon = .SmallIcon
If IsObject(.Tag) Then
Set ListItemStore.Tag = .Tag
Else
ListItemStore.Tag = .Tag
End If
ListItemStore.Text = .Text
ListItemStore.ToolTipText = .ToolTipText
If .ListSubItems.Count Then
ReDim ListItemStore.ListSubItems(1 To _
.ListSubItems.Count)
For i = 1 To .ListSubItems.Count
With .ListSubItems(i)
ListItemStore.ListSubItems(i).Bold = .Bold
ListItemStore.ListSubItems(i).ForeColor = _
.ForeColor
ListItemStore.ListSubItems(i).Key = .Key
ListItemStore.ListSubItems(i).ReportIcon = _
.ReportIcon
If IsObject(.Tag) Then
Set ListItemStore.ListSubItems(i).Tag = _
.Tag
Else
ListItemStore.ListSubItems(i).Tag = .Tag
End If
ListItemStore.ListSubItems(i).Text = .Text
ListItemStore.ListSubItems(i).ToolTipText = _
.ToolTipText
End With
Next 'i
Else
ReDim ListItemStore.ListSubItems(0)
End If
End With
If Remove Then
.Remove nListItem.Index
End If
End If
End With
End With
If LockUpdate Then
LockWindowUpdate 0&
End If
End Sub
Private Function zGetListItem(ListView As ListView, _
Optional KeyIndexListItem As Variant) As ListItem
With ListView
If IsMissing(KeyIndexListItem) Then
Set zGetListItem = .SelectedItem
ElseIf IsObject(KeyIndexListItem) Then
If TypeOf KeyIndexListItem Is ListItem Then
Set zGetListItem = KeyIndexListItem
End If
Else
On Error Resume Next
Set zGetListItem = .ListItems.Item(KeyIndexListItem)
On Error GoTo 0
End If
End With
End Function
Über die Hilfsprozedur LvwInsertListItemStore fügen Sie ein so extrahiertes ListItem an beliebiger Stelle in einem ListView wieder ein. Sie übergeben zunächst das ListView-Steuerelement und die benutzerdefinierte Variable, die die Daten eines ListItems enthält. Da das gespeicherte ListItem ja nicht unbedingt entfernt worden ist, können sie im dritten optionalen Parameter NewKey einen neuen Schlüssel angeben, um Konflikte zu vermeiden. So können Sie übrigens mit Hilfe dieser beiden Prozeduren ListItems nicht nur verschieben, sondern auch ganz allgemein ausschneiden bzw. kopieren und zu einem beliebigen Zeitpunkt wieder einfügen.
Die Einfügeposition legen Sie in einem der nächsten vier optionalen Parameter fest. Geben Sie keinen dieser vier Parameter an, wird das neue ListItem am Ende der ListItem-Sammlung eingefügt. Setzen Sie schließlich noch IgnoreSelected auf True, wird das eingefügte ListItem nicht ausgewählt, falls das extrahierte ListItem zuvor gewählt gewesen sein sollte.
Public Sub LvwInsertListItemStore(ListView As ListView, _
ListItemStore As ListItemStore, Optional NewKey As String, _
Optional ByVal Before As Variant, _
Optional ByVal After As Variant, _
Optional ByVal BeforeSelectedItem As Variant, _
Optional ByVal AfterSelectedItem As Variant, _
Optional ByVal IgnoreSelection As Boolean)
Dim nIndex As Variant
Dim nListItem As ListItem
Dim nListSubItem As ListSubItem
Dim i As Integer
With ListView
If Not IsMissing(BeforeSelectedItem) Then
If Not (.SelectedItem Is Nothing) Then
If CBool(BeforeSelectedItem) Then
nIndex = .SelectedItem.Index
End If
End If
ElseIf Not IsMissing(AfterSelectedItem) Then
If Not (.SelectedItem Is Nothing) Then
If CBool(AfterSelectedItem) Then
nIndex = .SelectedItem.Index + 1
End If
End If
ElseIf Not IsMissing(Before) Then
nIndex = Before
ElseIf Not IsMissing(After) Then
nIndex = After + 1
End If
End With
With ListItemStore
On Error Resume Next
If IsEmpty(nIndex) Then
Set nListItem = ListView.ListItems.Add(, .Key, .Text, .Icon, _
.SmallIcon)
ElseIf nIndex = 0 Then
Exit Sub
Else
If nIndex > ListView.ListItems.Count Then
Set nListItem = ListView.ListItems.Add(, .Key, .Text, _
.Icon, .SmallIcon)
Else
Set nListItem = ListView.ListItems.Add(nIndex, .Key, .Text, _
.Icon, .SmallIcon)
End If
End If
nListItem.Bold = .Bold
nListItem.Checked = .Checked
nListItem.ForeColor = .ForeColor
nListItem.Ghosted = .Ghosted
If Len(NewKey) Then
nListItem.Key = NewKey
Else
nListItem.Key = .Key
End If
If IsObject(.Tag) Then
Set nListItem.Tag = .Tag
Else
nListItem.Tag = .Tag
End If
nListItem.ToolTipText = .ToolTipText
If UBound(.ListSubItems) Then
For i = 1 To UBound(.ListSubItems)
Set nListSubItem = _
nListItem.ListSubItems.Add(, .ListSubItems(i).Key, _
.ListSubItems(i).Text, .ListSubItems(i).ReportIcon, _
.ListSubItems(i).ToolTipText)
nListSubItem.Bold = .ListSubItems(i).Bold
nListSubItem.ForeColor = .ListSubItems(i).ForeColor
If IsObject(.ListSubItems(i).Tag) Then
Set nListSubItem.Tag = .ListSubItems(i).Tag
Else
nListSubItem.Tag = .ListSubItems(i).Tag
End If
Next 'i
End If
If Not IgnoreSelection Then
nListItem.Selected = .Selected
End If
End With
End Sub
Auf der Grundlage dieser beiden Hilfsprozeduren dienen die vier folgenden Prozeduren dem einfachen Verschieben von ListItems in einem ListView-Steuerelement. Das zu verschiebende ListItem können Sie auch hier wieder per Schlüssel oder Index angeben, oder Sie übergeben direkt das gewünschte ListItem. Lassen die Angabe weg, wird das im ListView gewählte ListItem (SelectedItem) verschoben.
LvwListItemToTop und LvwListItemToEnd verschieben ein ListItem an den Anfang bzw. an das Ende der ListItems-Sammlung:
Public Sub LvwListItemToTop(ListView As ListView, _
Optional KeyIndexListItem As Variant, _
Optional ByVal LockUpdate As Boolean)
Dim nListItemStore As ListItemStore
Dim nListItem As ListItem
With ListView
If LockUpdate Then
LockWindowUpdate .hWnd
End If
With .ListItems
Set nListItem = zGetListItem(ListView, KeyIndexListItem)
If Not (nListItem Is Nothing) Then
If nListItem.Index > 1 Then
LvwGetListItemStore _
nListItemStore, ListView, nListItem, True
LvwInsertListItemStore ListView, nListItemStore, , 1
End If
End If
End With
End With
If LockUpdate Then
LockWindowUpdate 0&
End If
End Sub
Public Sub LvwListItemToEnd(ListView As ListView, _
Optional KeyIndexListItem As Variant, _
Optional ByVal LockUpdate As Boolean)
Dim nListItemStore As ListItemStore
Dim nListItem As ListItem
With ListView
If LockUpdate Then
LockWindowUpdate .hWnd
End If
With .ListItems
Set nListItem = zGetListItem(ListView, KeyIndexListItem)
If Not (nListItem Is Nothing) Then
If nListItem.Index < .Count Then
LvwGetListItemStore _
nListItemStore, ListView, nListItem, True
LvwInsertListItemStore ListView, nListItemStore
End If
End If
End With
End With
If LockUpdate Then
LockWindowUpdate 0&
End If
End Sub
Die Porzeduren LvwListItemUp und LvwListItemDown verschieben ein ListItem aufwärts bzw. abwärts. Hier können Sie zusätzlich im optionalen Parameter Steps angeben, um wie viele Zeilen das ListItem verschoben werden sollen. Es kann dabei allerdings nicht über den Anfang bzw. das Ende hinaus verschoben werden.
Public Sub LvwListItemUp(ListView As ListView, _
Optional KeyIndexListItem As Variant, _
Optional Steps As Long = 1, _
Optional ByVal LockUpdate As Boolean)
Dim nListItemStore As ListItemStore
Dim nListItem As ListItem
Dim nIndex As Long
With ListView
If LockUpdate Then
LockWindowUpdate .hWnd
End If
With .ListItems
Set nListItem = zGetListItem(ListView, KeyIndexListItem)
If Not (nListItem Is Nothing) Then
nIndex = nListItem.Index
If nIndex > 1 Then
nIndex = nIndex - Steps
If nIndex < 1 Then
nIndex = 1
End If
LvwGetListItemStore _
nListItemStore, ListView, nListItem, True
LvwInsertListItemStore _
ListView, nListItemStore, , nIndex
End If
End If
End With
End With
If LockUpdate Then
LockWindowUpdate 0&
End If
End Sub
Public Sub LvwListItemDown(ListView As ListView, _
Optional KeyIndexListItem As Variant, _
Optional Steps As Long = 1, _
Optional ByVal LockUpdate As Boolean)
Dim nListItemStore As ListItemStore
Dim nListItem As ListItem
Dim nIndex As Long
With ListView
If LockUpdate Then
LockWindowUpdate .hWnd
End If
With .ListItems
Set nListItem = zGetListItem(ListView, KeyIndexListItem)
If Not (nListItem Is Nothing) Then
nIndex = nListItem.Index
If nIndex < .Count Then
nIndex = nIndex + Steps
LvwGetListItemStore _
nListItemStore, ListView, nListItem, True
If nIndex > .Count Then
LvwInsertListItemStore ListView, nListItemStore
Else
LvwInsertListItemStore _
ListView, nListItemStore, , nIndex
End If
End If
End If
End With
End With
If LockUpdate Then
LockWindowUpdate 0&
End If
End Sub
|