Visual Basic Common Control API Routines
SHGetFileInfo: ListView Demo 2 - Populating the ListView
Second of four pages to create a ListView application to retrieve files from a specified folder.
     
Posted:   Sunday March 1, 1997
Updated:   Monday December 26, 2011
     
Applies to:   VB4-32, VB5, VB6
Developed with:   VB4-32, Windows 95
OS restrictions:   None
Author:   VBnet - Randy Birch
      
Related:   SHGetFileInfo: ListView Demo 1 - Obtaining the File Path
SHGetFileInfo: ListView Demo 2 - Populating the ListView
SHGetFileInfo: ListView Demo 3 - Adding Sorting Functionality
SHGetFileInfo: ListView Demo 4 - Adding the Associated Icons
     
 Prerequisites
SHGetFileInfo: ListView Demo 1 - Obtaining the File Path

This page details the code required to populate the listview control with files matching the selected file spec using the APIs FindFirstFile, FindNextFile and the WIN32_FIND_DATA type.

When the demo is completed, the final app will retrieve the users selection and populate the listview with selected files from that folder, complete with associated icons, file name, file type, file size and created date.

To the project constructed in Demo 1, add a ListView control as shown in the illustration.

In its Custom Properties, set:
   View = 3 - Report
   LabelEdit = 1 - Manual

Add the column headers as:
   Column 1 - Name - size=1700
   Column 2 - Size - size=900
   Column 3 - Type - size=1800
   Column 4 - Created - size=900

Set column 2 and column 4 to right alignment. Do not assign an imagelist to the control.
 BAS Module Code
To the bas module, make the following modifications and additions:

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.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
To the Constant declarations add:
Public Const SHGFI_DISPLAYNAME = &H200
Public Const SHGFI_EXETYPE = &H2000
Public Const SHGFI_SYSICONINDEX = &H4000  'system icon index
Public Const SHGFI_LARGEICON = &H0        'large icon
Public Const SHGFI_SMALLICON = &H1        'small icon
Public Const ILD_TRANSPARENT = &H1        'display transparent
Public Const SHGFI_SHELLICONSIZE = &H4
Public Const SHGFI_TYPENAME = &H400
Public Const BASIC_SHGFI_FLAGS = SHGFI_TYPENAME Or _
             SHGFI_SHELLICONSIZE Or SHGFI_SYSICONINDEX Or _
             SHGFI_DISPLAYNAME Or SHGFI_EXETYPE

Public Const MAX_PATH As Long = 260

To the Type area, add:
Public Type SHFILEINFO
   hIcon          As Long
   iIcon          As Long
   dwAttributes   As Long
   szDisplayName  As String * MAX_PATH
   szTypeName     As String * 80
End Type

Public shinfo As SHFILEINFO

Public Type FILETIME
  dwLowDateTime     As Long
  dwHighDateTime    As Long
End Type

Public Type SYSTEMTIME
  wYear             As Integer
  wMonth            As Integer
  wDayOfWeek        As Integer
  wDay              As Integer
  wHour             As Integer
  wMinute           As Integer
  wSecond           As Integer
  wMilliseconds     As Integer
End Type

Public Type WIN32_FIND_DATA
  dwFileAttributes  As Long
  ftCreationTime    As FILETIME
  ftLastAccessTime  As FILETIME
  ftLastWriteTime   As FILETIME
  nFileSizeHigh     As Long
  nFileSizeLow      As Long
  dwReserved0       As Long
  dwReserved1       As Long
  cFileName         As String * MAX_PATH
  cAlternate        As String * 14
End Type


In the API declaration area, add:
Public Declare Function FindFirstFile Lib "kernel32" _
   Alias "FindFirstFileA" _
  (ByVal lpFileName As String, 
   lpFindFileData As WIN32_FIND_DATA) As Long
   
Public Declare Function FindNextFile Lib "kernel32" _
  Alias "FindNextFileA" _
  (ByVal hFindFile As Long, 
   lpFindFileData As WIN32_FIND_DATA) As Long

Public Declare Function FindClose Lib "kernel32" _
  (ByVal hFindFile As Long) As Long

Public Declare Function FileTimeToSystemTime Lib "kernel32" _
  (lpFileTime As FILETIME, 
   lpSystemTime As SYSTEMTIME) As Long
   
Public Declare Function UpdateWindow Lib "user32" _
      (ByVal hwnd As Long) As Long

Public Declare Function ImageList_Draw Lib "comctl32" _
  (ByVal himl&, _
   ByVal i&, _
   ByVal hDCDest&, _
   ByVal x&, _
   ByVal y&, _
   ByVal flags&) As Long

Public Declare Function SHGetFileInfo Lib "shell32" _
   Alias "SHGetFileInfoA" _
  (ByVal pszPath As String, _
   ByVal dwFileAttributes As Long, _
   psfi As SHFILEINFO, _
   ByVal cbSizeFileInfo As Long, _
   ByVal uFlags As Long) As Long
 Form Code
Make the following additions to the form code:

Option Explicit

In the form's general declarations, add:
Dim UpdateFrequency  As Integer

In the form code, make the following bolded changes: 
Private Sub Form_Load()

    Me.Move (Screen.Width - Me.Width) \ 2, (Screen.Height - Me.Height) \ 2
    
    With Combo1
        .AddItem "All Files and Folders (*.*)"
        .AddItem "Applications (*.exe)"
        .AddItem "Device Drivers (*.drv)"
        .AddItem "Documents (*.doc)"
        .AddItem "Dynamic Link Libraries (*.dll)"
        .AddItem "Rich Text Format Documents (*.rtf)"
        .AddItem "System Files (*.sys)"
        .AddItem "Visual Basic Modules (*.bas)"
        .AddItem "Visual Basic Forms (*.frm)"
        .AddItem "Visual Basic 3 Projects (*.mak)"
        .AddItem "Visual Basic 4 Projects (*.vbp)"
        .AddItem "Postscript Printer Font Metrics (*.pfm)"
        .AddItem "Text Files (*.txt)"
        .AddItem "True Type Fonts (*.ttf)"
        .AddItem "Windows Help Files (*.hlp)"
        .AddItem "Windows Shortcuts (*.lnk)"
        .ListIndex = 0
    End With
    
    With ListView1
      .SortKey = 0
    End With
      
    UpdateFrequency = 25
   
End Sub


Private Sub cmdSelect_Click(index As Integer)

    Select Case index
      
        Case 0: fPath$ = vbGetBrowseDirectory$()
                If Len(fPath$) > 0 Then vbGetFileList
      
        Case 1: If Len(fPath$) > 0 Then vbGetFileList
        
        Case 2: Unload Me
                    
    End Select
  
End Sub


Add the following new code to the form:
Private Function TrimNull(item As String) As String

    Dim pos As Integer
    
    pos = InStr(item, Chr$(0))
    If pos Then item = Left$(item, pos - 1)
    TrimNull = item
  
End Function


Private Sub vbGetFileList()

    Dim hFile As Long
    Dim fName As String
    Dim fExt As String
    Dim counter As Integer
    Dim WFD As WIN32_FIND_DATA
    
    Me.MousePointer = vbArrowHourglass
    DoEvents
    
    fExt = vbGetComboFileSpec()
  
    If Len(fPath) > 0 And Len(fExt) > 0 Then
    
      fName = fPath & fExt
      DisplayName = fName
      
      DoEvents
      
          ListView1.ListItems.Clear
          DoEvents
          
          hFile = FindFirstFile(fName, WFD)
         
            If hFile > 0 Then
                  
              counter = 1
              vbAddFileItemView WFD
              
                While FindNextFile(hFile, WFD)
                
                  counter = counter + 1
                  vbAddFileItemView WFD
                     
                    If counter = UpdateFrequency Then
                        Call UpdateWindow(ListView1.hwnd)
                        counter = 0
                    End If
                     
                Wend
              
            End If
      
          FindClose hFile
      
    End If
  
    cmdSelect(1).Enabled = False
    Me.MousePointer = vbDefault
  
End Sub


Private Sub vbAddFileItemView(WFD As WIN32_FIND_DATA)

    Dim sFileName As String
    Dim ListImgKey As String
    Dim fType As String
    
    sFileName = TrimNull(WFD.cFileName)
    
    If sFileName <> "." And sFileName <> ".." Then
              
        Dim hInfo As Long
        Dim tExeType As Long
        Dim itmX As ListItem
        
        hInfo = SHGetFileInfo(fPath & sFileName, 0&, shinfo, Len(shinfo), BASIC_SHGFI_FLAGS)
        
        fType = LCase$(TrimNull(shinfo.szTypeName))
        
        Set itmX = ListView1.ListItems.Add(, , LCase$(sFileName))
        
        itmX.SubItems(1) = vbGetFileSizeKBStr(WFD.nFileSizeHigh + WFD.nFileSizeLow)
        itmX.SubItems(2) = fType
        itmX.SubItems(3) = vbGetFileDate$(WFD.ftCreationTime)
      
    End If
  
End Sub


Private Function vbGetFileDate(CT As FILETIME) As String

    Dim ST As SYSTEMTIME
    Dim ds As Single
       
    If FileTimeToSystemTime(CT, ST) Then
       ds = DateSerial(ST.wYear, ST.wMonth, ST.wDay)
       vbGetFileDate$ = Format$(ds, "Short Date")
    Else
       vbGetFileDate$ = ""
    End If
  
End Function


Private Function vbGetFileSizeKBStr(fsize As Long) As String

    vbGetFileSizeKBStr = Format$(((fsize) / 1000) + 0.5, "#,###,###") & "kb"
  
End Function
 Comments
Run the project, and click the Select Folder button. Browse to any folder, and hit OK. The folder selected and the file type from the combo box should be returned in the DisplayName label as a fully-qualified path and filespec. In addition, the listview should populate with all the files in the selected directory matching the selected file type.

Move to SHGetFileInfo: ListView Demo 3 - Adding Sorting Functionality.

 
 

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