Browsing and Exploring a Folder

skill level: intermediate

© 2003, Alyce Watson

Alyce's Restaurant

Home

Blast from the past

Beginning Game Programming

Differential Equations

Browsing and Exploring a Folder

Flash-O-Rama!

Beginning Programming Part IV

Four Methods for Drawing Arcs

Newsletter Help

Index

Browse For Folder --- Explore a Folder --- Sample Program

This article contains two methods. The first shows a "Browse For Folder" dialog. The second method shows how to let the users of your program activate Windows Explorer to investigate the contents of a folder. The two methods are combined in the sample program at the end, but they can be used independently. In fact, it is most likely that you will use them separately!


Browse For Folder Dialog

A Liberty BASIC FILEDIALOG allows the user to select a filename. Sometimes you want to give your users the chance to select a folder. You can do this with the SHBrowseForFolder API call.

The Browse For Folder Dialog looks like this:

browse for folder

This isn't a simple API call, but it isn't difficult to use if you follow the code given here. It is taken apart and explained in the body of the article, and the entire program is included at the bottom.

You must first build a struct to contain information sent to the function.

STRUCT BrowseInfo,_
    hWndOwner As Long,_
    pIDLRoot As Long,_
    pszDisplayName As Long,_
    lpszTitle$ As ptr,_
    ulFlags As Long,_
    lpfnCallback As Long,_
    lParam As Long,_
    iImage As Long

There is a struct member provided for the text that will display at the top of the Browse Dialog. Here it is set to contain two lines of text:

    crlf$=chr$(13)+chr$(10)

    'set up text to display on the dialog:
    txt1$="This is a Liberty BASIC 3+ capability!" + crlf$
    txt1$=txt1$+"Please choose a folder!"

    'fill the struct item with the text
    BrowseInfo.lpszTitle$.struct = txt1$

You also need to set a flag to tell the function to return directories:

 BIF.RETURNONLYFSDIRS = 1

   'Return only if the user selected a directory
    BrowseInfo.ulFlags.struct = BIF.RETURNONLYFSDIRS

Make the API call to Shell32 DLL like this:

    'Show the 'Browse for folder' dialog
    calldll #shell32, "SHBrowseForFolder",_
        BrowseInfo as struct,_
        lpIDList as long

If the function is successful, the return is a pointer to an ID List. You can retrieve the complete path and name of the folder chosen by setting up a string buffer to hold the name. The buffer must be terminated by chr$(0), to tell Liberty BASIC to pass the address of the buffer so that it can be modified by the API function. Without the null termination, Liberty BASIC passes a copy of the string, which cannot be modified by the function. You then call the SHGetPathFromIDList function, which requires the pointer to the ID List that was returned by the SHBrowseForFolder function. When this function completes its task, the path/foldername chosen by the user is contained in the buffer you set up. It sounds complicated, but it is easy to do using the following code.

    MAX.PATH = 260
    'return > 0 = success, so continue
    If lpIDList>0 Then
        'set up a string buffer:
        sPath$ = space$(MAX.PATH) + chr$(0)
        'Get the path from the IDList
        calldll #shell32, "SHGetPathFromIDList",_
            lpIDList as long,_
            sPath$ as ptr,_
            r as long
     End If
        'the folder name is now in sPath$

You now must free the memory taken by the ID List. This is done with a simple API call that requires the ID of the list.

        open "ole32" for dll as #ole
        'free the block of memory
        calldll #ole, "CoTaskMemFree",_
            lpIDList as long,_
            r as long
        close #ole

The path/foldername chosen by the user is now in sPath$. The name will be terminated by a null character - chr$(0) - so you can check for the placement of a null character in the string to discover the actual length of the path/folder and truncate the string accordingly.

        'check for null char, which
        'signals end of folder name string
        iNull = InStr(sPath$, chr$(0))

        'truncate string at null character
        If iNull Then
            sPath$ = Left$(sPath$, iNull - 1)
        End If


Browse For Folder --- Explore a Folder --- Sample Program


Exploring a Folder

There have been articles in previous newsletters about the ShellExecute API function. Issue #63 dealt with using ShellExecute to open files of various types. Issue #74 discussed printing a text file with ShellExecute. Issue #103 discussed printing graphics with ShellExecute.

It is also possible to use the ShellExecuteA function to explore a specified folder on disk. To do it, the "operation" parameter is "explore" and the "filename" parameter is a null, or empty string. The "directory" parameter is the folder to explore with Windows Explorer. If the "directory" parameter is a null string, it is likely that the program's DefaultDir$ will be called up in Windows Explorer. The "window handle" parameter can be the handle of a program window, or it can be 0. The "showflag" parameter is set to "_SW_SHOWNA", which shows the Windows Explorer window at its normal size (not minimized, maximized or hidden). The following small demo causes Windows Explorer to open in the program's DefaultDir$.

    hWnd = 0                   'window handle, can be 0
    lpszOp$ =  "explore"       'operation to perform
    lpszFile$ = ""             'filename, null here
    lpszParams$=""             'extra info
    lpszDir$ = DefaultDir$     'directory
    showflag = _SW_SHOWNA      'show normal

    CallDLL #shell32, "ShellExecuteA",_
    hWnd As long,_
    lpszOp$ As ptr,_
    lpszFile$ As ptr,_
    lpszParams$ As ptr,_
    lpszDir$ As ptr,_
    showflag As long,_
    result As long

    end

The sample demo combines the two methods discussed in this article. It allows a user to select a folder with the SHBrowseForFolder function and it then calls Windows Explorer with the ShellExecuteA API call to explore the folder. Either method can be used separately as detailed above.


Browse For Folder --- Explore a Folder --- Sample Program


Sample Program


'set up constants for api calls
BIF.RETURNONLYFSDIRS = 1
MAX.PATH = 260
crlf$=chr$(13)+chr$(10)

'create struct for api call
STRUCT BrowseInfo,_
    hWndOwner As Long,_
    pIDLRoot As Long,_
    pszDisplayName As Long,_
    lpszTitle$ As ptr,_
    ulFlags As Long,_
    lpfnCallback As Long,_
    lParam As Long,_
    iImage As Long

    'Set the owner window, optional
    BrowseInfo.hWndOwner.struct = 0

    'set up text to display on the dialog:
    txt1$="This is a Liberty BASIC 3+ capability!" + crlf$
    txt1$=txt1$+"Please choose a folder!"

    'fill the struct item with the text
    BrowseInfo.lpszTitle$.struct = txt1$

    'Return only if the user selected a directory
    BrowseInfo.ulFlags.struct = BIF.RETURNONLYFSDIRS

    'Show the 'Browse for folder' dialog
    calldll #shell32, "SHBrowseForFolder",_
        BrowseInfo as struct,_
        lpIDList as long

    'return > 0 = success, so continue
    If lpIDList>0 Then
		'set up a string buffer:
       sPath$ = space$(MAX.PATH) + chr$(0)
        'Get the path from the IDList
        calldll #shell32, "SHGetPathFromIDList",_
            lpIDList as long,_
            sPath$ as ptr,_
            r as long

        'the folder name is now in sPath$

        open "ole32" for dll as #ole
        'free the block of memory
        calldll #ole, "CoTaskMemFree",_
            lpIDList as long,_
            r as long
        close #ole

        'check for null char, which
        'signals end of folder name string
        iNull = InStr(sPath$, chr$(0))

        'truncate string at null character
        If iNull Then
            sPath$ = Left$(sPath$, iNull - 1)
        End If
    End If

    'if user cancelled, sPath$ is empty
    if sPath$="" then sPath$="Cancelled"

    print "Folder chosen is "
    print sPath$

    if sPath$="Cancelled" then end

'now cause Explorer to open in that folder
call ShellExecute 0, sPath$,_SW_SHOWNA, "explore"

end

Sub ShellExecute hWnd, file$, parameter, lpszOp$
    ' _SW_SHOWNA      show normal
    ' _SW_HIDE        hide window
    ' _SW_MINIMIZE    minimize window
    ' lpszOp$ =  "open" or "print" or "explore"
    lpszFile$ = file$ 
    lpszDir$ = DefaultDir$ 
    lpszParams$=""
    CallDLL #shell32, "ShellExecuteA", hWnd As long,_
    lpszOp$ As ptr,lpszFile$ As ptr,_
    lpszParams$ As ptr,lpszDir$ As ptr,_
    parameter As long, result As long
    End Sub


Home

Blast from the past

Beginning Game Programming

Differential Equations

Browsing and Exploring a Folder

Flash-O-Rama!

Beginning Programming Part IV

Four Methods for Drawing Arcs

Newsletter Help

Index