Visual Basic Common Control API Routines
SendMessage: Add a Background Image to a ListView
     
Posted:   Friday June 19, 1998
Updated:   Monday December 26, 2011
     
Applies to:   VB4-32, VB5, VB6
Developed with:   VB5, Windows 98
OS restrictions:   None
Author:   VBnet - Randy Birch
     
Related:   Pure VB: Create a Ledger-Style Listview Report Background
Pure VB: Create a Ledger-Style Listview Report Background with Custom Height
Pure VB: Highlight a Listview Report Column
WM_NOTIFY: Track Highlighted ListView Column Width Changes via Subclassing
     
 Prerequisites
This method is intended for Visual Basic 5 or Visual Basic 6 where the Common Control library used is the MSComCtl 5 version (comctl32.ocx). Because the VB6-specific mscomctl.ocx (Common Controls 6) is a complete implementation of comctl32.dll and not reliant on the version of comctl32.dll installed, this routine may not work when applied to a listview created from the VB6-specific mscomctl.ocx.

Enhanced Comctl32 functionality is only available to users with comctl32.dll version 4.70 or greater installed. This dll is typically installed with IE3.x or greater.


Once again, the SendMessage API, in conjunction with the new extended style flags for the Listview control, provides a means to customize the appearance of the listview common control in a Visual Basic application.

By combining the new LVBKIMAGE structure (Type), and specifying the LVBKIF_SOURCE_URL Or LVBKIF_STYLE_TILE style flags, you can apply a background image to the control.

Obviously, the image applied must be tasteful enough to allow the data to be presented. Too garish a background only detracts from the appearance of the app.  In addition, the background scrolls with the listview. This is not of concern when LVBKIF_STYLE_TILE is used (illustration below, left) ... the background always has the image, but without it (the main illustration to the right), the graphic will scroll with the data.

One of the added benefits of this feature is you can now add a graphic to the control to indicate that there is no data available (below, right).

The LVBKIMAGE is only available on systems that has the comctl32.dll version provided with IE4 and other later MS products installed.

 BAS Module Code
None.

 Form Code
Create a form like the one shown, with a listview, an imagelist containing a 16x16 icon or bitmap, five command buttons and three text boxes using the control default names. Set the textbox paths to point to the files you want to use for the demo. Set the listview style to report mode, then add the following code to the form:

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 Type LVBKIMAGE
   uFlags As Long
   hBmp As Long
   pszImage As String
   cchImageMax As Long
   xOffsetPercent As Long
   yOffsetPercent  As Long
End Type

Private Type tagINITCOMMONCONTROLSEX
    dwSize As Long
    dwICC As Long
End Type

Private Const ICC_LISTVIEW_CLASSES As Long = &H1
Private Const CLR_NONE = &HFFFFFFFF
Private Const LVM_FIRST As Long = &H1000
Private Const LVBKIF_SOURCE_NONE = &H0
Private Const LVBKIF_SOURCE_HBITMAP = &H1
Private Const LVBKIF_SOURCE_URL = &H2
Private Const LVBKIF_SOURCE_MASK = &H3
Private Const LVBKIF_STYLE_NORMAL = &H0
Private Const LVBKIF_STYLE_TILE = &H10
Private Const LVBKIF_STYLE_MASK = &H10
Private Const LVM_SETBKIMAGEA = (LVM_FIRST + 68)
Private Const LVM_SETBKIMAGEW = (LVM_FIRST + 138)
Private Const LVM_GETBKIMAGEA = (LVM_FIRST + 69)
Private Const LVM_GETBKIMAGEW = (LVM_FIRST + 139)
Private Const LVM_SETBKIMAGE = LVM_SETBKIMAGEA
Private Const LVM_GETBKIMAGE = LVM_GETBKIMAGEA
Private Const LVM_SETTEXTBKCOLOR = (LVM_FIRST + 38)
Private Const LVM_SETEXTENDEDLISTVIEWSTYLE As Long = (LVM_FIRST + 54)
Private Const LVS_EX_FULLROWSELECT As Long = &H20
   
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 Declare Sub InitCommonControls Lib "comctl32" ()

Private Declare Function InitCommonControlsEx Lib "comctl32" _
   (lpInitCtrls As tagINITCOMMONCONTROLSEX) As Boolean
   
         

Private Sub Form_Load()

   With ListView1
      .SortKey = 0
      .SmallIcons = ImageList1
      .ColumnHeaders(1).Width = .Width - 600
      .View = lvwReport
   End With
   
   Call InitComctl32(ICC_LISTVIEW_CLASSES)

  'An alternate way to set the extended listview styles!
   Call SendMessage(ListView1.hWnd, _
                    LVM_SETEXTENDEDLISTVIEWSTYLE, _
                    LVS_EX_FULLROWSELECT, ByVal True)
   
   DisplayNoDataImage
      
End Sub


Private Sub Command1_Click()

   Dim BKIMG As LVBKIMAGE
   
  'prepare the backimage structure data
   With BKIMG
      'use the file provided in pszImage member
      .uFlags = LVBKIF_SOURCE_URL
      
      'the imagefile to display
      .pszImage = (Text3.Text)
      
      'h&v offsets for the pix in percent. A setting
      'of 0 aligns the image against the left or top;
      '100 against the right or bottom.  A setting of
      '50 each centers the image in the control.
      .xOffsetPercent = 50
      .yOffsetPercent = 50
  
   End With
   
  'set the text background to none (transparent) to
  'allow image to show through.  A RGB() value can
  'also be passed to colour the text background
  '(to the edge of the control)
   Call SendMessage(ListView1.hWnd, _
                    LVM_SETTEXTBKCOLOR, _
                    0&, ByVal CLR_NONE)
   
  'set the image to the listview
   Call SendMessage(ListView1.hWnd, _
                    LVM_SETBKIMAGE, _
                    0, BKIMG)

End Sub


Private Sub Command2_Click()
   
   BuildLVdata
   DisplayNoDataImage

End Sub


Private Sub Command3_Click()

   Dim BKIMG As LVBKIMAGE
   
  'prepare the backimage structure data
   With BKIMG
      'use the file provided in pszImage and tile
      .uFlags = LVBKIF_SOURCE_URL Or LVBKIF_STYLE_TILE
      
      'the imagefile to display
      .pszImage = (Text2.Text)
      
      'h&v offsets for the pix (only if tiled not specified)
      '.xOffsetPercent = 0
      '.yOffsetPercent = 0
   End With
   
  'set the text background to none (transparent) to
  'allow image to show through.  A RGB() value can
  'also be passed to colour the text background
  '(to the edge of the control)
   Call SendMessage(ListView1.hWnd, _
                    LVM_SETTEXTBKCOLOR, _
                    0&, ByVal CLR_NONE)
   
  'set the image to the listview
   Call SendMessage(ListView1.hWnd, _
                    LVM_SETBKIMAGE, _
                    0&, BKIMG)
   
End Sub


Private Sub Command4_Click()

      ListView1.ListItems.Clear
      DisplayNoDataImage
   
End Sub


Private Sub Command5_Click()

   Unload Me
   
End Sub


Private Sub BuildLVdata()

   Dim itmX As ListItem
   Dim imgX As ListImage
   Dim sItem As String
   Dim c As Integer
   
   For c = 1 To 20
   
      sItem = "Listview listitem #" & c
      Set itmX = ListView1.ListItems.Add(, , Trim$(sItem))
      
      itmX.SmallIcon = ImageList1.ListImages("page").Key
   
   Next
      
End Sub


Private Sub DisplayNoDataImage()

   Dim BKIMG As LVBKIMAGE
   
   With BKIMG
   
      If ListView1.ListItems.Count > 0 Then
     
       'remove the 'no data' image by clearing
       'the image flag
        .uFlags = LVBKIF_SOURCE_NONE
        
      Else
        'set the image to the 'no data text' image
        'Specifying LVBKIF_SOURCE_URL indicates that the 
        'lParam member in SendMessage contains the 
        'path/filename of the image.
        .uFlags = LVBKIF_SOURCE_URL
        .pszImage = (Text1.Text)
        .xOffsetPercent = 3
        .yOffsetPercent = 3
      End If
     
   End With
      
   Call SendMessage(ListView1.hWnd, _
                    LVM_SETTEXTBKCOLOR, _
                    0&, ByVal CLR_NONE)

   Call SendMessage(ListView1.hWnd, _
                    LVM_SETBKIMAGE, _
                    0&, BKIMG)
      
End Sub


Private Function InitComctl32(dwFlags As Long) As Boolean

  Dim icc As tagINITCOMMONCONTROLSEX
  On Error GoTo Err_OldVersion
  
  icc.dwSize = Len(icc)
  icc.dwICC = dwFlags
  
 'VB will generate error 453 "Specified
 'DLL function not found" here if the new
 'version isn't installed and it can't find
 'the function's name. We'll hopefully be
 'able to load the old version below. Note 
 'that the methods here must have comctl32.dll 
 'v4.72 or greater; this routine only 
 'initializes the API; it does not 
 'determine the version.
  InitComctl32 = InitCommonControlsEx(icc)
  Exit Function

Err_OldVersion:
  InitCommonControls

End Function
 Comments
I have packaged up the three graphics shown in the illustrations in case you don't have anything handy to test the routines against.

 
 

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