anton
New Member
Posts: 9
|
Post by anton on Oct 4, 2023 17:06:52 GMT -5
Hi Everyone. I could really use some help. I am trying to open a file dialog that allows multi-selection of files. I have Alyce's wonderful book "APi's for Liberty Basic". I have tried to follow her directions, but I can not even get a filedialog to open. Below is my Code. I cut out everything but the necessary code. Any advice is welcome. Thank you Anton.
istruct ofn, _
lStructSize as ulong, _ 'size of struct
hwndOwner as ulong, _ 'owner window, can be null
hInstance as ulong, _ 'instance handle, can be null
lpstrFilter$ as ptr, _ 'filter strings, see below
lpstrCustomFilter$ as ptr, _ 'user's filter string choice
nMaxCustFilter as ulong, _ 'length of lpstrCustomFilter$
nFilterIndex as ulong, _ 'index of currently selected filter
lpstrFile$ as ptr, _ 'filename used to initialize
nMaxFile as ulong, _ 'length of lpstrFile$
lpstrFileTitle$ as ptr, _ 'buffer to receive filename without path
nMaxFileTitle as ulong, _ 'length of lpstrFileTitle$
lpstrInitialDir$ as ptr, _ 'initial file directory, or null for current
directory as ptr,_
lpstrTitle$ as ptr, _ 'titlebar string for dialog
flags as ulong, _ 'initialization flags, see below
nFileOffset as word, _ '0-based offset to filename in lpstrFile$
nFileExtension as word, _ '0-based offset to extension in lpstrFile$
lpstrDefExt$ as ptr, _ 'default extension if none is typed
lCustData as ulong, _ 'not used here
lpfnHook as long, _ 'hook procedure, not used here
lpTemplateName as long 'template name, not used here
lStructSize = len(ofn.struct)
Filter$ = "All files" + chr$(0) + "*.*" + chr$(0) + chr$(0)
ofn.lpstrCustomFilter$.struct = space$(260) + chr$(0)
ofn.nMaxCustFilter.struct = 260
ofn.nFilterIndex.struct = 1
ofn.lpstrFile$.struct = chr$(0) + space$(260) + chr$(0)
ofn.nMaxFile.struct = 260
ofn.lpstrFileTitle$.struct = space$(260) + chr$(0)
ofn.nMaxFileTitle.struct = 0'260
ofn.lpstrInitialDir$.struct = "C:\" + chr$(0)
ofn.lpstrTitle$.struct = "Open my file" + chr$(0)
ofn.lpstrDefExt$.struct = "doc" + chr$(0)
ofn.flags.struct = _OFN_PATHMUSTEXIST or _OFN_FILEMUSTEXIST _
or _OFN_ALLOWMULTISELECT
open "comdlg32.dll" for dll as #comdlg32
calldll #comdlg32,"GetOpenFileNameA",ofn As struct, re As word
notice re
b$=winstring(ofn.lpstrFile$.struct)
close #comdlg32
nsert code here
|
|
|
Post by tsh73 on Oct 5, 2023 5:35:08 GMT -5
|
|
|
Post by tsh73 on Oct 5, 2023 14:48:55 GMT -5
Here's old code from old forum , by Sephi I changed Long for uLong, that's all Looks working, multiselect too
OFN.EXPLORER = hexdec("&H80000")
filename$=GetOpenFileName$("Select files to copy","C:\","All Files"+chr$(0)+"*.*"+chr$(0)+chr$(0),0,1) notice "Files selected"+chr$(13)+filename$ print print ">";filename$;"<"
wait
Function GetOpenFileName$(title$, path$, filter$, filterIdx, multiselect) 'Returns a single file path or a chr$(13) delimited string of filepaths OFN.EXPLORER = 524288
Struct ofn, _ lStructSize As uLong, _ hwndOwner As uLong, _ hInstance As uLong, _ lpstrFilter$ As Ptr, _ lpstrCustomFilter$ As Ptr, _ nMaxCustFilter As uLong, _ nFilterIndex As uLong, _ lpstrFile$ As Ptr, _ nMaxFile As uLong, _ lpstrFileTitle$ As Ptr, _ nMaxFileTitle As uLong, _ lpstrInitialDir$ As Ptr, _ lpstrTitle$ As Ptr, _ Flags As uLong, _ nFileOffset As Word, _ nFileExtension As Word, _ lpstrDefExt As uLong, _ lCustData As uLong, _ lpfnHook As uLong, _ lpTemplateName As uLong
ofn.lStructSize.struct = Len(ofn.struct)
ofn.lpstrFilter$.struct = filter$ ofn.nFilterIndex.struct = filterIdx 'Allow a lot of files to be chosen, 32000 characters ofn.lpstrFile$.struct = Chr$(0) + Space$(32000) + Chr$(0) ofn.nMaxFile.struct = 32000 ofn.lpstrInitialDir$.struct = path$ + Chr$(0) ofn.lpstrTitle$.struct = title$ + Chr$(0) ofn.lpstrDefExt.struct = 0
If multiselect = 1 Then ofn.Flags.struct = _OFN_ALLOWMULTISELECT Or _OFN_PATHMUSTEXIST Or OFN.EXPLORER Else ofn.Flags.struct = _OFN_PATHMUSTEXIST Or OFN.EXPLORER End If
Calldll #comdlg32, "GetOpenFileNameA", ofn As Struct, r As uLong
If r Then q$ = Chr$(34) path$ = Winstring(ofn.lpstrFile$.struct) ofnPath$ = Left$(path$,ofn.nFileOffset.struct) If Right$(ofnPath$,1) <> "\" Then ofnPath$ = ofnPath$ + "\" End If
offset = ofn.lpstrFile$.struct + ofn.nFileOffset.struct file$ = Winstring(offset) GetOpenFileName$ = ofnPath$ + file$
If multiselect = 1 Then If GetOpenFileName$ <> "" Then GetOpenFileName$ = GetOpenFileName$ + Chr$(13) End If While file$<>"" offset = offset + Len(file$) + 1 file$ = Winstring(offset) If file$<>"" Then GetOpenFileName$ = GetOpenFileName$ + ofnPath$ + file$ + Chr$(13) End If Wend End If GetOpenFileName$ = Trim$(GetOpenFileName$) Else 'User cancelled or error, 'see CommDlgExtendedError API. End If End Function
|
|
|
Post by xxgeek on Oct 12, 2023 11:17:28 GMT -5
Nice, I've always wanted a MultiFile selector, been using one that creates it with VB script I wrote. Thanks for posting this.
I have edited it slightly due to a few crashes when too many files were selected. (not a lot, but too many for the allowed number of characters - changed 32000 to 256000) May need to be even larger depending on how many files get selected, or the length of the paths.
Also added some comments etc for those new to Liberty Basic. It goes to show you don't need to be an API expert, or even know anything about API's to use one that has been already written.
I AM curious about the first line in the code. OFN.EXPLORER = hexdec("&H80000") What is it, what does it do, and is it really necessary?
'written by Sephi - referred to by tsh73 @ https://libertybasiccom.proboards.com/thread/2426/multi-select-file-dialog?page=1&scrollTo=17735 'editted slightly by xxgeek
'OFN.EXPLORER = hexdec("&H80000") ' - this line seems to be unecessary??? 'works without the above line
'open a fileDialog to MultiSelect some files (one file can be selected if desired) filenames$=GetOpenFileName$("Select files to copy","C:\","All Files"+chr$(0)+"*.*"+chr$(0)+chr$(0),0,1)
'print the list to a file open "FilesList.txt" for output as #1 #1 filenames$ : close #1
'create an array of the selected files using line input to retrieve each line in FilesList.txt dim fileList$(numFiles) ' creates the space in memory for the array fileList$() print "Selected Files are Listed Below" print open DefaultDir$;"\FilesList.txt" for input as #1 while eof(#1) = 0 fileNum = fileNum + 1 line input #1, fileList$(fileNum) 'takes a line in FilesList.txt, adds it to array fileList$() - loops till end of file
'to print the list to mainwin as it is created (uncomment the next 2 print lines) 'print fileList$(fileNum) wend 'print 'an empty line
'Or print the array to mainwin (comment the next 5 lines if not) print "Printing all paths in the array" print 'The array fileList$() holds all the selected file paths. for arrayList = 1 to numFiles print "fileList$(";arrayList;") = ";fileList$(arrayList) ' prints the array from memory next arrayList
'Now that you have an array with all the selected file paths, you can 'use those paths any which way you choose 'As An Example (select only 3 files for this example '(from an unprotected/non system folder or drive)
'The 3 chosen files should open in a separate Notepad instance 'UnComment the next 3 lines to try the example 'for example = 1 to 3 ' run "notepad ";fileList$(example) 'next example wait
Function GetOpenFileName$(title$, path$, filter$, filterIdx, multiselect) global numFiles 'Returns a single file path or a chr$(13) delimited string of filepaths OFN.EXPLORER = 524288 Struct ofn, _ lStructSize As uLong, _ hwndOwner As uLong, _ hInstance As uLong, _ lpstrFilter$ As Ptr, _ lpstrCustomFilter$ As Ptr, _ nMaxCustFilter As uLong, _ nFilterIndex As uLong, _ lpstrFile$ As Ptr, _ nMaxFile As uLong, _ lpstrFileTitle$ As Ptr, _ nMaxFileTitle As uLong, _ lpstrInitialDir$ As Ptr, _ lpstrTitle$ As Ptr, _ Flags As uLong, _ nFileOffset As Word, _ nFileExtension As Word, _ lpstrDefExt As uLong, _ lCustData As uLong, _ lpfnHook As uLong, _ lpTemplateName As uLong ofn.lStructSize.struct = Len(ofn.struct) ofn.lpstrFilter$.struct = filter$ ofn.nFilterIndex.struct = filterIdx 'Allow a lot of files to be chosen, 256000 characters ' (increased from 32000 due to crashing on long lists) ofn.lpstrFile$.struct = Chr$(0) + Space$(256000) + Chr$(0) ofn.nMaxFile.struct = 256000 ofn.lpstrInitialDir$.struct = path$ + Chr$(0) ofn.lpstrTitle$.struct = title$ + Chr$(0) ofn.lpstrDefExt.struct = 0 If multiselect = 1 Then ofn.Flags.struct = _OFN_ALLOWMULTISELECT Or _OFN_PATHMUSTEXIST Or OFN.EXPLORER Else ofn.Flags.struct = _OFN_PATHMUSTEXIST Or OFN.EXPLORER End If Calldll #comdlg32, "GetOpenFileNameA", ofn As Struct, r As uLong If r Then ' q$ = Chr$(34) - unecessay line (q$ never gets used) path$ = Winstring(ofn.lpstrFile$.struct) ofnPath$ = Left$(path$,ofn.nFileOffset.struct) If Right$(ofnPath$,1) <> "\" Then ofnPath$ = ofnPath$ + "\" End If offset = ofn.lpstrFile$.struct + ofn.nFileOffset.struct file$ = Winstring(offset) GetOpenFileName$ = ofnPath$ + file$ If multiselect = 1 Then If GetOpenFileName$ <> "" Then GetOpenFileName$ = GetOpenFileName$ + Chr$(13) End If While file$<>"" numFiles = numFiles + 1 'counts the number of files selected to dim array(make global too) offset = offset + Len(file$) + 1 file$ = Winstring(offset) If file$<>"" Then GetOpenFileName$ = GetOpenFileName$ + ofnPath$ + file$ + Chr$(13) End If Wend print "Number of Files Selected = ";numFiles End If GetOpenFileName$ = Trim$(GetOpenFileName$) Else 'User cancelled or error, 'see CommDlgExtendedError API. End If End Function
|
|
|
Post by tsh73 on Oct 12, 2023 12:04:07 GMT -5
I expect file dialog to be used for selecting *some* amount of files Now, for Windows MAX_PATH is said to be 260 32000/260 ~ 123 Do you really have case there you need to select more then 100 files?
It is used in this piece of code
If multiselect = 1 Then ofn.Flags.struct = _OFN_ALLOWMULTISELECT Or _OFN_PATHMUSTEXIST Or OFN.EXPLORER Else ofn.Flags.struct = _OFN_PATHMUSTEXIST Or OFN.EXPLORER End If It sets bit-flags in the field ofn.Flags.struct Obviously, LB has some Windows constants defined to variables like _OFN_ALLOWMULTISELECT but OFN.EXPLORER is not on the list (print _OFN_EXPLORER errors during compile with "Undefined windows constant" But this value is needed, so author created a variable and assigned it a (right) number. (which was probably googled somewhere) )
|
|
|
Post by xxgeek on Oct 12, 2023 12:24:48 GMT -5
Thanks again for the quick response.
I don't really have a need to select 100 files, only for testing purposes. I wasn't selecting anywhere near 100 files though, and it was crashing the app using 32000, plus the LB IDE went down with it.
So I guess it would be best to keep the first line of code to avoid "other" possible issues?
Just tested 10 files using 32000 and it crashes. Using 256000 I had no problems with 500 files selected.
Code above has been edited to keep the first line of code, and to show the array contents in mainwin.
|
|