-->

Show Hidden Directories in DirListBox

 
While an Explorer style TreeView is favorable to using a DirListBox these days sometimes you may still have a DirListBox in your program. This code searches a DirListBox's Path for hidden directories and optionally system directories. It then adds each hidden folder to the DirListBox at the appropriate position. VB/Windows handles the added items without any further coding. Tested on Win98.

Download source code with a test app (4KB)

 
Option Explicit

'    © 9/18/2000
'    This code is by Arthur Marks.
'
'    You may use this code as you wish in your own projects. You may
'    distribute this code as long as you do not charge for it and you
'    include this information with it. (I would appreciate if you e-mail
'    me to let me know where you are posting it.) For ease of distribution
'    all code has been placed in a form module.
'
'    Use at your own risk, etc.
'
'    Usage:
'    From the Change event of your dir box call
'        ShowHiddenDirectories Dir1
'    Note that you should either provide the user the choice to show
'    hidden files or check the registry HKEY_CURRENT_USER\Software\
'    Microsoft\Windows\CurrentVersion\Explorer\Advanced\Hidden
'
'    Functional Description:
'    Searches a DirListBox's Path for hidden files.
'    It then adds each hidden folder to the Dirbox at the appropriate
'    position. VB/Windows handles the added items without any further
'    coding.
'
'    Thanks to the contributors in the VB API newsgroups for supplying
'    me with most of my knowledge on the API.
'
'    This code was tested on Win98 VB6. Please report bugs
'    to arthurruhtra@netscape.net



'_______________________________________
'   APIs for show hidden files
'_______________________________________
Private Const MAX_PATH = 260
Private Type FILETIME
        dwLowDateTime As Long
        dwHighDateTime As Long
End Type
Private 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

Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long

Private Const LB_GETCOUNT = &H18B
Private Const LB_INSERTSTRING = &H181
Private Const LB_ERR = (-1)

'private Const FILE_ATTRIBUTE_READONLY = &H1
Private Const FILE_ATTRIBUTE_HIDDEN = &H2
Private Const FILE_ATTRIBUTE_SYSTEM = &H4
Private Const FILE_ATTRIBUTE_DIRECTORY = &H10
'private Const FILE_ATTRIBUTE_ARCHIVE = &H20
'private Const FILE_ATTRIBUTE_NORMAL = &H80
'private Const FILE_ATTRIBUTE_TEMPORARY = &H100
'private Const FILE_ATTRIBUTE_COMPRESSED = &H800

Private Declare Function SendMessageString Lib "user32" Alias "SendMessageA" _
    (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
    ByVal lParam As String) 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


'* bShowSystem - shows directories with both the hidden and system attributes set
'* non-hidden system directories are already shown and are not affected by this
'* you probably shouldn't show hidden system folders (such as the
'  recycle bin and it's raw files)
Private Sub ShowHiddenDirectories(DirCtrl As DirListBox, Optional bShowSystem As Boolean)
    Dim res As Long
    Dim sF As String, sDirPath
    Dim FData As WIN32_FIND_DATA
    Dim fHand As Long, i As Long
    Dim level As Long
    Dim StillOK As Long
    Const HIDDEN_DIRECTORY = FILE_ATTRIBUTE_DIRECTORY Or FILE_ATTRIBUTE_HIDDEN
'     Const LBS_SORT = &H2&

    sDirPath = DirCtrl.Path
    'append trailing slash
    If Right$(sDirPath, 1) <> "\" Then sDirPath = sDirPath & "\"
    
    'get dir path level (i.e. c:\windows\system = 3)
    'LB_GETCOUNT counts all items in dirbox while
    'DirCtrl.ListCount gives only subdirectories
        '    VB method
        '    i = -1
        '    Do While Len(DirCtrl.List(i))
        '        i = i - 1
        '    Loop
        '    level = Abs(i) - 1
    'api
    res = SendMessage(DirCtrl.hwnd, LB_GETCOUNT, 0, 0)
    If res = LB_ERR Then Exit Sub
    level = res - DirCtrl.ListCount
    
    'Find hidden directories
    fHand = FindFirstFile(sDirPath & "*", FData)
    StillOK = fHand
    Do While StillOK > 0
        'check if file is a folder and hidden
        If (FData.dwFileAttributes And HIDDEN_DIRECTORY) >= HIDDEN_DIRECTORY Then
           'continue if we don't care if folder has system attribute
           'or if the folder doesn't have system attribute
           If bShowSystem Or ((FData.dwFileAttributes And FILE_ATTRIBUTE_SYSTEM) = 0) Then
            sF = CutRightAt(FData.cFileName)
            If sF <> "." And sF <> ".." Then
                'add the hidden folder to the dirbox
                
                'it is ordered automatically but incorrectly with LB_ADDSTRING
                'i.e. a hidden folder called A1 would be placed before C:\
'                res = SendMessageString(DirCtrl.hwnd, LB_ADDSTRING, 0, sF)
                
                'move backwards through dirbox and insert alphabetically
                'you could of course use a binary search but for any
                'Win9X system I've seen this would be overkill
                i = DirCtrl.ListCount
                Do
                    If i > 0 Then
                        'compare against part of DirBox's item that is foldername w/o path
                        res = StrComp(sF, Right(DirCtrl.List(i - 1), Len(DirCtrl.List(i - 1)) - Len(sDirPath)), vbTextCompare)
                        If res >= 0 Then 'found insertion point, now add folder
                            'don't add folder if the 2 strings are the same
                            'could occur if you invoked this sub a 2nd time w/o cd-ing
                            If res Then res = SendMessageString(DirCtrl.hwnd, LB_INSERTSTRING, i + level, sF)
                            Exit Do
                        'else keep looking for insertion point
                        End If
                    Else 'folder is first alphabetically
                        If i = 0 Then res = SendMessageString(DirCtrl.hwnd, LB_INSERTSTRING, i + level, sF)
                    End If
                    i = i - 1
                Loop While i >= 0
            End If 'not . or ..
           End If 'system
        End If 'hidden

        StillOK = FindNextFile(fHand, FData)
    Loop

    fHand = FindClose(fHand)
End Sub

'   typical TrimNull function with option to trim at any character
Private Function CutRightAt(NormString As String, Optional ascii As Long = 0) As String
    Dim i As Long
    i = InStr(1, NormString, Chr(ascii), vbBinaryCompare)
    If i Then
        CutRightAt = Left(NormString, i - 1)
    Else
        CutRightAt = NormString
    End If
End Function
'_______________________________________
'   the Form Code - the code above
'   could be moved to a bas module
'   with the obvious change to Public
'   of sub ShowHiddenDirectories
'_______________________________________
Private Sub Dir1_Change()
    ShowHiddenDirectories Dir1, Check1.Value = vbChecked
    File1.Path = Dir1
End Sub

Private Sub Check1_Click()
    If Check1.Value = vbUnchecked Then Dir1.Refresh 'return to non-hidden non-system view
    ShowHiddenDirectories Dir1, Check1.Value = vbChecked
End Sub