Set root folder of DirListBox
I'd really like to use a DirListBox, but I need to be able to set its root folder to something other than "C:\". Anyone know how to do this?
Specifically, I want to create an empty folder tree under Application Data to use as a placeholder. The user will then navigate this temporary folder tree using a DirListBox to select a folder. When done, I delete the temporary folder tree.
The user interface has very little room, making the DirListBox control highly preferable to a treeview. The regular DirListBox shows all parent paths, which in this case will end up being very confusing since the ultimate root folder will appear below the user's Application Data folder.
I'm hoping there is an API command that can simply overwrite the DirListBox's internal "RootPath" variable with whatever the programmer wants. Probably as simple as using SendMessage API.
Re: Set root folder of DirListBox
I doubt there is an api. The DirListBox is simply a windows listbox, owner drawn. Since VB designed it for navigation, internally, VB will always show the root drive. You might have more success in designing your own or using the BrowseForFolder API which I believe can do what you want. Here's an example:
Code:
Option Explicit
Private Declare Sub CoTaskMemFree Lib "ole32.dll" (ByVal hMem As Long)
Private Declare Function SHParseDisplayName Lib "shell32.dll" (ByVal pszName As Long, ByVal pbc As Long, ByRef ppidl As Long, ByVal sfgaoIn As Long, ByRef psfgaoOut As Long) As Long
Private Declare Function SHBrowseForFolder Lib "Shell32" (lpbi As BrowseInfo) As Long
Private Declare Function SHGetPathFromIDList Lib "Shell32" (ByVal pidList As Long, ByVal lpBuffer As String) As Long
Private Const BIF_RETURNONLYFSDIRS = 1
Private Const MAX_PATH = 260
Private Type BrowseInfo
hwndOwner As Long
pIDLRoot As Long
pszDisplayName As Long
lpszTitle As Long
ulFlags As Long
lpfnCallback As Long
lParam As Long
iImage As Long
End Type
Private Function BrowseForFolder(Optional Title As String, Optional StartupDir As String) As String
Dim lpIDList As Long
Dim sBuffer As String
Dim szTitle() As Byte
Dim tBrowseInfo As BrowseInfo
szTitle() = StrConv(Title & vbNullChar, vbFromUnicode)
With tBrowseInfo
.hwndOwner = Me.hWnd
.lpszTitle = VarPtr(szTitle(0))
.ulFlags = BIF_RETURNONLYFSDIRS
If Len(StartupDir) Then
Call SHParseDisplayName(StrPtr(StartupDir), ByVal 0&, .pIDLRoot, ByVal 0&, ByVal 0&)
End If
End With
lpIDList = SHBrowseForFolder(tBrowseInfo)
If tBrowseInfo.pIDLRoot Then Call CoTaskMemFree(tBrowseInfo.pIDLRoot)
If (lpIDList) Then
sBuffer = Space(MAX_PATH)
SHGetPathFromIDList lpIDList, sBuffer
sBuffer = Left(sBuffer, InStr(sBuffer, vbNullChar) - 1)
Call CoTaskMemFree(lpIDList)
BrowseForFolder = sBuffer
End If
End Function
Private Sub Command1_Click()
Debug.Print BrowseForFolder("Select Folder", "C:\Program Files")
End Sub
Edited: P.S. And if form real estate is a concern, you can't beat this option. A button, label, or menu can trigger it.
Re: Set root folder of DirListBox
I appreciate the response. I figured if anyone would know, it'd be you.
I already have the BrowseFolder code in my xp library. While it is indeed extremely space-efficient, it's too cumbersome to use for this specific implementation. As in it would require too many mouse clicks. A listbox is so much smoother, GUI-wise, at least for this.
My app is almost finished, and so far it's reference- and component-free, meaning I would hate to add dependencies just for a listbox. So that makes the imagelist+treeview alternative less than ideal.
I think instead I'll just use a regular listbox and deal with the folder structure manually, basically by adding a few spaces of indentation to the begininning of the List() item for each subfolder level, and simply repopulate the listbox after every mouse click. I was really hoping to have the folder icons, but it'll still work without them.
Thanks much for your time.
EDIT: In looking more closely I find your BrowseForFolder solution intriguing, though not for this specific app. Mine uses CSIDL instead of a string for the default folder.
Re: Set root folder of DirListBox
i found i could cheat the dirlistbox
if i found the index for a folder to be root, i could limit the topindex
this may not be suitable for what you want, but you can have a look
vb Code:
'declare ti at form level
Dir1.Path = Environ("appdata")
i = 0
Do Until Dir1.List(i) = ""
i = i - 1
Loop
ti = Abs(i + 2)
Private Sub Dir1_Scroll()
If Dir1.TopIndex < ti Then Dir1.TopIndex = ti
End Sub
Re: Set root folder of DirListBox
That looks very promising, but I'm a little confused by the code. First off, shouldn't it throw a runtime error pretty much immediately when you subtract 1 from i, meaning the second iteration of the Do...Loop tries to reference Dir1.List(-1)?
Then what's going on with the Abs() deal?
I tried to do what you describe on my own with no love, so I'm thinking the weirdness in your code is deliberate and necessary. I'd love to understand it better.
Re: Set root folder of DirListBox
my testing showed dir1.list(0) to be the first item below dir1.path
so dir1.path and all upwards items are negative
vb Code:
for i = 0 to dir1.listcount
debug.print dir1.list(i)
next
will print all items below the path
you do not need to use environ to set a path, just a very easy way to fill the dir list
don't know why you were having a problem with the code, i just put a dir list, the 1st code can be in form load
don't need to use abs, as always negative, could use ti = -i -2
in my case using appdata as the path, c:\ was dir1.list(-5), so ti needed to be 3
where is your code failing?
Re: Set root folder of DirListBox
One more option. Here is a complex Solution... but doable...
Use a DirListBox (Which will be hidden) and a treeview and set the parent node to "..." and set it's sub node to the default folder that you want... When the user clicks the "..." then display the DirListBox and hide the treeview.
This way you will control the treeview from the Dirlistbox. You can also set the icons of the treeview...
Well, just a thought...
Re: Set root folder of DirListBox
The treeview control is far superior to the DirListBox, so once you introduce the treeview the solution is complete. The only reasons I'm not using a treeview are 1) because the DirListBox is more space-efficient in the GUI, and 2) my otherwise complete project doesn't have a single component or reference, so adding a dependency for what amounts to a single listbox seems rather pointless.
Without dependencies, you don't need any installation routine for pretty much any version of Windows after 2000, and since several parts of my app already require XP or higher anyway the lack of needing any installation is a big plus.
EDIT: One of the very few legitimate reasons to program in VB6 at all is not needing any installation.