Results 1 to 39 of 39

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

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    [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
    Attached Files Attached Files
    Last edited by fafalone; Mar 17th, 2020 at 05:30 AM. Reason: Added link to new project with additional customizations

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    Project has been updated to show how to do things like respond to the OnFolderChanging event to return a value to stop the change, by swapping the class module sub for a function with SwapVTableEntry().

  3. #3
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

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

    Quote Originally Posted by fafalone View Post
    Project has been updated to show how to do things like respond to the OnFolderChanging event to return a value to stop the change, by swapping the class module sub for a function with SwapVTableEntry().
    You are so good at such advance stuff. Could you please make TLB for GDI+,DirectShow,DirectX?

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    As soon as I have a few thousand spare hours I'll get right on that

    But search around a little... http://www.vbcode.com/asp/showzip.as....zip&theID=389 would be a good starting point for DirectX. GDI+... isn't that all available through exported DLL functions? No advantage (and some disadvantages) to using a TLB to declare the apis.

  5. #5
    New Member
    Join Date
    Jan 2009
    Posts
    10

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

    Hallo there,
    I'm trying to use IFileDialog.
    I added a custom button as shown bellow:
    fdc.AddPushButton 1001, "Abandon"
    fdc.MakeProminent 1001 'Moves to by the open button; only checkboxes, buttons, combos, menus can be made prominent
    and I catch the click on it using the FD_ButtonClick event.
    Everything perfect so far. But when the user clicks it I need to return to the calling Form. How is it done? How do I quit the Dialog box just if the user clicked on Cancel button?

    Another question: is it possible to place the Dialog box in the position on the screen I desire?

    Appreciate your reply
    Slobodan Dijaković
    Casa Bustelli
    6864 Arzo
    Switzerland

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    That seems to be a glitch with interface itself, as there's no code in there that is preventing the closing. Instead, you'll need to use the .Close method.

    To place the dialog somewhere on the screen, in one of the events that's called when the dialog is constructed, such as OnFolderChange, you can use this method I ported from a c++ example on MSDN to get the hWnd:
    Code:
    Public Sub IFileDialogEvents_OnFolderChange(ByVal pdf As IFileDialog)
    
    Dim pUnk As olelib.IUnknown
    Dim pOle As IOleWindow
    Dim hWnd As Long
    
    Set pUnk = pdf
    pUnk.QueryInterface IID_IOleWindow, pOle
    hWnd = pOle.GetWindow
    Debug.Print "Got hwnd=" & hWnd
    Call MoveWindow(hWnd, 100, 100, 200, 200, 1)
    
    Set pOle = Nothing
    End Sub
    You can use any of the APIs with the hWnd... with the above code for some reason it will move the dialog but won't change the width and height. But since you've got the hWnd you can play around a little.

    For reference,
    Code:
    Public Declare Function MoveWindow Lib "user32" (ByVal hWnd As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long
    
    Public Function IID_IOleWindow() As UUID
    '00000114-0000-0000-C000-000000000046
    Static IID As UUID
     If (IID.Data1 = 0) Then Call DEFINE_UUID(IID, &H114, CInt(&H0), CInt(&H0), &HC0, &H0, &H0, &H0, &H0, &H0, &H0, &H46)
      IID_IOleWindow = IID
    
    End Function
    Public Sub DEFINE_UUID(Name As UUID, l As Long, w1 As Integer, w2 As Integer, B0 As Byte, b1 As Byte, b2 As Byte, B3 As Byte, b4 As Byte, b5 As Byte, b6 As Byte, b7 As Byte)
      With Name
        .Data1 = l
        .Data2 = w1
        .Data3 = w2
        .Data4(0) = B0
        .Data4(1) = b1
        .Data4(2) = b2
        .Data4(3) = B3
        .Data4(4) = b4
        .Data4(5) = b5
        .Data4(6) = b6
        .Data4(7) = b7
      End With
    End Sub
    Last edited by fafalone; Apr 21st, 2015 at 07:16 PM.

  7. #7
    New Member
    Join Date
    Jan 2009
    Posts
    10

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

    Hello "fafalone" (it sounds so italian).
    I very much appreciate your answer and will soon have an opportunity to put it into testing phase.
    Be in touch.

    Slobodan Dijaković
    Casa Bustelli
    6864 Arzo
    Switzerland

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    Also regarding the dialog staying open, I've noticed that if you use the swapped vtable version of OnFileOK, it will close correctly as long as the return value isn't changed.

  9. #9
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

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

    I've been experimenting a bit with this, and it looks very nice so far, thanks for your work on it.

    Couple of questions/things I noticed:

    • In your demo, after clicking the custom dialog option, then closing the window, then clicking the Multi-Open button and closing the window, the demo will crash with an Automation Error on the .Show method call. I haven't been able to figure out why yet, but thought you might want to investigate.
    • Do you have an example of how to set the initial folder to a specific path as opposed to a known folder path like Pictures?


    Thanks!

  10. #10
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

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

    To open the file dialog at an arbitrary path, first you need to add the following declarations and constants at the module level:

    Code:
    Private Declare Function SHCreateItemFromParsingName Lib "shell32" (ByVal p_Path As Long, ByVal p_BindCtx As Long, p_RefIID As Any, p_IShellItem As IShellItem) As Long
    
    Private Const IID_IShellItem = "{43826d1e-e718-42ee-bc55-a1e261c37bfe}"
    Then in the method where you are showing the file dialog, you must convert the above IID string to a CLSID and create a shell item from your arbitrary path as follows:

    Code:
    Dim l_RefIid As UUID
    Dim l_Path As String
    Dim isiDef as IShellItem
    
    l_Path = "C:\windows\" ' The file dialog will open in this folder
    
    If CLSIDFromString(StrPtr(IID_IShellItem), l_RefIid) = S_OK Then
       If SHCreateItemFromParsingName(StrPtr(l_Path), 0&, l_RefIid, isiDef) <> S_OK Then
          ' Couldn't get item from path
          Debug.Assert False
       End If
    End If
    Finally, before calling the Show method of the file dialog, call the SetFolder method with the shell item as follows:

    Code:
        If Not isiDef Is Nothing Then
            .SetFolder isiDef
        End If
    Here's a full method based on fafalone's demo code (drop in replacement for Command1_Click):

    Code:
    Private Declare Function SHCreateItemFromParsingName Lib "shell32" (ByVal p_Path As Long, ByVal p_BindCtx As Long, p_RefIID As Any, p_IShellItem As IShellItem) As Long
    
    Private Const IID_IShellItem = "{43826d1e-e718-42ee-bc55-a1e261c37bfe}"
    
    Private Sub Command1_Click()
       'Now we'll do an Open dialog with a little more
       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 hToken As Long
       Dim lPtr As Long
       Dim lOptions As FILEOPENDIALOGOPTIONS
       Dim l_RefIid As UUID
       Dim l_Path As String
       
       '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.
    
       l_Path = "C:\Windows"
       
       If CLSIDFromString(StrPtr(IID_IShellItem), l_RefIid) = S_OK Then
          If SHCreateItemFromParsingName(StrPtr(l_Path), 0&, l_RefIid, isiDef) <> S_OK Then
             ' Couldn't get item from path
             Debug.Assert False
          End If
       End If
    
       'isiDef.GetDisplayName SIGDN_FILESYSPATH, lPtr
    
       Set fodSimple = New FileOpenDialog
       Set cEvents = New cFileDialogEvents
    
       With fodSimple
          .Advise cEvents, hToken
          .SetTitle "Select Thine File Sir"
    
          'When setting options, you should first get them
          .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!!!"
    
          .SetFileTypes 2, VarPtr(FileFilter(0).pszName)
    
          If isiDef Is Nothing Then
             MsgBox "No shell item available!"
          Else
             .SetFolder isiDef
          End If
    
          .Show Me.hWnd
    
          .GetResult isiRes
    
          '.Unadvise hToken
          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 cEvents = Nothing
       Set fodSimple = Nothing
    End Sub
    Last edited by jpbro; Aug 5th, 2015 at 03:11 PM. Reason: Added demo code

  11. #11

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    If you're hardcoding the path that's fine, but if you're loading it from somewhere that's going to be user-defined or from a folder browse dialog, my preferred way for getting IShellItem is to work with a pidl for full Unicode support:

    Code:
    Dim pidlDef As Long
    Dim isiDef As IShellItem
    
    pidlDef = ILCreateFromPathW(StrPtr(path)) 'here you can substitute any other way of getting a pidl, such as the return from SHBrowseForFolder
    Call SHCreateItemFromIDList(pidlDef, IID_IShellItem, isiDef)
    IShellItem is something that's going to come up a lot when working with the Vista+ shell.


    -------
    Regarding the Automation Error... oftentimes it's not an error. For some reason or another when an action is cancelled/the dialog is closed without picking a file, it throws that "error" which is usually described as 'user cancelled action' or something like that IIRC.
    If it's a true crash like seems to be the case here (mine froze)... something has got to be getting left in memory somewhere. It might even be a bug in the Windows implementation, but I'll try a few more things before giving up.
    Last edited by fafalone; Aug 5th, 2015 at 04:48 PM.

  12. #12
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

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

    Hi Fafalone.

    I tried unicode filenames with my use of SHCreateItemFromParsingName and it seems to handle unicode fine (as I suppose your use of ILCreateFromPathW also does, haven't tried it yet). I don't know if there are any advantages of using one vs. the other, but I will do a bit of research.

    Regarding the Automation Error - it's not raising the "user cancelled action" error, it ends up reporting "Unspecified error". Perhaps it's a windows bug, but I'd be worried for anyone using the custom dialog in some parts of their program, and then an uncustomized one elsewhere in the same program as it might cause a crash?

    Just checked - selecting a file using your custom dialog demo seems to be crashing the application too, so maybe something wrong with the implementation/not getting cleaned up?

  13. #13

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    Selecting a file causes a crash when? When you first click on it, or after you click Ok? Definitely need more info to try to reproduce; works fine for me... can click around different files then hit Ok and retrieve the filename.

    Edit: I do remember something odd now; I forget what it was in particular but it's some obscure memory issue with Form1.FD_OnFileOK. Whether it works or not seems like it's magic 8ball based (see the screenshot at the top of the page). If you comment out everything inside it should behave as normal; the entire vtable-swap tends to be unstable; unless you really need the ability to prevent the dialog from closing based on returning a value to OnFileOK, you can do without it. The only related issue I've identified with the required shifting of getting custom control results is that the value of a custom edit control isn't retrievable; but if you leave the FD_OnFileOK portion for just getting the edit control text, it works and does not crash at all.
    What version of Windows are you on btw... a lot of these bugs don't seem like they're the callers fault as working with other interfaces is nearly identical, and they don't have these types of bugs.
    Last edited by fafalone; Aug 5th, 2015 at 11:30 PM.

  14. #14
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

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

    Hi fafalone,

    You're right - commenting out the FD_OnFileOK code eliminates the problem (it was happening when either double-clicking a file or when clicking the Mine File button in the customized dialog).

    Commenting out that code also prevents the other reported crash when subsequently selecting files by dbl-click/OK click in a non-customized after previously even just showing a customized dialog (having dismissed the customized dialog by clicking cancel).

    I'm using Windows 8.1 Pro.

  15. #15

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    Yeah, at some point I'll isolate it down to the precise function that causes the issue. But you can leave it like this to retain the ability to get a custom edit control text (which you can't do after the .Show statement returns, unlike other items like checkbox states and selected radio buttons):
    Code:
    Public Sub FD_OnFileOk(bAllowContinue As Long)
    'This event is sent when the ok button is clicked
    'So we get the control states as the final value
    
    'bAllowContinue: 0=dialog can close, non-zero=dialog stays open
    If (fdc Is Nothing) = False Then
    'everything else commented out and omitted
        Dim spt As Long
        Dim sz As String
        fdc.GetEditBoxText 2003, spt
            sz = BStrFromLPWStr(spt, False)
        Label5.Caption = "Textbox text=" & sz
    End If
    End Sub
    So it's not the principle of having some code there, it's a particular line that's causing the instability. I will look into it further; in the mean time, I've encountered no crashing if the code that was commented out is relocated to immediately after the .Show statement.

  16. #16
    New Member
    Join Date
    Aug 2015
    Posts
    6

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

    Please, can upload this complete example with TLB?
    Thanks.

  17. #17
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

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


  18. #18
    Addicted Member
    Join Date
    May 2016
    Location
    China
    Posts
    197

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

    sub Command4_Click added to the new line: Avoid mistakes without choosing radio

    fdc.StartVisualGroup 4000, "Radio station?"
    fdc.AddRadioButtonList 4001
    fdc.AddControlItem 4001, 4010, "Radio Station Alpha"
    fdc.AddControlItem 4001, 4011, "Radio Station Beta"

    fdc.SetSelectedControlItem 4001, 4010 'Add New Line

  19. #19
    Member Dragokas's Avatar
    Join Date
    Aug 2015
    Location
    Ukraine
    Posts
    740

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

    Hi, fafalone !

    Thanks for your project.

    What is OS requirements?
    Is it possible to add x64 bit folders support?
    Malware analyst, VirusNet developer, HiJackThis+ author || my CodeBank works

  20. #20

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    Works on Vista and newer, what do you mean 64 bit folder support? Does disabling the redirect not effect the dialog?

  21. #21
    Member Dragokas's Avatar
    Join Date
    Aug 2015
    Location
    Ukraine
    Posts
    740

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

    Works on Vista and newer
    Thank you.
    what do you mean 64 bit folder support?
    %SystemRoot%\System32 e.t.c.
    Does disabling the redirect not effect the dialog?
    No. Sorry, I think there is nothing you can do.
    For test, I placed API globally (on Form_Load), but test-file _x32.txt is still displayed in dialogue in System32 (but physically placed on SysWow64).

    Code:
    Private Declare Function Wow64DisableWow64FsRedirection Lib "kernel32.dll" (OldValue As Long) As Long
    Private Declare Function Wow64RevertWow64FsRedirection Lib "kernel32.dll" (ByVal OldValue As Long) As Long
    
    Private lWow64Old               As Long
    
    Private Sub Form_Load()
        Debug.Print 0 <> Wow64DisableWow64FsRedirection(lWow64Old)
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
    Set cEvents = Nothing
    Set fod = Nothing
    Set fsd = Nothing
    Set fodSimple = Nothing
    Set fdc = Nothing
        Debug.Print 0 <> Wow64RevertWow64FsRedirection(lWow64Old)
    End Sub
    Standart Comdlg32 GetOpenFileName dialogue has the same "issue".

    Regards,
    Alex.
    Malware analyst, VirusNet developer, HiJackThis+ author || my CodeBank works

  22. #22

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    There are a couple workarounds for this issue using SysNative. You're trying to access the 64-bit System32 directory right, where the test file wouldn't show? You can navigate to that from a 32-bit app without even disabling redirects.


    Method #1:
    What you can do is add a link in the places column (Favorites, Libraries, Computer, Network, etc) that's created to target SysNative, which will then bring up the 64-bit system32 as the previously invisible SysNative.

    Code:
    Public Declare Function SHCreateItemFromParsingName Lib "shell32" (ByVal pszPath As Long, pbc As Any, riid As UUID, ppv As Any) As Long
    
    Dim pChooseDir As New FileOpenDialog
    Dim psiResult As IShellItem
    Dim psiSysN As IShellItem
    Dim lpPath As Long, sPath As String
    Dim sSysN As String
    
    sSysN = "C:\Windows\SysNative"
    Call SHCreateItemFromParsingName(StrPtr(sSysN), ByVal 0&, IID_IShellItem, psiSysN)
    With pChooseDir
        If (psiSysN Is Nothing) = False Then
            Debug.Print "Got sysnative"
            .AddPlace psiSysN, FDAP_TOP
        End If
        .SetTitle "Choose a file..."
        .Show Me.hwnd
        .GetResult psiResult
        If (psiResult Is Nothing) = False Then
            psiResult.GetDisplayName SIGDN_FILESYSPATH, lpPath
            If lpPath Then
                SysReAllocString VarPtr(sPath), lpPath
                CoTaskMemFree lpPath
            End If
        End If
    End With
    Method #2:

    You could theoretically force a redirect in the dialog by using IFileDialogEvents_OnFolderChanging to detect the user selecting System32 and then redirect to SysNative. Not entirely sure if this is the greatest idea, but it does work:
    Code:
    Private Sub IFileDialogEvents_OnFolderChanging(ByVal pdf As IFileDialog, ByVal psiFolder As IShellItem)
    Debug.Print "OnFolderChanging"
    Dim lpPath As Long, sPath As String
    psiFolder.GetDisplayName SIGDN_FILESYSPATH, lpPath
    SysReAllocString VarPtr(sPath), lpPath
    CoTaskMemFree lpPath
    If sPath = "C:\Windows\System32" Then
        Debug.Print "Detected navigation to System32, rerouting"
        Dim psiSysN As IShellItem
        Dim sSysN As String
        
        sSysN = "C:\Windows\SysNative"
        Call SHCreateItemFromParsingName(StrPtr(sSysN), ByVal 0&, IID_IShellItem, psiSysN)
        If (psiSysN Is Nothing) = False Then
            Debug.Print "Got psiSysN, setting loc"
            pdf.SetFolder psiSysN
        End If
    End If
    
    End Sub
    As far as outright eliminating the redirect, you'd need a DLL to call from or some very fancy hacks that would probably get your app flagged as malware.
    Last edited by fafalone; Sep 1st, 2016 at 07:12 AM.

  23. #23
    Member Dragokas's Avatar
    Join Date
    Aug 2015
    Location
    Ukraine
    Posts
    740

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

    Thank you, fafalone. Clever decisions. It work.

    I converted string to IID_IShellItem manually. Are you using some ready-to-use TLB for this?
    Malware analyst, VirusNet developer, HiJackThis+ author || my CodeBank works

  24. #24

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    Any semi-recent download of oleexp has mIID.bas in the zip, which has all the IIDs in the project like that--- typed as UUID so no conversion needed.
    Last edited by fafalone; Sep 1st, 2016 at 04:11 PM.

  25. #25
    Addicted Member
    Join Date
    May 2016
    Location
    China
    Posts
    197

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

    How to get the selected post FileFilter Index?
    Code:
    Dim FileFilter() As COMDLG_FILTERSPEC
        ReDim FileFilter(3)
        FileFilter(0).pszName = "Image Files"
        FileFilter(0).pszSpec = "*.jpg;*.gif;*.bmp"
        FileFilter(1).pszName = "All Files"
        FileFilter(1).pszSpec = "*.*"
        FileFilter(2).pszName = "*.jpg"
        FileFilter(2).pszSpec = "*.jpg"
        FileFilter(3).pszName = "*.PNG"
        FileFilter(3).pszSpec = "*.png"
    How do you know that the user chose PNG?
    QQ: 289778005

  26. #26

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    Parse the filename when it returns... if you really need to know while the dialog is still open, the IFileDialogEvents sink has an OnTypeChanged notification where you can call pdf.GetFileTypeIndex on the IFileDialog it passes; or to be sure the SelectionChanged method lets you know when there's a new filename to check if you wanted to check by parsing the name before close.

  27. #27
    Addicted Member
    Join Date
    May 2016
    Location
    China
    Posts
    197

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

    Thanks, the way I use it now is to get the right three letters of the file name.
    I want to obtain the file name at the same time can also obtain the extension.
    QQ: 289778005

  28. #28
    Addicted Member
    Join Date
    May 2016
    Location
    China
    Posts
    197

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

    Find out what you said. Although it is not the direct extension I want, I can also determine which extension is based on this index. thanks again fafalone.
    Code:
    Public Sub IFileDialogEvents_OnTypeChange(ByVal pdf As IFileDialog)
        Form1.List1.AddItem "OnTypeChange"
        Dim i As Long
        pdf.GetFileTypeIndex i
        Form1.List1.AddItem i
        FileterIndex = i
    End Sub
    QQ: 289778005

  29. #29
    Member Dragokas's Avatar
    Join Date
    Aug 2015
    Location
    Ukraine
    Posts
    740

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

    Hi, fafalone!

    Thank you for the project.

    I found bug in your example. When click "Show multi-Open", than click "Cancel" in opened dialogue, causes program infinite loop (win7 x64).

    EDIT. Ok, I removed first "On Error Resume Next" and replace it by:
    Code:
            On Error Resume Next
            .Show Me.hwnd
            If Err.Number = 0 Then
                On Error GoTo 0
            
                .GetResults isia
                isia.EnumItems iesi
                
                Do While (iesi.Next(1, isiRes, 0) = 0)
                    isiRes.GetDisplayName SIGDN_FILESYSPATH, lPtr
                    Text1.Text = Text1.Text & BStrFromLPWStr(lPtr, True) & vbCrLf
                    Set isiRes = Nothing
                Loop
            End If
            On Error GoTo 0
    Last edited by Dragokas; Jul 21st, 2018 at 06:04 PM.
    Malware analyst, VirusNet developer, HiJackThis+ author || my CodeBank works

  30. #30
    Member Dragokas's Avatar
    Join Date
    Aug 2015
    Location
    Ukraine
    Posts
    740

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

    I'll post for people who like my modification:

    'Fork by Dragokas
    ' - Button_Click(s) converted to functions (only 3 variants: simple open dialogue, multiselect and save dialogue)
    ' - Default folder open location added as a parameter to function, otherwise "My PC" location will be open.
    ' - Added options FOS_FILEMUSTEXIST (FOS_PATHMUSTEXIST), FOS_FORCESHOWHIDDEN (to ensure file presence, show hidden files)
    ' - Added Windows\System32 to SysNative redirection by fafalone's sample (to support x64)
    ' - Removed example of VTable events redirection from class to module
    ' - Removed some comments
    ' - Removed several filters: left just 1 : *.* (all files)
    ' - Added .Unadvise to unhook events handler
    ' - Fixed infinite loop when cancel meltiselect dialogue
    Code:
    Function OpenFileDialogVista_Multi(aPath() As String, Optional sTitle As String, Optional InitDir As String, Optional hwnd As Long) As Long
    Function OpenFileDialogVista_Simple(Optional sTitle As String, Optional InitDir As String, Optional hwnd As Long) As String
    Function SaveFileDialogVista(Optional sTitle As String, Optional InitDir As String, Optional DefSaveFile As String, Optional hwnd As Long) As String
    Cheers,
    Stanislav.

    ---
    Interesting thing: dialogue doesn't see files/folders marked with both "Hidden" and "System" attributes (even with FOS_FORCESHOWHIDDEN flag set).
    If file has only 1 attr. either "H" or "S" it can see.
    Attached Files Attached Files
    Malware analyst, VirusNet developer, HiJackThis+ author || my CodeBank works

  31. #31

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    +HS are 'protected OS files'... a separate option in Explorer as well (you won't see them with just 'Show hidden files', they're what 'protected os files' is referring to). I'm not sure that you can have them shown in the dialog without changing the system setting. Is it different in earlier open dialogs like GetOpenFilename or the ocx?

    Also thanks for letting me know of the bug, I've been meaning to update the demo anyway, sounds like a good excuse. Good work on the fork.
    Last edited by fafalone; Jul 23rd, 2018 at 12:38 AM.

  32. #32
    Member Dragokas's Avatar
    Join Date
    Aug 2015
    Location
    Ukraine
    Posts
    740

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

    Good question. I checked GetOpenFileName + OFN_FORCESHOWHIDDEN and no, it also doesn't show +HS.
    Malware analyst, VirusNet developer, HiJackThis+ author || my CodeBank works

  33. #33
    New Member
    Join Date
    Aug 2018
    Posts
    6

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

    Hi,

    I have an old VB6 project that works fine in Windows 10, including Windows 10 64. The one problem is when it shows the open file dialogs it does not show the folder names correctly at the top. Instead of showing the full names, it shows a "?", followed by the folder name with the last two characters of the name replaced by two periods. For example "?inetp.." instead of "inetpub."

    The open file dialog otherwise works as expected, including the drop-down lists from the folder names at the top. The problem is just with the display in the top bar.

    I downloaded fafalone's 2015 project files, and the dialogue boxes look good when I run them as a separate project. But if I add them to my large project, the open file boxes it shows have the same problem as the common control dialog boxes.

    I then tried Drogokas' more recent version, but it had the same problem as fafalone's version.

    Any ideas?

  34. #34

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    The top bar as in the dropdown control's edit area?

    Does this occur with the GetOpenFileName API? And is there a difference between IDE and compiled? Other apps that use common dialogs?

    Is it all folders or just ones ending with a dot, because that's not a valid folder name in Windows so I guess it's on or came from a network share? If it's just these folders that's probably the main issue, but I couldn't say what in your project is triggering it; if it's in the exe only maybe a manifest setting? Do you use identical flags... if you used one of the dialog style flags in one but not the other that could effect it.
    Last edited by fafalone; Feb 6th, 2020 at 11:33 PM.

  35. #35
    New Member
    Join Date
    Aug 2018
    Posts
    6

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

    Thanks for offering help.

    Yes, the problem occurs if I use the GetOpenFileName API, exactly the same as when I use the common dialog control.

    There is no difference between the IDE and compiled versions.

    It affects all folders, and I don't have any ending with a period. For example I might see

    ?inetp.. ?wwwro.. ?cgi-b..

    following the drive letter.

    The dialog style flags don't seem to make a difference.

  36. #36
    PowerPoster
    Join Date
    Jan 2020
    Posts
    3,742

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

    file,color,font,How to achieve all of this? Dialog Settings

  37. #37

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    I don't know what you mean by 'file', but color and font can't be changed easily. You'd be better off using INamespaceTreeControl/IExplorerBrowser or my ucShellTree/ucShellBrowse controls to make your own custom dialog than trying to modify the colors and fonts of the system dialog.

  38. #38
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,854

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

    Maybe he refers to the CommonDialog control, which can be used to select a file, font or color

  39. #39

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

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

    If that's the case; then you could choose a font by setting the fonts folder as the starting path (you'd need to convert the file reference to a font yourself... match the file name against a font enumeration (EnumFontFamiliesEx)), but it doesn't have replacement dialogs for font or color.

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