Results 1 to 40 of 48

Thread: [VB6] Using the new IFileDialog interface for customizable Open/Save (TLB, Vista+)

Threaded View

  1. #1

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

    [VB6] Using the new IFileDialog interface for customizable Open/Save (TLB)

    LaVolpe put out an excellent class module that implements these interfaces, but I've been working on using them through a different approach for some time and wanted to post it as well since, while requiring a TLB, it offers advantages like having IShellItem as a declarable type used all over projects, interfaces, and APIs.

    IFileDialog / IFileOpenDialog / IFileSaveDialog

    IFileSaveDialog and IFileOpenDialog were introduced in Windows Vista to supersede the GetOpenFileName/GetSaveFileName API, and offer several advantages (although certainly some drawbacks). Windows provides a default implementation, so they're fairly easy to use in VB. Among the advantages is easy addition of custom controls, something that was not previously possible in VB (or at least so hard no one bothered).

    PROJECT UPDATED 2016 Nov 24th
    The attached sample project has been changed to reference oleexp.tlb 4.0 or higher, which supercedes the previous references to both oleexp3.tlb and olelib.tlb. That is the only change.


    PROJECT UPDATED
    Since I did it for myself, I thought I would share. If you're using the Advise sink, you might have noted that some events, like OnFolderChanging, offered the ability to change the response if you returned something. But since it has to be a Sub in order to be the HRESULT VB requires it to be but then discards and forces it into a sub, this wasn't possible. The new versions shows how to use a vtable-swap to replace the class module sub with a regular function that can return a variable.

    Also note that to reduce the proliferation of different versions of my typelib, I'm no longer including whatever version happens to be current at the time. Always go to the main project thread for the latest version.

    The typelib:
    This project uses oleexp.tlb, which is my own fork/expansion of olelib.tlb.
    Minimum required oleexp version is 4.0. Add under Project->References. Required only for IDE; not needed with compiled app.

    Get it here.

    IShellItem:
    For modern Windows, IShellItem is becoming more and more important. This project will familiarize you with using this object. The typelib based approach to this offers the advantage of being able to use IShellItem and related types project-wide, and pass them around easily, both within the project and to APIs and interfaces that use them. The sample project has helper functions that show how to create and manipulate IShellItem and related functions.
    --

    The attached ZIP includes a sample project illustrating the use of the dialogs. There's examples for a very simple Open, a typical Open dialog, a simple Save dialog, a multi-file-open dialog, and a highly customized open dialog.

    In Your Own Project
    To use IFileDialog-based Open/Save, your project needs to add a reference to olelib and oleexp. cFileDialogEvents.cls is required only if you want to receive feedback while the dialog is open (including from added custom controls).

    -----------------------------------
    Here's how simple a basic Open File dialog is with this tlb:

    Code:
    Dim fodSimple As FileOpenDialog
    Dim isiRes As IShellItem
    Dim lPtr As Long
    
    Set fodSimple = New FileOpenDialog
    
    With fodSimple
        .SetTitle "Simple File Open"
        .Show Me.hWnd
        
        .GetResult isiRes
        isiRes.GetDisplayName SIGDN_FILESYSPATH, lPtr
        Text1.Text = BStrFromLPWStr(lPtr, True)
    End With
    Set isiRes = Nothing
    Set fodSimple = Nothing
    That's all it takes to get the very simplest Open File dialog going, and shows how the class is used.

    Events
    While previously subclassing was required to receive event notifications while the dialog was displayed, this is now accomplished simply by adding the optional cFileDialogEvents class and calling the .Advise method.
    This same class also receives events from any custom controls added.

    Customization
    I thought that even with this approach, it was going to be hard. But the class is set up to make this a very easy process.
    To add a simple label and a button,
    Code:
    Dim fdc As IFileDialogCustomize
    Set fdc = pDlg 'pDlg is the FileOpenDialog object
    
    pDlg.Advise cFDE, 0 'the events class
    
    fdc.AddText 1000, "This is a test label."
    fdc.AddPushButton 1001, "New Button"
    With that, the events class will have its OnButtonClicked method called when its clicked.


    Here's the full sample code that produces the dialog in the above screenshot:

    Code:
    On Error Resume Next 'A major error is thrown when the user cancels the dialog box
    List1.Clear
    Dim isiRes As IShellItem
    
    Dim isiDef As IShellItem 'default folder
    Dim FOLDERID_Pictures As UUID
    Dim pidlDef As Long
    
    Dim lPtr As Long
    Dim lOptions As FILEOPENDIALOGOPTIONS
    
    'Set up filter
    Dim FileFilter() As COMDLG_FILTERSPEC
    ReDim FileFilter(1)
    
    FileFilter(0).pszName = "Image Files"
    FileFilter(0).pszSpec = "*.jpg;*.gif;*.bmp"
    
    FileFilter(1).pszName = "All Files"
    FileFilter(1).pszSpec = "*.*"
    
    'set up default folder: note that this only shows the very first time
    '                       after that, the last directory is default
    '                       automatically. override with SetFolder.
    Call CLSIDFromString(StrPtr(fidPictures), FOLDERID_Pictures)
    Call SHGetKnownFolderIDList(FOLDERID_Pictures, 0, 0, pidlDef)
    If pidlDef Then
        Call SHCreateShellItem(0, 0, pidlDef, isiDef)
    End If
    
    Set fod = New FileOpenDialog
    Set cEvents = New cFileDialogEvents
    
    With fod
        .Advise cEvents, 0
        .SetTitle "Select Thine File Sir"
        .GetOptions lOptions
        lOptions = lOptions Or FOS_FILEMUSTEXIST Or FOS_FORCESHOWHIDDEN 'just an example of options... shows hidden files even if they're normally not shown
        .SetOptions lOptions
        .SetOkButtonLabel "Mine File"
        .SetFileNameLabel "Look! A custom file label!!!"
        
        If (isiDef Is Nothing) = False Then
            .SetFolder isiDef
        End If
        .SetFileTypes 2, VarPtr(FileFilter(0).pszName)
        
        'Now we'll begin adding custom controls
        'First, we set up the interface
        'The control IDs can be any number, and should
        'really be stored as consts
        Set fdc = fod
        
        fdc.AddText 1000, "This is a test label."
        
        fdc.AddPushButton 1001, "New Button"
        fdc.MakeProminent 1001 'Moves to by the open button; only checkboxes, buttons, combos, menus can be made prominent
        
        fdc.AddPushButton 1002, "Some Other Button"
        
        fdc.StartVisualGroup 2000, "VG-1"
        fdc.AddCheckButton 2001, "Checkers!", 1
        fdc.AddSeparator 2002
        'For menus, and radio buttons/combos, first you add the control, then add items with AddControlItem
        fdc.AddMenu 2010, "Checkers?"
        fdc.AddControlItem 2010, 3000, "Pretty good."
        fdc.AddControlItem 2010, 3001, "Pretty bad."
        fdc.AddControlItem 2010, 3002, "Neutral!"
        fdc.AddEditBox 2003, "Other."
        fdc.EndVisualGroup
        
        fdc.StartVisualGroup 4000, "Radio station?"
        fdc.AddRadioButtonList 4001
        fdc.AddControlItem 4001, 4010, "Radio Station Alpha"
        fdc.AddControlItem 4001, 4011, "Radio Station Beta"
        fdc.EndVisualGroup
        
        fdc.AddComboBox 5000
        fdc.AddControlItem 5000, 5010, "Combo Alpha"
        fdc.AddControlItem 5000, 5011, "Combo Beta"
        fdc.AddControlItem 5000, 5012, "Combo Gamma"
        fdc.SetSelectedControlItem 5000, 5011
    
    
        .Show Me.hWnd
        
        .GetResult isiRes
        isiRes.GetDisplayName SIGDN_FILESYSPATH, lPtr
        Text1.Text = BStrFromLPWStr(lPtr, True)
    End With
        
    If pidlDef Then Call CoTaskMemFree(pidlDef)
    Set isiRes = Nothing
    Set isiDef = Nothing
    Set fod = Nothing
    See Also:
    For another customization of IFileDialog, advanced filtering of items to do things like implement a 'show all except...' filter with the .SetFilter method, see
    [VB6] Exclude file types from Open/Save Dialogs ('all except...'): IShellItemFilter



    twinBASIC 64bit compatible version at https://github.com/fafalone/MiscDemos
    Attached Files Attached Files
    Last edited by fafalone; Feb 28th, 2026 at 01:47 PM. Reason: Added link to new project with additional customizations

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