
It's possible to have complete control over what items are shown in the SHBrowseForFolder dialog. The picture above shows a filter of *.exe applied to a dialog with the BIF_BROWSEINCLUDEFILES option, but you can filter in a wide variety of ways as the IShellFolder and pidl for each item is passed, allowing you to get the name and compare by string and properties, as in the demo, or anything else you could want. The project notes where you could even filter by SHCONTF options.
This is accomplished through the BFFM_IUNKNOWN message that is received in the callback function. A lot of places have mentioned what it's for, but I wanted to show the actual details of using that message to set up a filter.
First, you create a class module that implements the IFolderFilter interface and create an instance of it before calling the dialog. The GetEnumFlags method is where you can filter by SHCONTF, but this demo is mainly concerned with examining each item in the ShouldShow method. Whether to show the item or not is based on the return code, so the class module function is swapped out to a function in the module. Here's the demo filters files, but not folders, according to the pattern specified in the text box:
Code:
Public Function ShouldShowVB(ByVal this As IFolderFilter, ByVal psf As IShellFolder, ByVal pidlFolder As Long, ByVal pidlItem As Long) As Long
Dim psi As IShellItem
Dim lpName As Long, sName As String
Dim dwAtr As Long
On Error GoTo e0
SHCreateItemWithParent 0&, psf, pidlItem, IID_IShellItem, psi
If (psi Is Nothing) = False Then
psi.GetAttributes SFGAO_FILESYSTEM Or SFGAO_FOLDER, dwAtr
If ((dwAtr And SFGAO_FILESYSTEM) = SFGAO_FILESYSTEM) And ((dwAtr And SFGAO_FOLDER) = 0) Then 'is in normal file system, is not a folder
psi.GetDisplayName SIGDN_PARENTRELATIVEPARSING, lpName
sName = LPWSTRtoStr(lpName)
Debug.Print "ShouldShow?" & sName & "|" & gSpec
If PathMatchSpecW(StrPtr(sName), StrPtr(gSpec)) Then
ShouldShowVB = S_OK 'should show
Else
ShouldShowVB = S_FALSE 'should not show
End If
End If
Else
Debug.Print "ShouldShow.NoItem"
End If
Exit Function
e0:
Debug.Print "ShouldShowVB.Error->" & Err.Description
End Function
Code:
Public Function BrowseCallbackProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal lParam As Long, ByVal lpData As Long) As Long
Dim pSite As IFolderFilterSite
Dim pUnk As oleexp.IUnknown
Select Case uMsg
Case BFFM_IUNKNOWN
'lParam contains a pointer to an IUnknown that implements IFolderFilterSite
Debug.Print "Received BFFM_IUNKNOWN"
vbaObjSetAddRef pUnk, lParam
Debug.Print "Set obj"
If (pUnk Is Nothing) = False Then
Set pSite = pUnk
If (pSite Is Nothing) = False Then
Debug.Print "Setting filter"
pSite.SetFilter cFilter
Debug.Print "Filter set"
Else
Debug.Print "Failed to set pSite"
End If
Else
Debug.Print "Failed to set pUnk"
Set cFilter = Nothing
End If
End Select
End Function
Requirements
-The demo project requires Windows Vista or newer, although it could theoretically be reworked to support XP.
-oleexp 4.1 or newer (this project requires a bug fixed only in 4.1, not 4.0)
-mIID.bas (included in the oleexp download)