|
Eine automatische Anpassung der Spaltenbreiten an den breitesten
Text ist beim ListView-Steuerelement (in der Report-Ansicht) nicht
vorgesehen. Sie können die Anpassung jedoch jederzeit für jede
Spalte separat vornehmen, indem Sie über die API-Funktion SendMessage
die Nachricht LVM_SETCOLUMNWIDTH
mit dem Parameter LVSCW_AUTOSIZE an das ListView-Steuerelement
senden.
Es gibt zwar dazu auch noch den Parameter
LVSCW_AUTOSIZE_USEHEADER, der die Breite der Spaltenbeschriftung (ColumnHeader)
in die Berechnung der Spaltenbreite einbeziehen sollte - bei der
ListView-Implementierung der Microsoft Common Controls bleibt er
allerdings offensichtlich ohne Wirkung. Ersatzweise können Sie
jedoch vorübergehend eine zusätzliche Zeile in das
ListView-Steuerelement einfügen, deren ListItem und dessen
ListSubItems die Texte (und gegebenenfalls die Icons) der
Spaltenköpfe enthalten. Nach der Anpassung der Spaltenbreite(n)
wird diese Zeile wieder entfernt. Sind die Spalten umsortiert worden
(Eigenschaft AllowColumnReorder gleich True), müssen Sie die
geänderte Reihenfolge beim Einfügen der Hilfszeile
berücksichtigen. Damit das Einfügen und Entfernen der Hilfszeile
nicht zu einem störenden Flackern führt oder gar sichtbar wird,
wird das ListView-Steuerelement vorübergehend mittels der
API-Funktion LockWindowUpdate
eingefroren.
Der folgenden Hilfsprozedur übergeben Sie im ersten Parameter
das betreffende ListView-Steuerelement. Optional können Sie im
zweiten Parameter eine spezifische Spalte (eine gültige Position
einer Spalte, von 1 bis zur Anzahl der Spalten)
angeben, deren Breite allein angepasst werden soll. Übergeben Sie
hier einen ungültigen Wert, werden alle Spalten angepasst. Im
nächsten optionalen Parameter IncludeHeaders geben Sie an, ob die
Breite der Texte der Spaltenköpfe mit berücksichtigt werden soll.
Setzen Sie den letzten optionalen Parameter gleich True, füllt die
letzte Spalte - soweit möglich - automatisch den verbleibenden Raum
bis zum rechten Rand des ListView-Steuerelements bzw. bis zu einem
gegebenenfalls sichtbaren vertikalen Rollbalken aus. Letzteren
Effekt können Sie über die darauffolgende Prozedur
ListViewLastColumnFillSize auch ohne Anpassung der übrigen
Spaltenbreiten erreichen.
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Declare Function GetClientRect Lib "user32" _
(ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function LockWindowUpdate Lib "user32" _
(ByVal hwndLock As Long) As Long
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
Sub ListViewAdjustColumnWidth(ListView As ListView, _
Optional Position As Integer, Optional IncludeHeaders As Boolean, _
Optional ByVal LastColumnFillSize As Boolean)
Dim i As Integer
Dim nListItem As ListItem
Dim nKey As String
Dim nColumn As Integer
Dim nPosition As Integer
Dim nSmallIconsSet As Boolean
Dim nRect As RECT
Dim nWidth As Single
Const LVM_SETCOLUMNWIDTH = &H101E
Const LVSCW_AUTOSIZE = -1&
With ListView
LockWindowUpdate .hwnd
If IncludeHeaders Then
If .SmallIcons Is Nothing Then
Set .SmallIcons = .ColumnHeaderIcons
nSmallIconsSet = True
End If
Select Case Position
Case 1 To .ColumnHeaders.Count
nKey = CStr(Now)
If zHasIcon(.ColumnHeaders(1)) Then
Set nListItem = .ListItems.Add(1, nKey, _
.ColumnHeaders(1).Text & " ")
Else
Set nListItem = .ListItems.Add(1, nKey, _
.ColumnHeaders(1).Text & " ")
End If
nPosition = .ColumnHeaders(1).Position
If nPosition = Position Then
nColumn = 0
End If
For i = 2 To .ColumnHeaders.Count
If zHasIcon(.ColumnHeaders(i)) Then
nListItem.ListSubItems.Add , , _
.ColumnHeaders(i).Text & " "
Else
nListItem.ListSubItems.Add , , _
.ColumnHeaders(i).Text
End If
nPosition = .ColumnHeaders(i).Position
If nPosition = Position Then
nColumn = i - 1
End If
Next
SendMessage .hwnd, LVM_SETCOLUMNWIDTH, nColumn, _
LVSCW_AUTOSIZE
Case Else
nKey = CStr(Now)
If zHasIcon(.ColumnHeaders(1)) Then
Set nListItem = .ListItems.Add(1, nKey, _
.ColumnHeaders(1).Text & " ")
Else
Set nListItem = .ListItems.Add(1, nKey, _
.ColumnHeaders(1).Text & " ")
End If
SendMessage .hwnd, LVM_SETCOLUMNWIDTH, 0, _
LVSCW_AUTOSIZE
For i = 2 To .ColumnHeaders.Count
If zHasIcon(.ColumnHeaders(i)) Then
nListItem.ListSubItems.Add , , _
.ColumnHeaders(i).Text & " "
Else
nListItem.ListSubItems.Add , , _
.ColumnHeaders(i).Text
End If
SendMessage .hwnd, LVM_SETCOLUMNWIDTH, i - 1, _
LVSCW_AUTOSIZE
Next
End Select
.ListItems.Remove nKey
If nSmallIconsSet Then
Set .SmallIcons = Nothing
End If
Else
Select Case Position
Case 1 To .ColumnHeaders.Count
nPosition = .ColumnHeaders(Position).Position
If nPosition = Position Then
SendMessage .hwnd, LVM_SETCOLUMNWIDTH, Position - 1, _
LVSCW_AUTOSIZE
Else
SendMessage .hwnd, LVM_SETCOLUMNWIDTH, nPosition - 1, _
LVSCW_AUTOSIZE
End If
Case Else
For i = 0 To .ColumnHeaders.Count
SendMessage .hwnd, LVM_SETCOLUMNWIDTH, i, _
LVSCW_AUTOSIZE
Next
End Select
End If
If LastColumnFillSize Then
For i = 1 To .ColumnHeaders.Count - 1
nWidth = nWidth + .ColumnHeaders(i).Width
Next 'i
GetClientRect .hwnd, nRect
nRect.Right = nRect.Right * Screen.TwipsPerPixelX
If nRect.Right > nWidth Then
.ColumnHeaders(.ColumnHeaders.Count).Width = _
nRect.Right - nWidth
End If
End If
.Refresh
End With
LockWindowUpdate 0&
End Sub
Private Function zHasIcon(ColumnHeader As ColumnHeader) _
As Boolean
Dim nIcon As Variant
nIcon = ColumnHeader.Icon
If nIcon = "0" Then
Else
zHasIcon = CBool(Len(nIcon))
End If
End Function
Public Sub ListViewLastColumnFillSize(ListView As ListView)
Dim i As Integer
Dim nRect As RECT
Dim nWidth As Single
With ListView
For i = 1 To .ColumnHeaders.Count - 1
nWidth = nWidth + .ColumnHeaders(i).Width
Next 'i
GetClientRect .hwnd, nRect
nRect.Right = (nRect.Right - 1) * Screen.TwipsPerPixelX
If nRect.Right > nWidth Then
.ColumnHeaders(.ColumnHeaders.Count).Width = _
nRect.Right - nWidth
End If
End With
End Sub
|