Results 1 to 1 of 1

Thread: [VB6] SHBrowseForFolder - Custom filter for shown items: BFFM_IUNKNOWN/IFolderFilter

Threaded View

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,654

    [VB6] SHBrowseForFolder - Custom filter for shown items: BFFM_IUNKNOWN/IFolderFilter


    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
    Now that the filter object and routine are good to go, it needs to be assigned to the dialog. When the BFFM_IUNKNOWN message fires, the lParam contains a pointer to an IUnknown object which implements IFolderFilterSite, which contains the call to assign our filter class. If the messages fires but the object is Nothing, the filter class needs to be released and reset, otherwise a subsequent call to SHBrowseDialog won't be filtered.
    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
    And that's about it. The rest is just calling the dialog like normal (+making a new instance of the cFolderFilter class first).

    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)



    -------

    twinBASIC 64bit compatible version at https://github.com/fafalone/MiscDemos
    Attached Files Attached Files
    Last edited by fafalone; Nov 15th, 2025 at 04:25 AM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width