This is an old revision of the document!
Selecting multiple files
by Richard Russell, March 2010
The main Help documentation describes how to use the Windows GetOpenFileName common dialogue to select a file (usually so it can subsequently be opened). That dialogue also permits the selection of multiple files (using the optional OFN_ALLOWMULTISELECT flag), but the format in which the filenames and paths are returned is quite tricky to deal with. The format also differs according to whether only one file, or multiple files, are selected.
The function listed below makes the selection of multiple files straightforward. It takes as parameters the title of the dialogue box, a file filter string and a string array in which to return the selected file(s); the function returns the number of files selected (or zero if the user clicked Cancel). The filter string contains the description(s) and extension(s) of the file types from which the user can make a selection. The array must be created before the function is called, and be sufficiently large to contain the maximum number of files that need to be selected; the first filename is returned in index 1 (not 0) of the array. An example of calling the function is as follows:
DIM files$(100)
filter$ = "All files"+CHR$(0)+"*.*"
num% = FNselectfiles("Select multiple files", filter$, files$())
IF num% THEN
FOR i% = 1 TO num%
PRINT files$(i%)
NEXT
ENDIF
If you want to sort the returned filenames into ascending alphabetical order you can easily do that using the SORTLIB library:
INSTALL @lib$+"SORTLIB"
sort% = FN_sortinit(0,0)
C% = num%
CALL sort%, files$(1)
Here is the function itself:
DEF FNselectfiles(title$, filter$, file$())
LOCAL fs{}, fp%, res%, nfiles%, P%, J%
DIM fs{lStructSize%, hwndOwner%, hInstance%, lpstrFilter%, \
\ lpstrCustomFilter%, nMaxCustFilter%, nFilterIndex%, \
\ lpstrFile%, nMaxFile%, lpstrFileTitle%, \
\ nMaxFileTitle%, lpstrInitialDir%, lpstrTitle%, \
\ flags%, nFileOffset{l&,h&}, nFileExtension{l&,h&}, \
\ lpstrDefExt%, lCustData%, lpfnHook%, lpTemplateName%}
DIM fp% LOCAL 65535
OFN_ALLOWMULTISELECT = &200
OFN_EXPLORER = &80000
title$ += CHR$0
filter$ += CHR$0+CHR$0
fs.lStructSize% = DIM(fs{})
fs.hwndOwner% = @hwnd%
fs.lpstrFilter% = !^filter$
fs.lpstrTitle% = !^title$
fs.lpstrFile% = fp%
fs.nMaxFile% = 65535
fs.flags% = OFN_ALLOWMULTISELECT OR OFN_EXPLORER
SYS "GetOpenFileName", fs{} TO res%
IF res% THEN
P% = fp%
WHILE ($$P% <> "") AND (nfiles% <= DIM(file$(),1))
file$(nfiles%) = $$P%
nfiles% += 1
P% += LEN$$P% + 1
ENDWHILE
IF nfiles%>1 THEN
nfiles% -= 1
FOR J% = 1 TO nfiles%
file$(J%) = file$(0)+"\"+file$(J%)
NEXT J%
ELSE
file$(1) = file$(0)
ENDIF
ENDIF
=nfiles%
The maximum number of files which may be returned is limited by the size of the supplied array, and by the total size of all the filenames not exceeding 65535 bytes.