[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.
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
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().
Re: [VB6] Using the new IFileDialog interface for customizable Open/Save (TLB, Vista+
Originally Posted by fafalone
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?
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.
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
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.
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
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.
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?
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
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.
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?
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.
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).
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.
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".
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.
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.
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.
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
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.
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.
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.
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.
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.
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.
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.
Re: [VB6] Using the new IFileDialog interface for customizable Open/Save (TLB, Vista+
Hi, I started to play with this and it works great, but I'm puzzled about one thing though that I don't quite understand. It's the cFileDialogEvents class, it has hard coded form names in it, which isn't very intuitive or even useful if you want to open dialogs from several forms in your project.
I assume I'm not very good at these windows interface stuff, but there has to be a more abstract to catch the event no matter with form the dialog/class is used in? Maybe I don't see the forest because of all the treas or... Basically, what I want is to e.g. catch if a checkbox was selected or not, but in the same procedure as where I catch the file name in the save or open dialog. What am I missing?
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?