=====Customising the Browse for Folder dialogue=====
//by Richard Russell, July 2009//\\ \\ The main [[http://www.bbcbasic.co.uk/bbcwin/manual/bbcwine.html#browsefolder|Help documentation]] explains how you can use the Windows API to display a **Browse for Folder** dialogue box, allowing the user to select a folder (directory) for some purpose.\\ \\ Unfortunately the basic functionality of **SHBrowseForFolder** is not very flexible, so below are listed two functions, the first of which lets you specify the **root** folder that the browse operation starts from, and the second lets you specify the **initial** folder selection. In both cases the default folder (i.e. the one returned if you simply click on OK) is the specified folder, but the difference is that in the first case you cannot navigate 'above' that folder, whereas in the second case you can.\\ \\ The first function, **FNbrowseforfolderroot**, is called in the following context:
title$ = "Set root selection"
root$ = "C:\bbcbasic\windows\programs"
folder$ = FNbrowseforfolderroot(title$, root$)
The second function, **FNbrowseforfolderinit**, is called in the following context:
INSTALL @lib$+"CALLBACK"
title$ = "Set initial selection"
init$ = "C:\bbcbasic\windows\programs"
folder$ = FNbrowseforfolderinit(title$, init$)
It would in principle be possible to combine the functions of the two routines, so that both the **root** and the **initial selection** may be specified, however that's not very likely to be required in practice.\\ \\ Here are the functions:
DEF FNbrowseforfolderroot(title$, root$)
LOCAL folder%, pathw%, pidl%, malloc%, bi{}
title$ += CHR$0 : root$ += CHR$0
BIF_USENEWUI = &40
DIM folder% LOCAL 260, pathw% LOCAL 520
SYS "MultiByteToWideChar", 0, 0, root$, -1, pathw%, 260
SYS "ILCreateFromPath", pathw% TO pidl%
DIM bi{hOwner%, pidlRoot%, pszDisplayName%, \
\ lpszTitle%, ulFlags%, lpfn%, lParam%, iImage%}
bi.hOwner% = @hwnd%
bi.pidlRoot% = pidl%
bi.pszDisplayName% = folder%
bi.lpszTitle% = !^title$
bi.ulFlags% = BIF_USENEWUI
SYS "SHBrowseForFolder", bi{} TO pidl%
IF pidl% THEN
SYS "SHGetPathFromIDList", pidl%, folder%
SYS "SHGetMalloc", ^malloc%
SYS !(!malloc%+20), malloc%, pidl%
ENDIF
=$$folder%
DEF FNbrowseforfolderinit(title$, init$)
LOCAL folder%, pidl%, malloc%, bi{}
title$ += CHR$0 : init$ += CHR$0
BFFM_INITIALIZED = 1
BFFM_SETSELECTION = &466
BIF_USENEWUI = &40
DIM folder% LOCAL 260
DIM bi{hOwner%, pidlRoot%, pszDisplayName%, \
\ lpszTitle%, ulFlags%, lpfn%, lParam%, iImage%}
bi.hOwner% = @hwnd%
bi.pszDisplayName% = folder%
bi.lpszTitle% = !^title$
bi.ulFlags% = BIF_USENEWUI
bi.lpfn% = FN_callback(FNBrowseCallbackProc(),4)
bi.lParam% = !^init$
SYS FN_syscalls("SHBrowseForFolder"), bi{}
pidl% = FN_sysresult
IF pidl% THEN
SYS "SHGetPathFromIDList", pidl%, folder%
SYS "SHGetMalloc", ^malloc%
SYS !(!malloc%+20), malloc%, pidl%
ENDIF
=$$folder%
DEF FNBrowseCallbackProc(hwnd%, uMsg%, lParam%, lpData%)
IF uMsg% <> BFFM_INITIALIZED THEN = 0
lParam% = FN_sendmessage(hwnd%, BFFM_SETSELECTION, TRUE, lpData%)
= 0