Announcement

Collapse
No announcement yet.

%OFN_ALLOWMULTISELECT with DISPLAY OPENFILE

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • %OFN_ALLOWMULTISELECT with DISPLAY OPENFILE

    I am using the following line of code to open a mutil-select file dialog.

    Code:
       title = "Select Files for Delete"
       flags = %ofn_allowmultiselect Or %ofn_filemustexist Or %ofn_nodereferencelinks Or %ofn_pathmustexist Or %ofn_shareaware
       filter = Chr$("All Files (*.*)", 0, "*.*", 0, "Document Files", 0, "*.txt;*.doc;*.wpd;*.log", 0)
    
       Display Openfile hDlg, 60, 50, title, $Nul, filter, $Nul, $Nul, flags To result
    The problem is when I select a folder with a large number of files and select "all" of the files I get strange results. Sometimes just some gibberish file names at the end part of the list, other times just a single high-ASCII character along with the null terminator.

    Any ideas of how to stop this? Is there are buffer limit on the number of bytes that can be returned by this?
    Scott Slater
    Summit Computer Networks, Inc.
    www.summitcn.com

  • #2
    Insufficient code shown....
    %OFN_ALLOWMULTISELECT
    Multiple selections are allowed. If the user chooses multiple items, the return value consists of multiple file names which are null-terminated
    ... because you do not show the code you are using to parse out the multiple file names from 'result'
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      Any ideas of how to stop this? Is there are buffer limit on the number of bytes that can be returned by this?
      How are you checking the contents of the buffer and reading it out? Post some code please. As to limits PB will have to let us know, since this wraps GetOpenFilename and may have an internal limit. Have you tried the pure API route? Might also be over-running the standard, preset edit box capacity. I.E. you must be trying to select even the kitchen sink!

      Keep in mind that the return string terminator, for a string with null character delimiters is 2 consecutive null characters, CHR$(0) per MS.

      Try this code:

      Code:
      #COMPILE EXE
      #DIM ALL
      
      FUNCTION PBMAIN () AS LONG
         LOCAL title,filter,result,msg AS STRING , flags,i AS LONG
         title = "Select Files for Delete"
         flags = %OFN_ALLOWMULTISELECT OR %OFN_FILEMUSTEXIST OR %OFN_NODEREFERENCELINKS OR %OFN_PATHMUSTEXIST OR %OFN_SHAREAWARE
         filter = CHR$("All Files (*.*)", 0, "*.*", 0, "Document Files", 0, "*.txt;*.doc;*.wpd;*.log", 0)
      
         DISPLAY OPENFILE 0, 60, 50, title, $NUL, filter, $NUL, $NUL, flags TO result
      
         msg$ = msg$+HEX$(PEEK(STRPTR(result)+LEN(result)))+$SPC
         msg$ = msg$+HEX$(PEEK(STRPTR(result)+LEN(result)+1))+$SPC
         msg$ = msg$ + $CRLF
         FOR i& = 1 TO PARSECOUNT (result,CHR$(0))
             msg$ = msg$ + PARSE$(result,CHR$(0),i&)+$CRLF
         NEXT i&
      
         ? msg$
      
      END FUNCTION
      Rick Angell

      Comment


      • #4
        Also there are MS limits, for some OS's:
        Note, when selecting multiple files, the total character limit for the file names depends on the operating system and the version of the function.
        • Windows 95/98/Me: (only ANSI is supported) no restriction
        • Microsoft Windows NT4 and earlier: 32k limit
        • Windows 2000/XP: (ANSI) 32k limit, (Unicode) no restriction
        Here the link to the topic:
        http://msdn.microsoft.com/en-us/library/ms646927.aspx
        Rick Angell

        Comment


        • #5
          OS: Vista Home Premium 64-bit and XP Professional, both with same results.

          Here is the code used to parse out the file names, but the gibberish is in "result" before any parsing takes place. I found this by simply using a statement like "Replace $NUL With " " in result" and then printing it.

          Code:
                result = RTrim$(result, Chr$(0))  ' get rid of trailing $Nul
                iCount = ParseCount(result, Chr$(0))
                For idx = 2 To iCount            ' 1 is the directory, so we start with 2
                   file = Parse$(result, Chr$(0), idx)    ' get next file name
                   Incr gListRecs
                   ReDim Preserve gList(gListRecs) As Global String
                   gList(gListRecs-1) = file
                Next idx
          one directory contains 65 files, I can see 41 of them in tact, then the rest are just garbage characters.

          another directory contains 468 files, I only get back a 2-character string of Chr$(210,0).

          I am getting this by opening the open file dialog, Ctrl-A to select all, and then clicking OK.

          As I stated earlier, the gibberish is in the result before any parsing is done.
          Scott Slater
          Summit Computer Networks, Inc.
          www.summitcn.com

          Comment


          • #6
            This code works for this purpose:
            Code:
            DISPLAY OPENFILE 0, 10, 10, "", "C:\",  CHR$("BASIC", 0, "*.BAS;*.INC;*.BI;*.FRM;*.VBP;*.CLS", 0), _
                           "", "",%OFN_ALLOWMULTISELECT OR %OFN_FILEMUSTEXIST OR %OFN_NOCHANGEDIR _
                           OR %OFN_SHAREAWARE OR %OFN_NONETWORKBUTTON TO gotfiles
                           zz=TALLY(gotfiles,CHR$(0))    'The first is the directory so there is one less file than zz
                           IF zz=0 THEN EXIT IF            'This snippet is from an IF block
                           REDIM filesafe(0 TO zz-1)
                           PARSE gotfiles, filesafe(),CHR$(0)    'store the files in an array
            Last edited by Rodney Hicks; 7 Oct 2008, 09:39 PM. Reason: add comment, remove unnecessary line
            Rod
            I want not 'not', not Knot, not Knott, not Nott, not knot, not naught, not nought, but aught.

            Comment


            • #7
              Originally posted by Rodney Hicks View Post
              This code works for this purpose:
              Code:
              DISPLAY OPENFILE 0, 10, 10, "", "C:\",  CHR$("BASIC", 0,...
              I still get the garbage characters. I'm not sure what the problem is, but I do know that it has nothing to do with the parsing of the file names. The garbage is there right after the call to DISPLAY OPENFILE.

              I have tried this on local drives, and remote drives both give the same result. If I select more than about 40-some files or the string gets around 600+ bytes, then I have a problem.

              I have also tried using direct API calls with the same result as well.

              I am going to test this on my laptop later because both of the machines that I have currently been testing on have the Novell Client installed on them. I really doubt that it has anything to do with it, but I still need to rule it out.
              Scott Slater
              Summit Computer Networks, Inc.
              www.summitcn.com

              Comment


              • #8
                Here's a complete working piece of code that replicates the problem.

                Code:
                #Compile Exe
                #Dim All
                 
                %ListBox = 100
                %AddBtn  = 120
                %ClrBtn  = 130
                %ExitBtn = 150
                $Title   = "Test DISPLAY OPENFILE"
                 
                CallBack Function DlgProc
                 
                   Local files As String
                   Local index As Dword
                 
                   Select Case Long Cb.Msg
                      Case %wm_command
                         Select Case Long Cb.Ctl
                            Case %AddBtn
                               Display Openfile Cb.Hndl,,, "Add Multiple Files", $Nul, _
                                  Chr$("All Files (*.*)", 0, "*.*", 0, "Document Files", _
                                  0, "*.txt;*.doc;*.wpd;*.log", 0), $Nul, $Nul, _
                                  %ofn_allowmultiselect Or %ofn_filemustexist Or _
                                  %ofn_nodereferencelinks Or %ofn_pathmustexist Or _
                                  %ofn_shareaware To files
                               files = RTrim$(files, $Nul)
                               If ParseCount(files, $Nul) > 1 Then
                                  For index = 2 To ParseCount(files, $Nul)
                                     ListBox Add Cb.Hndl, %ListBox, Parse$(files, $Nul, index)
                                  Next index
                               Else
                                  ListBox Add Cb.Hndl, %ListBox, files
                               End If
                               ListBox Get Count Cb.Hndl, %ListBox To index
                               Dialog Set Text Cb.Hndl, $Title & ": Count = " & Format$(index, "0,")
                            Case %ClrBtn
                               ListBox Reset Cb.Hndl, %ListBox
                               Dialog Set Text Cb.Hndl, $Title
                            Case %ExitBtn
                               Dialog End Cb.Hndl
                         End Select
                   End Select
                            
                End Function
                 
                Function PBMain () As Long
                   
                   Local hDlg As Dword
                 
                   Dialog New 0, $Title,,, 200, 140 To hDlg
                   
                   Control Add ListBox, hDlg, %ListBox,, 10, 10, 180, 120, %lbs_notify _
                      Or %ws_tabstop Or %ws_vscroll Or %lbs_disablenoscroll, %ws_ex_clientedge
                      
                   Control Add Button, hDlg, %AddBtn, "Add Files", 10, 120, 50, 15
                   Control Add Button, hDlg, %ClrBtn, "Clear List", 75, 120, 50, 15
                   Control Add Button, hDlg, %ExitBtn, "Exit", 140, 120, 50, 15
                   
                   Dialog Show Modal hDlg, Call DlgProc
                   
                End Function
                Scott Slater
                Summit Computer Networks, Inc.
                www.summitcn.com

                Comment


                • #9
                  Well, how about that.

                  Your take on the situation seems accurate. I hope support can solve this, because I can't see any way of fixing this since it occurs between the selection and putting the selection into the variable.
                  I originally thought that it had something to do with this line:
                  Code:
                  files = RTrim$(files, $Nul)
                  but it does the same with that commented out.
                  Rod
                  I want not 'not', not Knot, not Knott, not Nott, not knot, not naught, not nought, but aught.

                  Comment


                  • #10
                    The files = RTrim$(files, $Nul) line simply removes the trailing NUL Character so that ParseCount will return an accurate number of fields.

                    I think it is something with the Windows API, because the direct API call also yields the same results. I am simply trying to figure out what exactly is causing the problem, so that maybe I can place a restriction on the number of bytes that I accept from the return something like:

                    Code:
                       If Len(result) > 512 Then
                          result = Left$(result, 512)                         ' Truncate it!
                          idx = InStr(-1, result, Chr$(0))                    ' get the position of the last NULL CHAR
                          result = Left$(result, idx-1)                       ' return everything leading up to it
                       End If
                    Anyone else have any ideas?
                    Scott Slater
                    Summit Computer Networks, Inc.
                    www.summitcn.com

                    Comment


                    • #11
                      "Assuming" the DISPLAY OPENFILE function is based in the Windows "GetOpenFileName()" WinAPI function, the compiler would be generating an OPENFILENAME structure to pass to that call.....
                      Code:
                      typedef struct tagOFN { 
                        DWORD         lStructSize; 
                        HWND          hwndOwner; 
                        HINSTANCE     hInstance; 
                        LPCTSTR       lpstrFilter; 
                        LPTSTR        lpstrCustomFilter; 
                        DWORD         nMaxCustFilter; 
                        DWORD         nFilterIndex; 
                        LPTSTR        lpstrFile; 
                      [B][COLOR="Red"]  DWORD         nMaxFile; [/COLOR][/B]
                        LPTSTR        lpstrFileTitle;
                      ... the question is, "to what value does the compiler set the nMaxFile member? This will limit the number of characters returned by the GetOpenFileName call.

                      That still would not explain the "garbage" characters, but it is a place to start looking.... "ASSUMING" 'DISPLAY OPENFILE' is implemented as suggested.


                      ADDED:
                      The symptoms you describe are almost the "classic" symptoms of "buffer overflow." The equally common symptom would be a general protection fault. (0xC0000005, invalid address).




                      MCM
                      Last edited by Michael Mattias; 8 Oct 2008, 09:32 AM.
                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #12
                        Since this particular issue doesn't seem to find an error, at least I haven't got it to report an error, I think that it should be sent in to support for clarification. If there is a limit due to the operating system it should be in the documentation I would think. There is no way to stop the user from selecting more than the 40 or so files that it will accept within the DISPLAY OPENFILE syntax. I will send it in later today after a few more tests. I still want to try a few experiments.
                        Rod
                        I want not 'not', not Knot, not Knott, not Nott, not knot, not naught, not nought, but aught.

                        Comment


                        • #13
                          Seems to be a problem with the Windows API. I just did a compile with some other compilers and found the same issue.

                          I have yet to test this on any other versions of Windows other than Vista-64, and XP Pro. I will try it on 2000 later and see if the problem is there as well.
                          Scott Slater
                          Summit Computer Networks, Inc.
                          www.summitcn.com

                          Comment


                          • #14
                            Looks like MCM might be pretty close on this one.. sigh!
                            Modifying Scott's demo code to use a call to OpenFileDialog instead of the new Display Openfile seems to fix the problem..
                            Code:
                                        Case %AddBtn
                             
                                           OpenFileDialog( 0, "Add Multiple Files", files, $Nul, _
                                              "All Files (*.*)|*.*|Document Files|*.txt;*.doc;*.wpd;*.log", $Nul, _
                                              %ofn_allowmultiselect Or %ofn_filemustexist Or _
                                              %ofn_nodereferencelinks Or %ofn_pathmustexist Or _
                                              %ofn_shareaware Or %ofn_explorer)
                             
                             'NB. OpenFileDialog is wrapper for GetOpenFilename(ofn) - see ComDlg32.inc
                             [COLOR=red]'ofn.nMaxFile         = LEN(sFileSpec)     ' ~  %OFN_FILEBUFFERSIZE = 8192[/COLOR]
                             'reducing size of %OFN_FILEBUFFERSIZE in ComDlg32.inc (eg = 1000) causes similar results
                             'to DISPLAY OPENFILE in PBWin90 when more than 60 or so files (?LEN(files)?) are opened.
                             
                             '               Display Openfile Cb.Hndl,,, "Add Multiple Files", $Nul, _
                             '                  Chr$("All Files (*.*)", 0, "*.*", 0, "Document Files", _
                             '                  0, "*.txt;*.doc;*.wpd;*.log", 0), $Nul, $Nul, _
                             '                  %ofn_allowmultiselect Or %ofn_filemustexist Or _
                             '                  %ofn_nodereferencelinks Or %ofn_pathmustexist Or _
                             '                  %ofn_shareaware To files
                             
                                           files = RTrim$(files, $Nul)
                            (You'll also need to add "#INCLUDE "COMDLG32.INC")
                            Last edited by Dave Biggs; 9 Oct 2008, 12:41 AM.
                            Rgds, Dave

                            Comment


                            • #15
                              There is no way to stop the user from selecting more than the 40 or so files that it will accept within the DISPLAY OPENFILE syntax.
                              But you can do this eschewing DISPLAY OPENFILE in favor of GetOpenFileName() with a hook procedure.

                              DEMO: Explorer-Style hook Procedures for OpenFileDialog and SaveFileDialog 3-31-07
                              Michael Mattias
                              Tal Systems (retired)
                              Port Washington WI USA
                              [email protected]
                              http://www.talsystems.com

                              Comment


                              • #16
                                For that matter, using a hook procedure would allow you to return a string array of all files selected.

                                For extra credit, do this WITHOUT using any GLOBAL variables. (Hint: 'lcustdata')
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #17
                                  But you can do this eschewing DISPLAY OPENFILE in favor of GetOpenFileName() with a hook procedure.
                                  I was thinking that the documentation should reveal the limits, and sent it in, and I see that there is something to be adjusted at the next opportunity, according to Bob Zale.(PowerBase forum)
                                  Rod
                                  I want not 'not', not Knot, not Knott, not Nott, not knot, not naught, not nought, but aught.

                                  Comment


                                  • #18
                                    Hmm, I see that Powerbase entry.

                                    I may have another PowerBASE entry for PB/CC 5.0. I sent in an example of bug for CC 4.03 and did not see a fix in the "history" for CC 5, but I never installed 4.04 and the history supplied with CC 5.0 only includes "since 4.04"

                                    But now that I have installed CC 5 I guess I should try it.

                                    (Tried it. Still broke. Sent in).
                                    Last edited by Michael Mattias; 9 Oct 2008, 09:28 AM.
                                    Michael Mattias
                                    Tal Systems (retired)
                                    Port Washington WI USA
                                    [email protected]
                                    http://www.talsystems.com

                                    Comment

                                    Working...
                                    X