Visual Basic Browse/ PIDL / CSIDL Routines
SHBrowseForFolder: Browse for Folders New UI Features
Posted:   Saturday May 17, 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:   BROWSE:
SHBrowseForFolder: Browse Folders Dialog Overview
SHBrowseForFolder: Browse for Folders Dialog
SHBrowseForFolder: Browse for Folders Callback Overview
SHBrowseForFolder: Pre-selecting Folders using a Browse Callback
SHBrowseForFolder: Browse to Obtain Network Machines or Shares

CSIDL / Folders:
SHGetFolderPath: Overview of Shell and ComCtrl Versions, CSIDL Values
SHGetFolderPath: Retrieve Windows Shell Folders (Best Practice)

SHGetSpecialFolderLocation: Retrieve Windows Shell Folder
SHGetKnownFolderPath: Retrieve Windows Known (Shell) Folders under Vista
Pure VB: Using the Shell Application Object to Retrieve Windows Shell Folders

Internet Explorer 4 or better.

This page is wider than I prefer in order to to accommodate the Browse constant's descriptions. It will appear fine pasted into a VB project.

As has been the history with past releases of Internet Explorer, new Shell32 functionality has become available in each version of Internet Explorer's Shell updates or the shell of newer operating systems.

IE4 added the  BIF_EDITBOX and BIF_VALIDATE callback functionality, allowing a Browse Dialog using a callback to retrieve a user's typed-in file or path name.

Shell Version 5 (Windows 2000 and IE5) added BIF_BROWSEINCLUDEFILES which displays the dialog with both the normal folder/virtual folder chosen as well as files under those folders. 

Windows 2000, IE6 and Windows XP can use the BIF_USENEWUI flag providing within the Browse dialog a new user-interface including a larger dialog that can be resized, as well as several new capabilities including drag and drop within the dialog box, a new folder button, item reordering and a right-click context menu containing the standard commands you'd expect when selecting a file system or namespace item.

This demo, loosely based on the original Browse demo code provided to VBnet by Brad Martinez, performs several functions. On load, a combo is populated with strings representing all available Constants, except those for the RISC platform.

Illustrations 1/2/3 show setting up and calling an old-style Browse dialog, returning My Computer as the user's selection. Pictures 4/5/6 repeat this same selection using the new dialog UI and edit box. Figures 7/8/9 show the result of selecting a shortcut when BIF_NOTRANSLATESTARGETS is set.

This demo does not utilize a callback - other pages on VBnet address adding that feature, something that would be trivial for this demo. This means the BIF_VALIDATE flag is of no value as it is meant to be used by the callback to signal the user's changing of the selection in the edit box.

Remember that some of the items listed are available only on later OS versions. Use GetVersionEx() wrappers to restrict feature selection to valid options. The code shows doing this for one option - the BIF_NOTRANSLATETARGETS flag, which when set allows the user to select a shortcut and the dialog will return that shortcut as the full path. Normal pre-XP behavior is to resolve the selected shortcut and return the path to the actual item pointed to by the shortcut.

Finally, it must be noted that while the new features provide access to the contents of virtual folders (i.e. Recycle Bin, Fonts, Internet etc), I can only strongly recommend that you do not use the return values from the Browse dialog to directly manipulate those files, especially Recycle Bin.

 BAS Module Code

 Form Code
This form isn't really too complicated; the Load event will set the appropriate captions. Add a command button (Command1), a combo (Combo1) with Sorted=True, six check boxes (Check1 through Check6) and four textboxes (Text1-Text4). Labels are optional. Size the combo, check boxes and Text3 and Text4 fairly wide. Add the following 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 Const VER_PLATFORM_WIN32_NT As Long = 2
Private Const S_OK  As Long = 0
Private Const MAX_PATH As Long = 260

'BROWSEINFO.ulFlags values
Private Const BIF_RETURNONLYFSDIRS   As Long = &H1 'only file system directories
Private Const BIF_DONTGOBELOWDOMAIN As Long = &H2  'no network folders below domain level
Private Const BIF_STATUSTEXT As Long = &H4         'include status area for callback
Private Const BIF_RETURNFSANCESTORS As Long = &H8  'only return file system ancestors
Private Const BIF_EDITBOX As Long = &H10           'add edit box 
Private Const BIF_NEWDIALOGSTYLE As Long = &H40    'use the new dialog layout
Private Const BIF_UAHINT As Long = &H100
Private Const BIF_NONEWFOLDERBUTTON As Long = &H200 'hide new folder button
Private Const BIF_NOTRANSLATETARGETS As Long = &H400 'return lnk file
Private Const BIF_BROWSEFORCOMPUTER As Long = &H1000 'only return computers
Private Const BIF_BROWSEFORPRINTER As Long = &H2000 'only return printers
Private Const BIF_BROWSEINCLUDEFILES As Long = &H4000 'browse for everything
Private Const BIF_SHAREABLE As Long = &H8000 'sharable resources, requires BIF_USENEWUI

'class ID values
Private Const CSIDL_DESKTOP As Long = &H0
Private Const CSIDL_INTERNET As Long = &H1
Private Const CSIDL_PROGRAMS As Long = &H2
Private Const CSIDL_CONTROLS As Long = &H3
Private Const CSIDL_PRINTERS As Long = &H4
Private Const CSIDL_PERSONAL As Long = &H5
Private Const CSIDL_FAVORITES As Long = &H6
Private Const CSIDL_STARTUP As Long = &H7
Private Const CSIDL_RECENT As Long = &H8
Private Const CSIDL_SENDTO As Long = &H9
Private Const CSIDL_BITBUCKET As Long = &HA
Private Const CSIDL_STARTMENU As Long = &HB
Private Const CSIDL_MYDOCUMENTS As Long = &HC
Private Const CSIDL_MYMUSIC As Long = &HD
Private Const CSIDL_MYVIDEO As Long = &HE
Private Const CSIDL_UNUSED1 As Long = &HF '&HF not currently implemented
Private Const CSIDL_DRIVES As Long = &H11
Private Const CSIDL_NETWORK As Long = &H12
Private Const CSIDL_NETHOOD As Long = &H13
Private Const CSIDL_FONTS As Long = &H14
Private Const CSIDL_TEMPLATES As Long = &H15
Private Const CSIDL_COMMON_STARTMENU As Long = &H16
Private Const CSIDL_COMMON_PROGRAMS As Long = &H17
Private Const CSIDL_COMMON_STARTUP As Long = &H18
Private Const CSIDL_APPDATA As Long = &H1A
Private Const CSIDL_PRINTHOOD As Long = &H1B
Private Const CSIDL_LOCAL_APPDATA As Long = &H1C
Private Const CSIDL_ALTSTARTUP As Long = &H1D
Private Const CSIDL_INTERNET_CACHE As Long = &H20
Private Const CSIDL_COOKIES As Long = &H21
Private Const CSIDL_HISTORY As Long = &H22
Private Const CSIDL_COMMON_APPDATA As Long = &H23
Private Const CSIDL_WINDOWS As Long = &H24
Private Const CSIDL_SYSTEM As Long = &H25
Private Const CSIDL_PROGRAM_FILES As Long = &H26
Private Const CSIDL_MYPICTURES As Long = &H27
Private Const CSIDL_PROFILE As Long = &H28
Private Const CSIDL_SYSTEMX86 As Long = &H29 'RISC only
Private Const CSIDL_PROGRAM_FILESX86 As Long = &H2A 'RISC only
Private Const CSIDL_PROGRAM_FILES_COMMONX86 As Long = &H2C 'RISC only
Private Const CSIDL_ADMINTOOLS As Long = &H30
Private Const CSIDL_CONNECTIONS As Long = &H31
Private Const CSIDL_COMMON_MUSIC As Long = &H35
Private Const CSIDL_COMMON_PICTURES As Long = &H36
Private Const CSIDL_COMMON_VIDEO As Long = &H37
Private Const CSIDL_RESOURCES As Long = &H38
Private Const CSIDL_COMMON_OEM_LINKS As Long = &H3A
Private Const CSIDL_CDBURN_AREA As Long = &H3B
Private Const CSIDL_UNUSED2 As Long = &H3C '&H3C not currently implemented

'special flags
Private Const CSIDL_FLAG_PER_USER_INIT As Long = &H800 
Private Const CSIDL_FLAG_NO_ALIAS As Long = &H1000 
Private Const CSIDL_FLAG_DONT_VERIFY As Long = &H4000 
Private Const CSIDL_FLAG_CREATE As Long = &H8000 
Private Const CSIDL_FLAG_MASK As Long = &HFF00 

'windows-defined type OSVERSIONINFO
  OSVSize         As Long
  dwVerMajor      As Long
  dwVerMinor      As Long
  dwBuildNumber   As Long
  PlatformID      As Long
  szCSDVersion    As String * 128
End Type

'parameters for SHBrowseForFolder
Private Type BROWSEINFO    'BI
    hOwner As Long
    pidlRoot As Long
    pszDisplayName As String
    lpszTitle As String
    ulFlags As Long
    lpfn As Long
    lParam As Long
    iImage As Long
End Type

Private Declare Function SHGetPathFromIDList Lib "shell32.dll" _
   Alias "SHGetPathFromIDListA" _
  (ByVal pidl As Long, _
   ByVal pszPath As String) As Long

Private Declare Function SHBrowseForFolder Lib "shell32.dll" _
   Alias "SHBrowseForFolderA" _
  (lpBrowseInfo As BROWSEINFO) As Long

Private Declare Function SHGetSpecialFolderLocation Lib "shell32.dll" _
  (ByVal hwndOwner As Long, _
   ByVal nFolder As Long, _
   pidl As Long) As Long

Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" _
  (lpVersionInformation As OSVERSIONINFO) As Long

Private Declare Sub CoTaskMemFree Lib "ole32.dll" _
  (ByVal pv As Long)

Private Sub Form_Load()
   Command1.Caption = "Browse"
   Check1.Caption = "Include files as well as folders in dialog"
   Check2.Caption = "Use new dialog style (resizable w/new folder button)"
   Check3.Caption = "Include edit box"
   Check4.Caption = "Use UA Hint (edit box overrides)"
   Check5.Caption = "Hide the New Folder button"
   Check6.Caption = "Return shortcut; don't traverse to file ( XP or later )"
   Text1.Text = ""
   Text2.Text = ""
   Text3.Text = ""
   Text4.Text = ""
   Check6.Enabled = IsWinXPPlus()
   Call LoadCombo
End Sub

Private Sub Command1_Click()

   Dim dwFlags As Long
   Dim sTitle As String
   Dim csidl As Long
  'build dwFlags according to the options selected
   If Check1.Value = vbChecked Then dwFlags = dwFlags Or BIF_BROWSEINCLUDEFILES
   If Check2.Value = vbChecked Then dwFlags = dwFlags Or BIF_NEWDIALOGSTYLE
   If Check3.Value = vbChecked Then dwFlags = dwFlags Or BIF_EDITBOX
   If Check4.Value = vbChecked Then dwFlags = dwFlags Or BIF_UAHINT
   If Check5.Value = vbChecked Then dwFlags = dwFlags Or BIF_NONEWFOLDERBUTTON
   If Check6.Value = vbChecked Then dwFlags = dwFlags Or BIF_NOTRANSLATETARGETS
   sTitle = Combo1.List(Combo1.ListIndex)
   csidl = Combo1.ItemData(Combo1.ListIndex)
   Text4.Text = Browse(csidl, dwFlags, sTitle)
End Sub

Private Sub Combo1_Click()

   Dim csidl As Long
   csidl = Combo1.ItemData(Combo1.ListIndex)
   Text1.Text = csidl
   Text2.Text = "&H" & CStr(Hex(csidl))
End Sub

Private Sub Check2_Click()

   Check3.Enabled = Check2.Value = vbChecked
   Check4.Enabled = Check2.Value = vbChecked
   Check5.Enabled = Check2.Value = vbChecked

End Sub

Private Function Browse(csidl As Long, BIF_FLAGS As Long, sTitle As String) As String

  Dim pidl As Long
  Dim sPath As String
  Dim pos As Integer
  'Fill BROWSEINFO structure data
   With bi
      .hOwner = Me.hWnd
      .pidlRoot = CSIDLToPIDL(csidl)
      .lpszTitle = "Browsing " & sTitle
      .ulFlags = BIF_FLAGS
      .pszDisplayName = Space$(MAX_PATH)
   End With
  'show dialog returning pidl to selected item
   pidl = SHBrowseForFolder(bi)
  'if pidl is valid, parse & return the user's selection
   sPath = Space$(MAX_PATH)
   If SHGetPathFromIDList(ByVal pidl, ByVal sPath) Then
     'SHGetPathFromIDList returns the absolute
     'path to the selected item
      pos = InStr(sPath, Chr$(0))
      If pos > 0 Then Browse = Left(sPath, pos - 1)

   End If

  'pszDisplayName contains the string
  'representing the users last selection.
  'Even when SHGetPathFromIDList is empty,
  'this should return the selection, making
  'it the choice for obtaining user information
  'when selecting Printers, Control Panel etc,
  'or any of the other virtual folders that
  'do not normally return a path
   pos = InStr(bi.pszDisplayName, Chr$(0))
   If pos > 0 Then
      Text3.Text = Left(bi.pszDisplayName, pos - 1)
      Text3.Text = ""
   End If
  'free the pidl
   Call CoTaskMemFree(pidl)
End Function

Private Function CSIDLToPIDL(ByVal csidl As Long) As Long

  Dim pidl As Long

  If csidl > 0 Then
      If SHGetSpecialFolderLocation(Me.hWnd, csidl, pidl) = S_OK Then
         CSIDLToPIDL = pidl
      End If
      CSIDLToPIDL = 0&
   End If
End Function

Private Function IsWinXPPlus() As Boolean

  'returns True if running Windows XP or later

   osv.OSVSize = Len(osv)

   If GetVersionEx(osv) = 1 Then
      IsWinXPPlus = (osv.PlatformID = VER_PLATFORM_WIN32_NT) And _
                    (osv.dwVerMajor >= 5 And osv.dwVerMinor >= 1)

   End If

End Function

Private Sub LoadCombo()

   With Combo1

      .AddItem "Desktop (default browse)":
      .ItemData(.NewIndex) = CSIDL_DESKTOP

      .AddItem "Internet Explorer (icon on desktop)"
      .ItemData(.NewIndex) = CSIDL_INTERNET

      .AddItem "Start Menu\Programs"
      .ItemData(.NewIndex) = CSIDL_PROGRAMS

      .AddItem "Control Panel"
      .ItemData(.NewIndex) = CSIDL_CONTROLS

      .AddItem "Printers"
      .ItemData(.NewIndex) = CSIDL_PRINTERS

      .AddItem "My Documents"
      .ItemData(.NewIndex) = CSIDL_PERSONAL

      .AddItem "Favorites (Current User)"
      .ItemData(.NewIndex) = CSIDL_FAVORITES

      .AddItem "Start Menu\Programs\Startup"
      .ItemData(.NewIndex) = CSIDL_STARTUP

      .AddItem "Recent (Current User)"
      .ItemData(.NewIndex) = CSIDL_RECENT

      .AddItem "SendTo (Current User)"
      .ItemData(.NewIndex) = CSIDL_SENDTO

      .AddItem "Recycle Bin (desktop)"
      .ItemData(.NewIndex) = CSIDL_BITBUCKET

      .AddItem "Start Menu (Current User)"
      .ItemData(.NewIndex) = CSIDL_STARTMENU

      .AddItem "WinXP+ : Logical My Documents desktop icon"
      .ItemData(.NewIndex) = CSIDL_MYDOCUMENTS
      .AddItem "WinXP+ : My Music folder"
      .ItemData(.NewIndex) = CSIDL_MYMUSIC
      .AddItem "WinXP+ : My Videos folder"
      .ItemData(.NewIndex) = CSIDL_MYVIDEO
      .AddItem "Desktop Directory (Current User)"
      .ItemData(.NewIndex) = CSIDL_DESKTOPDIRECTORY

      .AddItem "My Computer"
      .ItemData(.NewIndex) = CSIDL_DRIVES

      .AddItem "Network Neighborhood"
      .ItemData(.NewIndex) = CSIDL_NETWORK

      .AddItem "NetHood (Current User)"
      .ItemData(.NewIndex) = CSIDL_NETHOOD

      .AddItem "Fonts"
      .ItemData(.NewIndex) = CSIDL_FONTS

      .AddItem "Templates"
      .ItemData(.NewIndex) = CSIDL_TEMPLATES
      .AddItem "Start Menu (All Users) (NT or later)"
      .ItemData(.NewIndex) = CSIDL_COMMON_STARTMENU

      .AddItem "Programs (All Users) (NT or later)"
      .ItemData(.NewIndex) = CSIDL_COMMON_PROGRAMS

      .AddItem "Startup (All Users) (NT or later)"
      .ItemData(.NewIndex) = CSIDL_COMMON_STARTUP

      .AddItem "Desktop Directory (All Users)"

      .AddItem "Application Data (Current User)"
      .ItemData(.NewIndex) = CSIDL_APPDATA

      .AddItem "PrintHood (Current User)"
      .ItemData(.NewIndex) = CSIDL_PRINTHOOD

      .AddItem "Win2k+ : Application Data (Current User, non roaming)"
      .ItemData(.NewIndex) = CSIDL_LOCAL_APPDATA

      .AddItem "Non-localized Startup"
      .ItemData(.NewIndex) = CSIDL_ALTSTARTUP

      .AddItem "Non-localized Common Startup (NT or later)"
      .ItemData(.NewIndex) = CSIDL_COMMON_ALTSTARTUP

      .AddItem "Common Favorites"
      .ItemData(.NewIndex) = CSIDL_COMMON_FAVORITES

      .AddItem "Internet Cache"
      .ItemData(.NewIndex) = CSIDL_INTERNET_CACHE

      .AddItem "Internet Cookies"
      .ItemData(.NewIndex) = CSIDL_COOKIES

      .AddItem "Internet History"
      .ItemData(.NewIndex) = CSIDL_HISTORY

      .AddItem "Win2k+ : Application Data (All Users)"
      .ItemData(.NewIndex) = CSIDL_COMMON_APPDATA

      .AddItem "Win2k+ : Windows Directory"
      .ItemData(.NewIndex) = CSIDL_WINDOWS

      .AddItem "Win2k+ : System Directory"
      .ItemData(.NewIndex) = CSIDL_SYSTEM

      .AddItem "Win2k+ : Program Files"
      .ItemData(.NewIndex) = CSIDL_PROGRAM_FILES

      .AddItem "Win2k+ : My Pictures"
      .ItemData(.NewIndex) = CSIDL_MYPICTURES

      .AddItem "Win2k+ : User Profile (Current User)"
      .ItemData(.NewIndex) = CSIDL_PROFILE

      .AddItem "Win2k+ : Program Files\Common (NT or later)"
      .ItemData(.NewIndex) = CSIDL_PROGRAM_FILES_COMMON

     .AddItem "Templates (All Users) (NT or later)"
     .ItemData(.NewIndex) = CSIDL_COMMON_TEMPLATES

     .AddItem "Documents (All Users) (NT or later)"
     .ItemData(.NewIndex) = CSIDL_COMMON_DOCUMENTS

     .AddItem "Win2k+ : Administrative Tools (All Users)"
     .ItemData(.NewIndex) = CSIDL_COMMON_ADMINTOOLS

     .AddItem "Win2k+ : Administrative Tools (Current User)"
     .ItemData(.NewIndex) = CSIDL_ADMINTOOLS
     .AddItem "WinXP+ : Network and Dial-up Connections"
     .ItemData(.NewIndex) = CSIDL_CONNECTIONS
     .AddItem "WinXP+ : (shared music) All Users\My Music"
     .ItemData(.NewIndex) = CSIDL_COMMON_MUSIC
     .AddItem "WinXP+ : (shared pictures) All Users\My Pictures"
     .ItemData(.NewIndex) = CSIDL_COMMON_PICTURES
     .AddItem "WinXP+ : (shared video) All Users\My Video"
     .ItemData(.NewIndex) = CSIDL_COMMON_VIDEO
     .AddItem "WinXP+ : Resource Directory (themes parent folder)"
     .ItemData(.NewIndex) = CSIDL_RESOURCES
     .AddItem "WinXP+ : Localized Resource Directory"

     .AddItem "WinXP+ : Links to All Users OEM specific apps"
     .ItemData(.NewIndex) = CSIDL_COMMON_OEM_LINKS
     .AddItem "WinXP+ : CD Burning (USERPROFILE\Local Settings\Application Data\Microsoft\)"
     .ItemData(.NewIndex) = CSIDL_CDBURN_AREA
     .AddItem "WinXP+ : Computers Near Me (computered from Workgroup membership)"
     .ItemData(.NewIndex) = CSIDL_COMPUTERSNEARME
     .ListIndex = 3  'desktop (default browse)

   End With

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