FF FileOpen Function Errors

Started by Roger Garstang, December 27, 2005, 04:56:20 AM

Previous topic - Next topic

Roger Garstang

Not sure if you are on the PB Beta anymore Paul, but the FileOpen Dialog Wrappers were found to have some problems...both PB's which is old news and yours.  It amounted to being if a long name was selected then a short it would only overwrite part of the name like if 12345.mid was selected then 123.mid the returned string would be like "123.mid<nul>d".  I've fixed this, plus added some extras to enhance how everything works:


'-- RG_OpenFileDialog ---------------------------------------------
'
'   Creates and displays an Open common dialog box that lets the user
'   select one or many files.
'
'   hWnd:         Handle of parent window (if any)
'   Caption:      Caption to display as the Title of the dialog.
'   FileSpec:     The default filename to display. This parameter also returns
'                 the selected file(s) when the user closes the dialog.
'   InitialDir:   The initial directory that the dialog will show. If this
'                 value is null then the current directory is used.
'   Filter:       Description of files to show in the dialog. This is a
'                 delimited string that will produce the options available
'                 in the "Files of type" combobox.
'                 Example: "Source files (*.bas, *.inc)|*.bas;*.inc|All Files (*.*)|*.*"
'   DefExtension: The default file extension to apply to the filename if
'                 the user does not supply one.
'   Flags:        A combination of one or more values as described in the
'                 Win32 Help file under "OpenFileName".
'                 E.g.: %OFN_ALLOWMULTISELECT Or %OFN_FILEMUSTEXIST Or %OFN_NOCHANGEDIR
'   CenterFlag:   %TRUE to center dialog on the Desktop screen.
'
'
'   Returns:      If the user specifies a filename and clicks the OK button
'                 then the return value is non-zero. Zero if the dialog is
'                 canceled. The parameter FileSpec will return the name
'                 of the selected file. If multiple files are selected then
'                 FileSpec will be a $Nul (Chr$(0)) delimited list. The user
'                 can use the Parse$ function to extract the individual
'                 file names. Refer to the example in the FireFly Help file.
'
'------------------------------------------------------------------
Function RG_OpenFileDialog(ByVal hWnd As Long, _                ' parent window
                          ByVal Caption As String, _           ' caption
                          FileSpec As String, _                ' filename (input/output)
                          ByVal InitialDir As String, _        ' start directory
                          ByVal Filter As String, _            ' filename filter
                          ByVal DefExtension As String, _      ' default extension
                          ByVal Flags As Dword, _              ' flags
                          ByVal CenterFlag As Long) As Long    ' Center in desktop

 Local sFile         As String
 Local os            As OSVERSIONINFO
 Local Ofn           As OPENFILENAME5
 Local zFileTitle    As Asciiz * %MAX_PATH
 Local zInitialDir   As Asciiz * %MAX_PATH
 Local zTitle        As Asciiz * %MAX_PATH
 Local zDefExt       As Asciiz * 10
 Local lChrPos       As Long
 Local lRetVal       As Long

 Replace "|" With Chr$(0) In Filter

 If Len(InitialDir) = 0 Then InitialDir = CurDir$

 Filter                = Filter & $Nul
 zInitialDir           = InitialDir & $Nul

 If ((Flags = 0) And (CenterFlag)) Or ((Flags > 0) And (Flags And %OFN_EXPLORER)) Then ' Explorer Style
    lChrPos = InStr(FileSpec, $Nul)
    If lChrPos Then ' Multi-File List
       sFile= Left$(FileSpec, lChrPos - 1)
       If Right$(sFile, 1) <> "\" Then sFile= sFile + "\"
       sFile= sFile + Parse$(FileSpec, $Nul, 2)
    Else ' Single File
       sFile = FileSpec
    End If
 Else ' Old Style
    lChrPos = InStr(FileSpec, $Spc)
    If lChrPos Then ' Multi-File List
       sFile= Left$(FileSpec, lChrPos - 1)
       If Right$(sFile, 1) <> "\" Then sFile= sFile + "\"
       sFile= sFile + Parse$(FileSpec, $Spc, 2)
    Else ' Single File
       sFile = FileSpec
    End If
 End If
 
 sFile = sFile + $Nul + Space$(16383)  '<- At Least 63 to 126 Files keeping under 32K WinNT4 Limit
 
 zDefExt               = DefExtension & $Nul
 zTitle                = Caption & $Nul

 'Need to check what operating system we are using.
 os.dwOSVersionInfoSize = SizeOf(os)
 If GetVersionEx(os) Then
    If ((os.dwPlatformId = %VER_PLATFORM_WIN32_NT) And (os.dwMajorVersion > 4)) Then
       ofn.lStructSize       = Len(OPENFILENAME5) ' if Win2K or later, use full size of new structure
    Else
       ofn.lStructSize       = Len(OPENFILENAME)  ' else set size to old, smaller one's (76 bytes)
    End If
 End If

 ofn.hWndOwner         = hWnd
 ofn.lpstrFilter       = StrPtr(Filter)
 ofn.nFilterIndex      = 1
 ofn.lpstrFile         = StrPtr(sFile)
 ofn.nMaxFile          = Len(sFile)
 ofn.lpstrFileTitle    = VarPtr(zFileTitle)
 ofn.nMaxFileTitle     = SizeOf(zFileTitle)
 ofn.lpstrInitialDir   = VarPtr(zInitialDir)
 ofn.FlagsEx           = 0
 If Len(zTitle) Then
   ofn.lpstrTitle      = VarPtr(zTitle)
 End If

 'If needed, hook the Common dialog so it centers on the screen
 If CenterFlag Then
    If Flags = 0 Then
       Flags = %OFN_EXPLORER Or %OFN_ENABLESIZING
    End If
    Flags              = Flags Or %OFN_ENABLEHOOK
    ofn.lpfnHook       = CodePtr(RG_CenterOpenFileDialog)
 End If

 ofn.Flags             = Flags
 ofn.lpstrDefExt       = VarPtr(zDefExt)

 lRetVal = GetOpenFileName(ByVal VarPtr(ofn))

 If lRetVal Then ' Only Modify if File Selected
    lChrPos = InStr(sFile, $Nul + $Nul)
    If lChrPos Then
        sFile = Left$(sFile, lChrPos - 1)
    Else
        lChrPos = InStr(sFile, $Nul)
        If lChrPos Then
            sFile = Left$(sFile, lChrPos - 1)
        Else
            sFile = ""
        End If
    End If
    Filespec = sFile  ' return the filename(s)
 End If
 
 Function = lRetVal
End Function


' Help function for RG_OpenFileDialog that will center the dialog on the screen.
Function RG_CenterOpenFileDialog( ByVal hWnd As Long, ByVal wMsg As Long, _
                                 ByVal wParam As Long, ByVal lParam As Long ) As Long

 Local pNMHDR As NMHDR Ptr
 Local rc1    As Rect
 Local rc2    As Rect

 If wMsg = %WM_NOTIFY Then
    pNMHDR = lParam

    If @pNMHDR.Code = %CDN_INITDONE Then
        GetWindowRect GetDesktopWindow, rc1
        GetWindowRect GetParent(hWnd), rc2
        SetWindowPos  GetParent(hWnd), %HWND_TOPMOST, (rc1.nLeft + rc1.nRight - rc2.nRight + rc2.nLeft) / 2 , _
                        (rc1.nTop + rc1.nBottom - rc2.nBottom + rc2.nTop) / 2, 0, 0, %SWP_NOSIZE Or %SWP_NOACTIVATE

        Function = %TRUE: Exit Function
    End If
 End If
End Function

Roger Garstang

Also, I just noticed...now that I made it only return one file of a multi-file list for the default filename value, the 16383 number could probably be 32K-260 and get you around 126 file max with still keeping under the 32K NT4 limit.  As it is right now the comment line should read '<- At Least 63 to 64 Files.  I didn't update it after changing the way it loads the file list.

If you notice any other improvements, note them and I'll test them in my app, then maybe we can get a new code file so I don't have to add this as a function.  The Save Function may need improved too...I didn't look at it yet.

TechSupport

Thanks Roger, I have logged your solution so that I can add it to the new FireFly.

:)