dcsimg
Results 1 to 13 of 13

Thread: [vb6]Common Dialog Class (Yet Another One)

  1. #1

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    17,441

    [vb6]Common Dialog Class (Yet Another One)

    Then enclosed class combines the Windows XP/Win2000 Open/Save dialog that uses APIs to generate the dialog with the IFileDialog interface used in Vista and higher. Basically, the class is a unicode-friendly dialog option as a drop-in, self-contained class. Do note that the class has been hard-coded to not run on any O/S less than XP/Win2000. Also included in the class is the old-style "Browse for Folder" dialog. The class can get all dialogs to callback to itself and forward you the events.

    Though the class makes heavy use of calling to interfaces not known to VB, it does not use type libraries (TLBs). However, I have made every effort to make it compatible to TLBs you may be using in your project. In other words, objects returned by this class through its events or functions should be 100% compatible with a TLB that defines interfaces that this class is using. Anything less would be an oversight by me and considered a "bug report".

    This class has absolutely no real benefit over existing code you may already be using unless you want more advanced options. Some of those options include:

    - XP/Win2000. APIs used to display the dialogs
    -- class-generated thunks for hooking the dialog. Those thunks result in raised events from the class to its host, i.e., form, usercontrol, other class, etc.
    -- auto-sizing buffer for multi-selection to prevent the ugly 'buffer too small' error and forcing users to go back and try again

    - Vista and higher. IFileDialog interface used to display the dialogs
    -- Customize by adding additional controls to the dialog and receive events for those controls
    -- Add a read-only checkbox back to the dialog that populates the common OFN_ReadOnly flag
    -- Interact with the dialog via class-generated thunks that raise events from the class to its host
    -- Use embedded custom configurations. There are currently 7 of those.
    1. Browse for Folders while showing file names too
    2. Navigate into compressed folders (zips) while being able to select the zip itself or one of its contained files or any other file
    3. Show both files and folders and be able to select either folders or files or both
    4. Four "basket mode" settings which allows selecting files/folders across multiple directories. Similar to "Add to my Cart" button.
    -- All custom mode button captions can be assigned by you or default to locale-aware captions (see screenshot below)

    Nearly all of the advanced Vista+ options are incorporated into this class, but not all. If you find you need anything more that is not offered, modify as needed.

    If you just want a simple Open/Save dialog where the filter is: All Files, the code needed for the dialog is as simple as:
    Code:
        Dim cBrowser As CmnDialogEx
        Set cBrowser = New CmnDialogEx
        If cBrowser.ShowOpen(Me.hWnd) = True Then
            MsgBox "File Selected: " & cBrowser.FileName
        End If
    Want to add the "Read-Only" checkbox back to the dialog?
    Code:
        Dim cBrowser As CmnDialogEx
        Set cBrowser = New CmnDialogEx
        cBrowser.Controls_AddReadOnlyOption 100    ' << user-defined Control ID
        If cBrowser.ShowOpen(Me.hWnd) = True Then
            MsgBox "File Selected and Read-Only opted for: " & CBool(cBrowser.Flags And Dlg_ReadOnly)
        End If
    Want a "Browse for Folder" like dialog that also shows files (not doable with newer dialog using standard options)?
    Code:
        Dim cBrowser As CmnDialogEx
        Set cBrowser = New CmnDialogEx
        cBrowser.Controls_SetCustomMode cm_BrowseFoldersShowFiles
        If cBrowser.ShowOpen(Me.hWnd) = True Then
            MsgBox "Selected Folder: " & cBrowser.FileName
        End If
    The screenshot below highlights locale-aware captions. The only one I haven't been able to find is a locale-aware caption like: All Files. That would be a nice-touch.
    Edited: Found it in shell32.dll ID: 34193 for Vista+. XP/Win2K will still use hard-coded value as needed
    Name:  Dialog.jpg
Views: 954
Size:  28.4 KB

    The sample project offers examples of several dialog variations. The class itself is heavily commented.
    Code:
    Update History
    5 Aug 18 - Massive changes see post #13 for  details
    28 May 18 - Enhancements & altered format of FileName property return value 
            when multiple files selected
    23 Jan 18 - Minor fixes
            Fixed a couple locale-aware captions being retrieved from common dlls
            Addressed case where Windows can convert "Open" button to unexpected split-button
    21 Jan 18 - initial release
    FYI: If you are using any previous version, do not simply replace it with the one in the zip below. So many changes were made to this version that it is not compatible with previous ones. To ensure no confusion between versions, the class name was also changed from OSDialogEx to CmnDialogEx.

    Minor fix to be applied after downloading. Next time zip is uploaded, fix will be applied and this paragraph will be removed. Test code left as-was by mistake.
    Code:
    - Routine: InitDir property Let
    - Action:
    
    relocate this line: If Len(Value) = 0& Then Exit Property relocate to immediately above this line: If InStr(Value, ":") Then
    - Reason: can't reset InitDir to null otherwise, without calling the Clear method
    Attached Files Attached Files
    Last edited by LaVolpe; Aug 11th, 2018 at 10:14 AM. Reason: Updated Version
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  2. #2

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    17,441

    Tips, Tricks, Notes...

    Notes. For those of you not yet using a real Vista+ dialog, there are several new flags made available. And some of those flags conflict with previous version of the dialog. Here's a couple of those changes. See this MSDN link for a complete list, also commented in the class.

    ForceFileSystem. Display only true files, not virtual files
    AllNonStorageItems. Allows you to navigate into non-system folders and zip files. AllNonStorageItems & ForceFileSystem are mutually exclusive. One or the other.
    PickFolders. Enables the new basic "Browse for Folder" dialog.
    Previous version flag OFN_ENABLEHOOK. Not supported because same value as new PickFolders constant. For pre-Vista users, the ShowOpen & ShowSave functions have an optional parameter to hook the dialog and pass events to you instead.

    All public enumerations in the class have been made unique so that they don't conflict with any similar enumerations you may already have. So, the class isn't truly plug & play with your existing dialog code, but very little effort is required. Typically, you may only need to change your Flags enumeration values from FOS_[xxxx] or OFN_[xxx] values to the class' DLG_[xxx] & DLGex_[xxx] values.
    Tip. DLG_ prefix is for all systems, DLGex_ prefix is for Vista and above DLGXP_ is for XP/Win2K

    Another major change is the heavy usage of IShellItem and IShellItemArray interfaces. Though for basic usage, interacting with those interfaces is not absolutely needed. The class does offer some 'courtesy' functions to query most of those interface methods.

    For those of you still quite comfortable with VB's common dialog or other classes designed to use GetOpenFileName and GetSaveFileName APIs, this class was designed around that structure. But the newer Vista+ dialog offers much more. The class offers many additional properties/methods to address those. All methods and properties in the class, except a few, are valid for the Vista+ dialog. Those few are silently ignored. Many of those others are not valid for the older XP/Win2K dialog. There are comments for each method/property. Those not applicable for the older dialog should be clearly stated.

    Tip. Any additional controls/containers you add to the dialog are assigned a user-defined numeric ID. That ID allows you to call the Controls_PropertyGet/Set functions to get/set properties before the dialog is displayed, while displayed, or after it closes. No ID can be duplicated and the IDs can range from 1 to 268435455 (&H1 to &HFFFFFFF)

    Tip. The FileName property contains the selected item(s) from the dialog. This property is different than other dialogs you have used when multiple files are selected. Because Vista+ can allow selection of files from different folders (items in a Library for example), each selected file includes the file's path. Previous versions included the path then a vbNullChar-delimited list of file titles which no longer can be enforced with Vista+. As was before, testing for a vbNullChar in the FileName property can be used to determine if multiple items were selected by the user.
    Note: If you allow non-system folders to be browsed/selected from within (AllNonStorageItems flag), then it is possible you will get a virtual path/file.

    Tip. The ShowOpen/ShowSave functions have an optional parameter to pass a stdole.IUnknown reference. This reference will contain an IShellItem or IShellItemArray (multiple selected items) on return. That reference can be passed to the modern IFileOperation interface which supersedes the SHFileOperation API (Win2K/XP). This class does not expose the IFileOperation interface. A TLB or custom solution is required.

    Tip. This class appears to work just fine in MS Office (at least Access), even with the thunks and subclassing in play. However, you will need to change some vartypes. Access does not recognize CheckBoxConstants used in public event: DialogCheckBoxChanged. Change that to Long or Boolean. It also does not recognize the vbCFFiles constant used in pvGetDisplayName. Change that constant to: 15.

    Tip. Though the dialog can be displayed without a passed owner hWnd, you should avoid this unless absolutely needed. Without that hWnd, the dialog is modal only to the line of code that called it, not the form that called it. That means your form is not 'disabled' while the dialog is displayed. It also means the user can close your form/project while the dialog is running. When they eventually close the dialog, your code continues to run which may lead to reloading your form/project, hidden to the user. In any case, the dialog does not disable the entire project (multiple forms displayed), only the form that called it when you also pass the form's hWnd as the owner hWnd. If this doesn't work for you, the easy workaround is: Before calling the dialog, disable all forms but the calling form, call the dialog, and when it closed, re-enable those forms.

    Tip. The old-style "Browse For Folder" dialog modality is same as the file dialog.

    Tip. For Vista+ and asking for events, you can change the folder view (list, tiles, small icons, etc) of the dialog via the IFileDialog_SetViewMode method.

    Tip. Use client GUIDs to have Windows save some of your dialog's last settings, i.e., position, size, last folder visited and a bit more. See CreateClientDataGUID & ShowOpen function comments for details.
    Last edited by LaVolpe; Aug 6th, 2018 at 06:29 AM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3
    Hyperactive Member
    Join Date
    Jul 2007
    Location
    Essex, UK.
    Posts
    405

    Re: [vb6]Common Dialog Class (Yet Another One)

    This is excellent until I needed to dump some files to my 'F:\' drive. It wouldn't select the drive root with browseforfolder! Or am I doing something wrong

  4. #4

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    17,441

    Re: [vb6]Common Dialog Class (Yet Another One)

    Quote Originally Posted by Steve Grant View Post
    This is excellent until I needed to dump some files to my 'F:\' drive. It wouldn't select the drive root with browseforfolder! Or am I doing something wrong
    I'm not sure what you mean by "wouldn't select". Are you saying it wouldn't navigate to F root?

    Can you be more specific and maybe also include the options you used? Maybe my logic in the subclassing for a custom mode you might have been using has a logic flaw?

    Edited: Yep, a logic flaw in the sample project, but not the dialog class.
    The dialog returns the root folder, but the looping I used in the sample failed...
    Code:
    ...
                sPath = cBrowser.FilePath & "\"
                sItems() = Split(Mid$(cBrowser.FileName, Len(sPath) + 1&), vbNullChar)
    sPath length is 3 since root folder selected. So the split is trying to split on Mid$(Path, 4). When I get a chance I'll update the sample project. If you actually look at cBrowser.FilePath or .FileName, you should see your folder selected.

    However, if multi-selecting root folders using "Browse for Folders", the class does have a logic flaw. I didn't take that into consideration and assumed multi-selection (non-basket mode) would all be in the same parent folder, i.e., same root path. Roots don't quite fit that failed logic. I'll need to tweak that & post the update this weekend.
    Last edited by LaVolpe; Feb 9th, 2018 at 04:29 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5
    Hyperactive Member
    Join Date
    Jul 2007
    Location
    Essex, UK.
    Posts
    405

    Re: [vb6]Common Dialog Class (Yet Another One)

    You are so right. Thank you.

    Code:
            If UBound(sItems) > -1 Then
                For lItem = 0 To UBound(sItems)
                    lstEvents.AddItem "    Selected: " & sPath & sItems(lItem), lItem + 1&
                Next
            Else
                lstEvents.AddItem "    Selected: " & sPath
            End If

  6. #6
    Lively Member
    Join Date
    Jan 2010
    Posts
    107

    Re: [vb6]Common Dialog Class (Yet Another One)

    Is it possible to hide/remove Help button in Vista style dialog?

  7. #7

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    17,441

    Re: [vb6]Common Dialog Class (Yet Another One)

    If it's an actual window, I would think you can use FindWindow/FindWindowEx to locate it an hide it, but don't know if you can remove it resulting in the other buttons shifting to fill the empty space. That is not an option that is made available by the IFileDialog or its related interfaces. At least not that I know of. Clicking on that help button does not raise an event in the IFileDialog.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  8. #8
    Lively Member
    Join Date
    Jan 2010
    Posts
    107

    Re: [vb6]Common Dialog Class (Yet Another One)

    Yes, I can find that button, it is called "&Help". Given that IModalWindow::Show is a blocking call, it would be complicated to use ShowWindow API to hide it. I was hoping to use IFileDialogCustomize interface to remove it.

  9. #9

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    17,441

    Re: [vb6]Common Dialog Class (Yet Another One)

    Quote Originally Posted by riov View Post
    Yes, I can find that button, it is called "&Help". Given that IModalWindow::Show is a blocking call, it would be complicated to use ShowWindow API to hide it. I was hoping to use IFileDialogCustomize interface to remove it.
    If on Vista and higher and using this class, you can opt for events. One of the events is the DialogOnInit event. That event contains the dialog hWnd. Within any event, you can call the class IFileDialog_GetHwnd function. Events are not blocked
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  10. #10
    Lively Member
    Join Date
    Jan 2010
    Posts
    107

    Re: [vb6]Common Dialog Class (Yet Another One)

    Unfortunately, under further investigation it looks like it is impossible to hide that Help button. The reason is that it has no hwnd as it is drawn by DirectUIHWND. I can get a list of its properties, but I have not found a way to change them.


  11. #11

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    17,441

    Re: [vb6]Common Dialog Class (Yet Another One)

    Dialog class and sample project updated. List of primary changes follows:

    1. Changed format of FileName property when multiple files/folders selected.
    Instead of old format: Path vbNullChar FileName1 vbNullChar FileName2 etc
    Changed to: Path\FileName1 vbNullChar Path\FileName2 etc
    Reason: Vista+ allows selection of files from different paths, i.e., Library items. Since each selected item can be at a different path, the previous method of identifying just one path for all selected files no longer applies. Though pre-Vista still restricts multiple selections from same path, this new format is used whether the dialog is being displayed pre-Vista or Vista+

    2. Exposed IFolderView2 which can be used to change display of the dialog: details, list, small icon, etc
    - Added functions to get/set the folder's display mode
    IFileDialog_IFolderView2 retrieves interface
    IFileDialog_GetViewMode returns current folder's display mode
    IFileDialog_SetViewMode sets current folder's display mode
    - Added new enum to support above functions: IShellViewModeEnum

    3. Changed Controls_AddReadOnlyOption method to default Read-Only option to False vs. True
    - if checkbox style: checkbox is unchecked by default
    - if split-button style: "Open" button defaults to not open as read only

    4. Added locale-aware 'All Files' filter item when default filter used. Applies to Vista+
    Name:  Untitled.jpg
Views: 247
Size:  8.0 KB

    5. Added option within Filter property to allow not showing the filter, if desired. In screenshot below, you can see the Filter in a typical dialog and then the dialog with the hidden filter. Tip: This is a nice alternative when the filter would just be All Files... Why show the filter if it really doesn't apply? Rhetorical.
    Name:  Untitled.jpg
Views: 345
Size:  13.6 KB
    Last edited by LaVolpe; Jun 2nd, 2018 at 07:53 AM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  12. #12

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    17,441

    Re: [vb6]Common Dialog Class (Yet Another One)

    Here's a replacement for the pvProcessCustomMode routine in the class.

    Scenario: Using options to show both files and folders while browsing for folders. Since files are shown, then can be selected.

    Problem: Logic flaw. It is possible the user only selects files and selects no folders. The dialog would close when the "Select Folder" button is clicked. This resulted in dialog returning a true value (items selected) when none were actually selected. In this scenario, the parent folder should be returned.

    Solution: Test the count of actual folders that were selected and ignore button click if zero folders were selected. The existing code removed any files from the selection, but didn't recheck the count afterwards and simply closed the dialog in that case. If user selected only files, then the dialog will return the parent folder.

    Changes are bolded and in blue below. I'll include this patch the next time I update the zip in original post above. Will also look at preventing files from being clickable in this scenario.
    Code:
    Private Function pvProcessCustomMode() As Long
    
        ' this routine processes the subclassed "Open" button. User wants to select something
        ' applies only when Controls_SetCustomMode called and a subclass was created
        
        ' overriding default behavior is a bit complex
        
        Dim bCancel As Boolean, nrItems As Long
        Dim lAttrs As Long, oPtr As Long, aPtr As Long
        Dim lOptions As Long, n As Long, aData() As Long
        Dim IFolderView2 As stdole.IUnknown
        Const IfIFolderView2_GetSelection As Long = 32
        
        pvCallInterface ObjPtr(m_Dialog), ifFileDialog_GetOptions, VarPtr(lOptions)
        If (lOptions And DLG_AllowMultiSelect) Then
            ' see IFileDialog_GetCurrentSelection method for comments why we ask for multi-select items this way
            Set IFolderView2 = pvGetIFolderView2
            If Not IFolderView2 Is Nothing Then
                pvCallInterface ObjPtr(IFolderView2), IfIFolderView2_GetSelection, 0&, VarPtr(m_ModeResults)
                Set IFolderView2 = Nothing
            End If
        End If
        If m_ModeResults Is Nothing Then
            Set m_ModeResults = Me.IFileDialog_GetCurrentSelection(True, nrItems)
            If m_ModeResults Is Nothing Then Exit Function      ' no items selected
        Else
            pvCallInterface ObjPtr(m_ModeResults), ifShellItemArray_GetCount, VarPtr(nrItems)
        End If
        
        Select Case (m_StateFlags And emskCustMode)
         
         Case cm_BasketModeFilesOrFolders, cm_PickFilesOrFolders ' can select anything
             If (m_StateFlags And emskCustMode) = cm_BasketModeFilesOrFolders Then
                 RaiseEvent DialogAddBasketItem(m_ModeResults, bCancel)
             ElseIf (m_StateFlags And emskAllEvents) Then
                 RaiseEvent DialogOnFileOk(bCancel)
             End If
             If bCancel Then
                 Set m_ModeResults = Nothing ' function returns 0 to keep dialog open
             ElseIf (m_StateFlags And emskCustMode) = cm_PickFilesOrFolders Then
                 pvProcessCustomMode = True   ' closes dialog
             Else
                 pvUpdateBasket nrItems      ' dialog remains open
                 Set m_ModeResults = Nothing
             End If
             
         Case cm_BrowseFoldersShowFiles, cm_BasketModeFoldersOnlyShowFiles
             For n = 0& To nrItems - 1&                ' test attributes of each selected item
                 pvCallInterface ObjPtr(m_ModeResults), ifShellItemArray_GetItemAt, n, VarPtr(oPtr)
                 If oPtr Then
                     pvCallInterface oPtr, ifShellItem_GetAttributes, -1&, VarPtr(lAttrs)
                     pvCallInterface oPtr, ifUnknown_Release: oPtr = 0&
                     If (lAttrs And siAttr_FOLDER) = 0& Then Exit For    ' not a folder
                     If (lOptions And DLGex_AllNonStorageItems) = 0 Then ' only system folders (not zip content)?
                         If Not (lAttrs And (siAttr_FILESYSTEM Or siAttr_STREAM)) = siAttr_FILESYSTEM Then Exit For
                     End If
                 End If
             Next
             If n < nrItems Then                         ' at least one non-folder selected
                 If nrItems = 1& Then                    ' else multi-selection
                     nrItems = 0&
                 Else
                     ReDim aData(0 To nrItems - 1&)          ' loop again, keeping only valid items
                     For n = 0& To nrItems - 1&
                         pvCallInterface ObjPtr(m_ModeResults), ifShellItemArray_GetItemAt, n, VarPtr(oPtr)
                         If oPtr Then
                             pvCallInterface oPtr, ifShellItem_GetAttributes, -1&, VarPtr(lAttrs)
                             If (lAttrs And siAttr_FOLDER) Then
                                 SHGetIDListFromObject oPtr, aData(aPtr): aPtr = aPtr + 1&
                                 If (lOptions And DLGex_AllNonStorageItems) = 0 Then ' only system folders (not zip content)?
                                     If Not (lAttrs And (siAttr_FILESYSTEM Or siAttr_STREAM)) = siAttr_FILESYSTEM Then _
                                         aPtr = aPtr - 1&
                                 End If
                             End If
                             pvCallInterface oPtr, ifUnknown_Release: oPtr = 0&
                         End If
                     Next
                     Set m_ModeResults = Nothing: nrItems = aPtr
                     If nrItems > 0& Then                      ' rebuild results, skipping invalid selections
                        SHCreateShellItemArrayFromIDLists nrItems, VarPtr(aData(0)), m_ModeResults
                        For nrItems = 0& To nrItems - 1&
                            CoTaskMemFree aData(nrItems)
                        Next
                    End If
                End If
                If (m_StateFlags And emskCustMode) = cm_BrowseFoldersShowFiles And nrItems = 0& Then
                    ' only files were selected, choose the files folder & place into IShellItemArray
                    pvCallInterface ObjPtr(m_Dialog), ifFileDialog_GetFolder, VarPtr(m_ModeResults)
                    If Not m_ModeResults Is Nothing Then
                        SHGetIDListFromObject ObjPtr(m_ModeResults), aPtr
                        Set m_ModeResults = Nothing
                        If aPtr Then
                            SHCreateShellItemArrayFromIDLists 1&, VarPtr(aPtr), m_ModeResults
                            CoTaskMemFree aPtr: nrItems = 1&
                        End If
                    End If
                End If
             End If
             If nrItems < 1& Then
                bCancel = True
             ElseIf (m_StateFlags And emskCustMode) = cm_BasketModeFoldersOnlyShowFiles Then
                 RaiseEvent DialogAddBasketItem(m_ModeResults, bCancel)
             ElseIf (m_StateFlags And emskAllEvents) Then
                 RaiseEvent DialogOnFileOk(bCancel)
             End If
             If bCancel Then
                 Set m_ModeResults = Nothing     ' keep dialog open
             ElseIf (m_StateFlags And emskCustMode) = cm_BasketModeFoldersOnlyShowFiles Then
                 pvUpdateBasket nrItems          ' keep dialog open
                 Set m_ModeResults = Nothing
             Else
                 pvProcessCustomMode = True       ' close dialog
             End If
         
         Case cm_CompressedFolderPlusFiles, cm_BasketModeFilesOnly
             For n = 0& To nrItems - 1&
                 pvCallInterface ObjPtr(m_ModeResults), ifShellItemArray_GetItemAt, n, VarPtr(oPtr)
                 If oPtr Then
                     pvCallInterface oPtr, ifShellItem_GetAttributes, -1&, VarPtr(lAttrs)
                     pvCallInterface oPtr, ifUnknown_Release: oPtr = 0&
                     If (lAttrs And siAttr_FOLDER) Then
                         If Not (lAttrs And (siAttr_FILESYSTEM Or siAttr_STREAM)) = _
                             (siAttr_FILESYSTEM Or siAttr_STREAM) Then Exit For
                     End If
                 End If
             Next
             If n < nrItems Then
                 Set m_ModeResults = Nothing
             ElseIf (m_StateFlags And emskCustMode) = cm_BasketModeFilesOnly Then
                 pvUpdateBasket nrItems
                 Set m_ModeResults = Nothing
             Else
                 If (m_StateFlags And emskAllEvents) Then RaiseEvent DialogOnFileOk(bCancel)
                 If bCancel Then Set m_ModeResults = Nothing Else pvProcessCustomMode = True
             End If
             
        'Case cm_PickFilesOrFolders, cm_BasketModeFoldersOnly  ' these are not subclassed
             
        End Select
    
    End Function
    Upcoming enhancement: Inclusion of Vista+ SetClientGUID and ClearClientData options. SetClientGUID allows you to assign dialog-startup persisted information to a GUID. This is like having a configuration file for a dialog. You can have as many of these as you'd like, for example, one for a Open dialog, one for a Save dialog, etc. ClearClientData resets associated GUIDs. GUIDs are cached per application. See this for more info.
    By specifying a GUID, an application can have different persisted states (such as the last visited folder and the position and size of the dialog) for different versions of the dialog within the same application (for example, an import dialog and an open dialog).
    Considering other enhancements before the next update.
    Last edited by LaVolpe; Jun 2nd, 2018 at 02:55 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  13. #13

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    17,441

    Re: [vb6]Common Dialog Class (Yet Another One)

    Project updated ... massively.

    Important. The class in the zip file is no longer named the same, on purpose. So many changes were made that it could not be kept compatible with the previous version. Old name was OSDialogEx and new class name is CmnDialogEx. Here is a summary of the changes made:

    - Includes the old-style "Browse For Folder" dialog. It is likely many still use it. So, decided to include it with the class. Most of the class methods don't apply to that dialog. At top of the class, there are comments to which class methods do apply (about a dozen). This is biggest reason why class became incompatible with previous one. Also included several callback events.

    - Since the property Flags is no longer intuitive to which dialog it belongs to, we now have 3 Flags properties:
    FlagsDialog is the old Flags property and pertains to the file dialogs
    FlagsDialogEx is the old FlagsEx property and pertains to the file dialogs
    FlagsFolderBrowsing is a new property and only pertains the "Browse for Folder" dialog

    - InitDir, SetRootFolder, SetNavFolders, SetNavFoldersEx have been slightly modified to accept various forms of "folder" references to include: standard folder names, PIDLs, CSIDL constants, Vista+ KnownFolderIDs & control panel path GUIDs

    - Added ability to use client GUIDs with the Vista+ file dialog. See previous reply above for more info. Also to support this, included a custom class function to create these GUIDs for you, on demand. There's a bit more to this if you opt to use them and the class CreateClientGUID function is well commented about that. Tweaked the ShowOpen and ShowSave functions for client GUID use and added comments there too.

    - A few properties were removed: FileExtension, FilePath & MaxFileTitle. Another became read-only: FileTitle

    - Included all known CLSID values and Vista+ KnownFolderIDs to the class via enumerations so you don't have to go looking for them if needed. For example, returning a known folder ID:
    Code:
     ' cBrowser as been declared as CmdDialogEx
        Debug.Print cBrowser.GetKnownFolderGUID(eFOLDERID_ProgramFilesX64)
        ' following printed out: {6D809377-6AF0-444b-8957-A3773F02200E}
    - Minor bug fixes noted at top of the class comments

    - Also updated the sample project to include use of the "Browse for Folder" dialog
    Last edited by LaVolpe; Aug 6th, 2018 at 02:21 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

Posting Permissions

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



Featured


Click Here to Expand Forum to Full Width