Trucos ListView : Mostrar imágenes en la cabecera

La funcionalidad extendida de la dll Comctl32.dll sólo está disponible para la versión 4.70 y superiores (instaladas por el IE 3.x y el IE 4)

Si necesitamos mostrar una imagen en la cabecera de las columnas del ListView (por ejemplo para mostrar el sentido de la ordenación) podremos emplear algo como :

Declaramos en un módulo :

Public Declare Function SendMessageLong Lib "user32" _
   Alias "SendMessageA" _
  (ByVal hwnd As Long, _
   ByVal wMsg As Long, _
   ByVal wParam As Long, _
   ByVal lParam As Long) As Long

Public Declare Function SendMessageAny Lib "user32" _
   Alias "SendMessageA" _
  (ByVal hwnd As Long, _
   ByVal wMsg As Long, _
   ByVal wParam As Long, _
   lParam As Any) As Long

Public Declare Function GetWindowLong Lib "user32" _
   Alias "GetWindowLongA" _
  (ByVal hwnd As Long, _
   ByVal nIndex As Long) As Long

Public Declare Function SetWindowLong Lib "user32" _
   Alias "SetWindowLongA" _
  (ByVal hwnd As Long, _
   ByVal nIndex As Long, _
   ByVal dwNewLong As Long) As Long


Public Const GWL_STYLE = (-16)
Public Const LVM_FIRST = &H1000
Public Const LVM_GETHEADER = (LVM_FIRST + 31)

Public Const HDS_HOTTRACK = &H4

Public Const HDI_BITMAP = &H10
Public Const HDI_IMAGE = &H20
Public Const HDI_ORDER = &H80
Public Const HDI_FORMAT = &H4
Public Const HDI_TEXT = &H2
Public Const HDI_WIDTH = &H1
Public Const HDI_HEIGHT = HDI_WIDTH

Public Const HDF_LEFT = 0
Public Const HDF_RIGHT = 1
Public Const HDF_IMAGE = &H800
Public Const HDF_BITMAP_ON_RIGHT = &H1000
Public Const HDF_BITMAP = &H2000
Public Const HDF_STRING = &H4000

Public Const HDM_FIRST = &H1200
Public Const HDM_SETITEM = (HDM_FIRST + 4)

Public Type HD_ITEM
   mask As Long
   cxy As Long
   pszText As String
   hbm As Long
   cchTextMax As Long
   fmt As Long
   lParam As Long
   iImage As Long
   iOrder As Long
End Type

Y añadimos esta función :

Public Sub ShowHeaderIcon(lv As ListView, colNo As Long, imgIconNo As Long, _
                          left As Boolean, show As Boolean)
'Parámetros :
'lv : El ListView
'colNo : el número de columna donde irá la imagen
'imgIconNo : el número de imagen del ImageList al que está ligada la propiedad
'SmallIcons del ListView
'left : true si queremos la imagen a la izquierda del texto y false si
'la queremos a la derecha
'show : true si queremos mostrar la imagen o false si queremos ocultarla
'
'Los iconos pueden ser como mucho de 16x16 pero es aconsejable
'que sean de 12x12 o 13x13

   Dim r As Long
   Dim hHeader As Long
   Dim HD As HD_ITEM

  'obtenemos un handle a la cabecera del ListView
   hHeader = SendMessageLong(lv.hwnd, LVM_GETHEADER, 0, 0)
  'damos valores a la estructura
   With HD
      .mask = HDI_IMAGE Or HDI_FORMAT
      .fmt = HDF_LEFT Or HDF_STRING Or _
             IIf(left, HDF_BITMAP, HDF_BITMAP_ON_RIGHT) Or _
             IIf(show, HDF_IMAGE, 0)
      .pszText = lv.ColumnHeaders(colNo + 1).Text
      If show Then .iImage = imgIconNo
   End With
  'modificamos la cabecera
   r = SendMessageAny(hHeader, HDM_SETITEM, colNo, HD)
End Sub

Para usarla para mostrar si estamos ordenando ascendente o descendentemente podemos usar algo como esto en el evento ColumClick :

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As ComctlLib.ColumnHeader)

   Dim i As Long
   Static sOrder

   sOrder = Not sOrder

  'Empleamos la ordenación por defecto para ordenar los elementos
   ListView1.SortKey = ColumnHeader.Index - 1
   ListView1.SortOrder = Abs(sOrder)
   ListView1.Sorted = True

  'borramos la imagen de la columna no ordenada actualmente
  'y actualizamos la columna en la que pulsaron
   For i = 0 To ListView1.ColumnHeaders.Count - 1
      'si esta es la columna ordenada
      If i = ListView1.SortKey Then
            ShowHeaderIcon ListView1, _
                           ListView1.SortKey, _
                           ListView1.SortOrder, _
                           False, _
                           True
      Else: ShowHeaderIcon ListView1, i, 0, 0, 0
      End If
   Next i
End Sub


Otro efecto aplicable a la cabecera es la posibilidad de que el texto cambie de color al situarnos sobre él. Para ello emplearemos la función :

Public Sub SetHeaderHotTrack()
   Dim r As Long
   Dim hHeader As Long
   Dim rstyle As Long

  'obtenemos un handle a la cabecera del ListView
   hHeader = SendMessageLong(ListView1.hwnd, LVM_GETHEADER, 0, 0)
  'obtenemos el estilo actual de la cabecera
   rstyle = GetWindowLong(hHeader, GWL_STYLE)
  'ponemos el contrario
   rstyle = rstyle Xor HDS_HOTTRACK
  'aplicamos el nuevo estilo a la cabecera
   r = SetWindowLong(hHeader, GWL_STYLE, rstyle)
End Sub

Actua "como un interruptor". La primera vez que la llamas activa el cambio de color, la segunda lo desactiva, etc.



Trucos Trucos

Visual Basic Página de Visual Basic

Página principal Página principal

www.jrubi.com