I've inherited a set of macros, one of which allows the running of one or more macros on a batch of files. The main dialog has a browse button on it which opens up a little browse dialog to allow the user to choose the path to the folder containing the files on which to run the macro(s). The thing is, this browser window is kind of annoying as it always defaults to the my computer view (the one in this page) and the user has to click down through the tree structure to the directory (s)he wants, which is rather tedious. I'd like to replace this dialog with one which allows the user to paste a path into the text-box at the bottom of the dialog and hit OK - a more modern Windows dialog. I'm not very experienced in VB (about 5 weeks if the truth be told) and don't understand the code fully, but have narrowed it down to two possible places where I have to make the change.
Is there much of a change needed in the following code, just the addition of a few lines, or do I need to use a completely different dialog and rewrite the code (I assume it's been done before, but attempts to find the code I need have been a bit confusing)?
When I open the form corresponding to the main dialog of the multimacrorunner, I can see that the name of the selected folder is lbFolder, and clicking browse activates this code:
VB Code:
Private Sub btnBrowse_Click()
lblFolder.Caption = BrowseFolder
End Sub
Not much info there, but further on in the code there's the bit that corresponds to the opened folder:
VB Code:
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function SHBrowseForFolder Lib "shell32.dll" ( _
ByRef lpbi As BROWSEINFO) As Long
Private Declare Function SHGetPathFromIDList Lib "shell32.dll" ( _
pidl As Any, ByVal pszPath As String) As Long
'======= .bas wrapper for ShBrowseForFolder =======
Private Const BIF_RETURNONLYFSDIRS As Long = &H1&
Private Const BIF_DONTGOBELOWDOMAIN = &H2&
Private Const BIF_STATUSTEXT = &H4&
Private Const BIF_RETURNFSANCESTORS = &H8&
Private Const BIF_EDITBOX = &H10&
Private Const BIF_VALIDATE = &H20& ' insist on valid result (or CANCEL)
Private Const BIF_BROWSEFORCOMPUTER = &H1000& ' Browsing for Computers.
Private Const BIF_BROWSEFORPRINTER = &H2000& ' Browsing for Printers
Private Const BIF_BROWSEINCLUDEFILES = &H4000& ' Browsing for Everything
Private Const MAX_PATH = 260
Private Const CSIDL_DRIVES As Long = &H11&
Private Type BROWSEINFO
hwndOwner As Long ' HWND
pidlRoot As Long '* pointer to: LPCITEMIDLIST (opens at ID)
sDisplayName As String 'buffer for result
sTitle As String 'prompt string
ulFlags As Long ' UINT
lpfn As Long '* pointer to: BFFCALLBACK
lParam As Long ' LPARAM
iImage As Long ' int
End Type
Private Declare Function FindWindow Lib "user32" Alias _
"FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As Long) As Long
Public Function BrowseFolder(Optional sPrompt As String = "Select a folder..") As String
'returns "" if Cancel selected, else Path
Dim BINF As BROWSEINFO
Dim lpItem As Long
Dim sDir As String
With BINF
.hwndOwner = FindWindow("ThunderXFrame", 0)
'.pidlRoot = 0& 'open at desktop
.pidlRoot = 0 'CSIDL_DRIVES 'skips desktop <*> changed to 0 to show network folders
have a look here
for more information and a list of the constants you can use for the start folders to browse from
.pidlRoot = 0 'CSIDL_DRIVES 'skips desktop <*> changed to 0 to show network folders
this line is the one that sets the starting directory
0 is CSIDL_DESKTOP (0x0000)
The virtual folder representing the Windows desktop, the root of the namespace.
CSIDL_DRIVES is 11
CSIDL_DRIVES (0x0011)
The virtual folder representing My Computer, containing everything on the local computer: storage devices, printers, and Control Panel. The folder may also contain mapped network drives.
Cheers pete. I messed about with that, trying different values, and I now (I don't know why as as far as I can see the code is back to the way it was!) get the last-opened folder as the default, which is the value I want at least half the time.
Now, will I be able to enable this style of dialog with the input boxes at the bottom for file and type replaced by a pth to a directory?
I have to try rephrase that... I'd like to have a dialog like the one in the screenshot open instead of the current browser but with no option to select a file or filetype, only a directory.
If I understand you correctly you want to set an initial path for the BrowseForFolder dialog box. To be able to do that you need to create a callback function for the BrowseForFolder dialog box to call. You then have to check for the BFFM_INITIALIZED message and set the initial path you want to have selected when the dialog appears on screen.
Copy the below code to a regular BAS module (that's the only place a callback function can exist in).
'... and the rest of the code to determent the selected folder
As you can see above I make a call to a ReturnParam function, this is just a dummy function that returns the AddressOf the function. It looks like this:
VB Code:
Private Function ReturnParam(ByVal nParam As Long) As Long
'This function is a dummy function that only returns
'the argument passed to it.
ReturnParam = nParam
End Function
You need this function simply because you can't assign the AddressOf ShowFolderCallback directly to the structure member.
Last edited by Joacim Andersson; Jun 7th, 2005 at 04:25 PM.
Thanks for all the answers, but I'm in way over my head. I did a terrible job of trying to explain what I wanted, partially because I wasn't sure what I wanted. I'm going to read through the code in these replies and try and understand it, as it's bound to be useful to know.
This is going to sound stupid now, but I think what I want to do is simply replace the entire BrowseFolder function with something that simply opens a common dialog and returns a path to a directory.
Also, I plan to completely rewrite the multimacrorunner macro some day, as I think it's needlessly complicated for something that simply runs a selection of macros on a selection of files (hear the sound of an idiot underestimating work!)
I think I misunderstood your request in my earlier reply since I thought you wanted to be able to set an initial directory when the BrowseForFolder dialog box opened. But after reading it again I suspect what you're after is the dialog shown in the attached image.
That's easily fixed with the code you had. You only need to add on flag constant, marked as red in the code. You already had the flag constant for the edit box declared but you didn't use it so I added that to and marked it yellow below. Besides these changes the code is the same as you posted it. So there is no need to show an Open File dialog box when you want the user to select a folder.
VB Code:
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function SHBrowseForFolder Lib "shell32.dll" ( _
ByRef lpbi As BROWSEINFO) As Long
Private Declare Function SHGetPathFromIDList Lib "shell32.dll" ( _
pidl As Any, ByVal pszPath As String) As Long
'======= .bas wrapper for ShBrowseForFolder =======