FILEDIALOG - Path length limited: Difference between revisions

From Liberty BASIC Family
Jump to navigation Jump to search
m (Text replacement - "Bug Tracker Categories" to "Bug Tracker")
 
m (1 revision imported)
 

Latest revision as of 03:03, 11 October 2023

Description

The path length returned by the file dialog is limited to 128 characters. The path is not truncated, but an error is raised and the command execution fails.

Example code to demonstrate the bug.

    filedialog "open ...", "*.*", File$
    print len(File$)

' if path is longer than 128 characters you will get
' Runtime error: Wrong Parameter. ( OS error 16r57 )

Example code to work around the bug.

Selecting Multiple Files - by Stefan Pendl

    Dir$ = "C:\"
    Filter$ = "Textfiles|*.txt;*.bat|All Files|*.*"
    Title$ = "Select Files"

    print FileExplorer$(Title$, Dir$, Filter$)
end

function FileExplorer$(Caption$, InitialDir$, FilterString$)
' function to select multiple files
'
' Usage:
'       FilterString in the form of {description}|{list of extensions}
'           extensions are seperated with semicolons (;)
'           multiple pairs are supported
'           field seperator is the pipe (|)
'
' the returned string consits of the number of files
' and the directory followed by the filenames
' all fields are seperated by semicolons (;)

    OFN.EXPLORER = hexdec("80000")
    z$ = chr$(0)

    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 ptr, _
        lCustData          as ulong, _
        lpfnHook           as ulong, _
        lpTemplateName$    as ptr

    Filter$ = ReplaceString$(FilterString$, "|", z$, "ALL", 0) + z$ + z$

    ofn.lStructSize.struct = len(ofn.struct)
    ofn.lpstrFilter$.struct = Filter$
    ofn.lpstrFile$.struct = z$ + space$(3072) + z$
    ofn.nMaxFile.struct = 3072
    ofn.lpstrFileTitle$.struct = space$(255) + z$
    ofn.nMaxFileTitle.struct = 255
    ofn.lpstrInitialDir$.struct = InitialDir$ + z$
    ofn.lpstrTitle$.struct = Caption$ + z$
    ofn.flags.struct = _OFN_PATHMUSTEXIST or _OFN_FILEMUSTEXIST or _OFN_ALLOWMULTISELECT or OFN.EXPLORER

    calldll #comdlg32, "GetOpenFileNameA",_
        ofn as struct,_
        ok  as boolean

    pointer = ofn.lpstrFile$.struct
    count = 0

    If ok Then
        FileExplorer$ = WinString(pointer)
        pointer = pointer + Len(FileExplorer$) + 1
        program$ = WinString(pointer)

        if program$ = "" then
            FileExplorer$ = DirName$(FileExplorer$); ";";BaseName$(FileExplorer$, "", "")
            count = 1
        else
            While program$ <> ""
                FileExplorer$ = FileExplorer$; ";"; program$
                pointer = pointer + Len(program$) + 1
                count = count + 1
                program$ = WinString(pointer)
            Wend
        end if
    End If

    FileExplorer$ = count; ";"; FileExplorer$
end function

function BaseName$(input$, ext$, sep$)
' returns the name of the given file
' if ext$ matches the last part of
' input$ it will be cut off
    if sep$ = "" then sep$ = "\"

    if len(ext$) > 0 and right$(input$, len(ext$)) = ext$ then _
        input$ = left$(input$,len(input$) - len(ext$))

    BaseName$ = input$
    bsPos = len(input$)
    while mid$(input$, bsPos, 1) <> sep$ and bsPos > 0
        bsPos = bsPos - 1
    wend

    if bsPos <> 0 then BaseName$ = right$(input$,len(input$) - bsPos)
end function

function DirName$(input$)
' returns the path of the given file

    DirName$ = input$
    bsPos = len(input$)
    while mid$(input$, bsPos, 1) <> "\" and bsPos > 0
        bsPos = bsPos - 1
    wend

    if bsPos <> 0 then DirName$ = left$(input$,bsPos - 1)
end function

function ReplaceString$(in$,ere$,repl$,occ$,pos)
' Function to replace expressions in strings
'
' Usage:
'
'
' ReplaceString$({string},{expression},{replacement},{occurrances},{startposition})
'
'       string .......... string to be parsed
'       expression ...... string to be replaced
'       replacement ..... substitute for expression
'       occurrances ..... ALL -> replaces all occurrances
'                         else the specified number
'       startposition ... position from where to start substitution
'
'   returns altered string
    ReplaceString$ = in$
    if upper$(occ$) = "ALL" then
        number = len(in$)
    else
        number = val(occ$)
    end if
    if pos < 0 then pos = 0

    while instr(ReplaceString$,ere$,pos) > 0
        pos = instr(ReplaceString$,ere$,pos)

        ReplaceString$ = left$(ReplaceString$,pos - 1) + repl$ + mid$(ReplaceString$,pos + len(ere$))

        if upper$(occ$) = "ALL" and number > 1 then
            pos = pos + len(repl$)
            number = number - 1
        else
            pos = len(ReplaceString$)
        end if
    wend
end function

Shared Code from LB Community Wiki

function uSaveFileDialog$(filter$, defaultExt$, initialDir$, initialFile$, windTitle$)
    'Opens dialog to find file name for saving file. Returns full path name+file name+extension
    'filter$ specifies the type of file to allow. Sample:
    'filter$ = "Text files" + chr$(0) + "*.txt" + chr$(0) + _
    '       "All files" + chr$(0) + "*.*"
    'filter$ is pairs of strings, or null for no filter
    'defaultExt$ is the extension to add if the user does not specify one; do not include the period
    'initialDir$ is the directory in which to start
    'windTitle$ is the title of the dialog window

    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 ptr, _
        lCustData as ulong, lpfnHook as long, lpTemplateName as long

    ofn.lStructSize.struct = len(ofn.struct)    'len of this struct
    ofn.lpstrFilter$.struct = filter$+ chr$(0) + chr$(0)   'filter for file types
    ofn.nFilterIndex.struct = 1     'Filter initially selected
    ofn.lpstrFile$.struct = initialFile$+chr$(0) + space$(360) + chr$(0) 'File name used to initialize; receives full selected file path+name
    ofn.nMaxFile.struct = 360   'length of lpstrFile$; buffer may actually be longer
    ofn.lpstrFileTitle$.struct = space$(260) + chr$(0) 'Receives file name w/o path
    ofn.nMaxFileTitle.struct = 260  'len of lpstrFileTitle$
    ofn.lpstrInitialDir$.struct = initialDir$ + chr$(0) 'initial directory; null for default directory
    ofn.lpstrTitle$.struct = windTitle$ + chr$(0)   'titlebar string for dialog
    ofn.flags.struct = _OFN_OVERWRITEPROMPT     'Warn if file exists already
    ofn.lpstrDefExt$.struct = defaultExt$ + chr$(0) 'default extension to add if none specified

    CallDLL #comdlg32, "GetSaveFileNameA", ofn As struct, ok As boolean

    'ofn.lpstrFile.struct returns a long integer memory address.
    'Use winstring() to retrieve the string of text
    'at that address, as filled by the function. If multiple files were selected,
    'this returns only the first
    if ok then uSaveFileDialog$=winstring(ofn.lpstrFile$.struct) else uSaveFileDialog$=""
end function

function uOpenFileDialog$(filter$, defaultExt$, initialDir$, initialFile$, windTitle$)
    'Opens dialog to find file name for saving a single file. Return full path name+file name+extension
    'filter$ specifies the type of file to allow. Sample:
    'filter$ = "Text files" + chr$(0) + "*.txt" + chr$(0) + _
    '       "All files" + chr$(0) + "*.*"
    'filter$ is pairs of strings, or null for no filter
    'defaultExt$ is the extension to add if the user does not specify one; do not include the period
    'initialDir$ is the directory in which to start
    'windTitle$ is the title of the dialog window
    OFN.EXPLORER = hexdec("80000")
    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 ptr, _
        lCustData as ulong, lpfnHook as long, lpTemplateName as long

    ofn.lStructSize.struct = len(ofn.struct)    'len of this struct
    ofn.lpstrFilter$.struct = filter$+ chr$(0) + chr$(0)   'filter for file types
    ofn.nFilterIndex.struct = 1     'Filter initially selected
    ofn.lpstrFile$.struct = initialFile$+chr$(0) + space$(1000) + chr$(0) 'File name used to initialize; receives full selected file path+name
    ofn.nMaxFile.struct = 1000   'length of lpstrFile$; buffer may actually be longer
    ofn.lpstrFileTitle$.struct = space$(260) + chr$(0) 'Receives file name w/o path
    ofn.nMaxFileTitle.struct = 260  'len of lpstrFileTitle$
    ofn.lpstrInitialDir$.struct = initialDir$ + chr$(0) 'initial directory; null for default directory
    ofn.lpstrTitle$.struct = windTitle$ + chr$(0)   'titlebar string for dialog
    ofn.flags.struct = _OFN_PATHMUSTEXIST or _OFN_FILEMUSTEXIST or OFN.EXPLORER
    ofn.lpstrDefExt$.struct = defaultExt$ + chr$(0) 'default extension to add if none specified

    CallDLL #comdlg32, "GetOpenFileNameA", ofn As struct, ok As boolean

    'ofn.lpstrFile.struct returns a long integer memory address.
    'Use winstring() to retrieve the string of text
    'at that address, as filled by the function. If multiple files were selected,
    'this returns only the first
    if ok then uOpenFileDialog$=winstring(ofn.lpstrFile$.struct) else uOpenFileDialog$=""
end function