Visual Basic Common Control API Routines
Pure VB: Highlight a Listview Report Column
Posted:   Wednesday February 20, 2002
Updated:   Monday December 26, 2011
Applies to:   VB6, or VB5 using APIs (not demonstrated)
Developed with:   VB6, Windows XP
OS restrictions:   None
Author:   VBnet - Randy Birch

Pure VB: Create a Ledger-Style Listview Report Background
Pure VB: Create a Ledger-Style Listview Report Background with Custom Height
WM_NOTIFY: Track Highlighted ListView Column Width Changes via Subclassing

Visual Basic 6. Visual Basic 5 users can not access the listview's picture property without using APIs: see SendMessage: Add a Background Image to a ListView

Just as the picture property was used in Pure VB: Create a Ledger-Style Listview Report Background to simulate a ledger-style background for the listview, this code provides a means to highlight the data in a specific column in the control using the same technique.

To do this, the the default background colour, and the colour for the highlighted row are passed, along with the 1-based index of the column of interest. The code determines the left and width of the column of interest, and draws a 1 pixel high filled rect at that location. The code then assigns the picture drawn to the listview's picture property in tiled mode, causing the column to take the a BackColor specified. This code works equally well with the HideColumnHeaders property set to either True or False.

There is an obvious drawback to this routine ... although scrolling provides no problems, resizing the column once the highlight has been applied does not cause the highlight width to match the new column width because the listview does not expose any method to track the movement of the ColumnHeaders. This is addressed in the subclassed demo of this series listed above.

 BAS Module Code

 Form Code
Add a command button (Command1), a picture box (Picture1), a combo (Combo1), a label (Label1) and a listview (Listview1) to a form.   An Imagelist is optional - if used add at least one 16x16 icon and set the correct Enum parameter in the load event (change LoadData sizeNone to LoadData sizeIcon).  Add the following code:

Option Explicit
' Copyright 1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
Private Enum ImageSizingTypes
   [sizeNone] = 0
End Enum

Private Enum LedgerColours
  vbledgerWhite = &HF9FEFF
  vbLedgerGreen = &HD0FFCC
  vbLedgerYellow = &HE1FAFF
  vbLedgerRed = &HE1E1FF
  vbLedgerGrey = &HE0E0E0
  vbLedgerBeige = &HD9F2F7
  vbLedgerSoftWhite = &HF7F7F7
  vbledgerPureWhite = &HFFFFFF
End Enum

Private sFilenameIn As String

'Below used for listview column auto-resizing
Private Const LVM_FIRST As Long = &H1000
Private Const LVM_SETCOLUMNWIDTH As Long = (LVM_FIRST + 30)
Private Const LVSCW_AUTOSIZE As Long = -1

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

Private Sub Form_Load()
   Command1.Caption = "Highlight Column"
   With Combo1
      .AddItem 1
      .AddItem 2
      .AddItem 3
      .AddItem 4
      .AddItem 5
      .ListIndex = 0
   End With
   LoadData sizeNone  'change to sizeIcon if using an imagelist
End Sub

Private Sub Command1_Click()

   With ListView1
      .Visible = False
      .Checkboxes = False
      .FullRowSelect = True
      Call SetHighlightColumn(ListView1, _
                              vbLedgerRed, _
                              vbledgerPureWhite, _
                              Combo1.List(Combo1.ListIndex), _
      .Visible = True            'Restore visibility

   End With

End Sub

Private Sub SetHighlightColumn(lv As ListView, _
                               clrHighlight As LedgerColours, _
                               clrDefault As LedgerColours, _
                               nColumn As Long, _
                               nSizingType As ImageSizingTypes)

   Dim cnt     As Long  'counter
   Dim cl      As Long  'columnheader left
   Dim cw      As Long  'columnheader width
   On Local Error GoTo SetHighlightColumn_Error
   If lv.View = lvwReport Then
     'set up the listview properties
      With lv
        .Picture = Nothing  'clear picture
        .Visible = 1
        .PictureAlignment = lvwTile
      End With  ' lv
     'set up the picture box properties
      With Picture1
         .AutoRedraw = False       'clear/reset picture
         .Picture = Nothing
         .BackColor = clrDefault
         .Height = 1
         .AutoRedraw = True        'assure image draws
         .BorderStyle = vbBSNone   'other attributes
         .ScaleMode = vbTwips
         .Top = Form1.Top - 10000  'move it off screen
         .Visible = False
         .Height = 1               'only need a 1 pixel high picture
         .Width = Screen.Width
        'draw a box in the highlight colour
        'at location of the column passed
         cl = ListView1.ColumnHeaders(nColumn).Left
         cw = ListView1.ColumnHeaders(nColumn).Left + _
         Picture1.Line (cl, 0)-(cw, 210), clrHighlight, BF
         .AutoSize = True
      End With  'Picture1
     'set the lv picture to the
     'Picture1 image
      lv.Picture = Picture1.Image
      lv.Picture = Nothing
   End If  'lv.View = lvwReport

On Local Error GoTo 0
Exit Sub

  'clear the listview's picture and exit
   With lv
      .Picture = Nothing
   End With
   Resume SetHighlightColumn_Exit
End Sub

Private Sub LoadData(nSizingType As ImageSizingTypes)

   Dim cnt As Long
   Dim itmX As ListItem
   With ListView1
      .ColumnHeaders.Add , , "Number"
      .ColumnHeaders.Add , , "Time"
      .ColumnHeaders.Add , , "Mode"
      .ColumnHeaders.Add , , "State"
      .ColumnHeaders.Add , , "Warnings"
      .View = lvwReport
      .Sorted = False
   End With
  'Create some fake data
   For cnt = 1 To 100
      Set itmX = Form1.ListView1.ListItems.Add(, , Format$(cnt, "###"))

      itmX.SubItems(1) = "Weld process"
      itmX.SubItems(2) = "T-manual"
      If cnt Mod 2 = 0 Then
         itmX.SubItems(2) = "Auto detect"
      End If
      If cnt Mod 3 = 0 Then
         itmX.SubItems(4) = "Trouble at " & Format$(Time, "hh:mm:ss am/pm")
         itmX.SubItems(3) = "Stopped"
         If nSizingType = sizeIcon Then itmX.SmallIcon = 1
      End If

  'Now that the control contains data, this
  'causes the columns to resize to fit the items
   Call lvAutosizeControl(Form1.ListView1)
End Sub

Private Sub lvAutosizeControl(lv As ListView)

   Dim col2adjust As Long

  'Size each column based on the maximum of
  'EITHER the column header text width, or,
  'if the items below it are wider, the
  'widest list item in the column
   For col2adjust = 0 To lv.ColumnHeaders.Count - 1
      Call SendMessage(lv.hwnd, _
                       LVM_SETCOLUMNWIDTH, _
                       col2adjust, _
                       ByVal LVSCW_AUTOSIZE_USEHEADER)

End Sub


PayPal Link
Make payments with PayPal - it's fast, free and secure!


Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy


Hit Counter