[fpc-pascal] Getting multiple files from GetOpenFileNameA

James Richters james at productionautomation.net
Fri May 24 02:17:03 CEST 2019


Thank you very much for explaining all this!!   I really don’t know what I would do without the helpful people here!

 

I didn’t know there was something like IncludeTrailingPathDelimiter, wow that sure is useful!   I have a LOT of places I need to make sure I stick in the trailing \ and this function will really help clean up a lot of that mess!

 

I did not realize Open_File.lpstrFile was working like a pointer to Ret…  knowing that makes things make more sense!  I thought setting Open_File.lpstrFile:=Ret was just a way to initialize it, not that it was actually a pointer to Ret.

Should I just never use Open_File.lpstrFile except to set it to Ret (which I will probably rename to make it more clear that THAT is the real location of all my file name data)

So in other words do 

 

         Repeat

            String_List.add(StrPas(Ret[Position_of_Filename]));

            inc(Position_of_Filename,length(String_List[String_List.Count-1])+1);

         Until Ret[Position_of_Filename]=#0;

 

The reason I made those variables global is because I set the initial ones in the main program loop… no real reason for doing that other than I thought it might help my crash issues if I wasn’t constantly creating and destroying those variables.  It does seem like a good idea to initialize every time so I’ll move all that into the function.

 

I’ve incorporated the recommended changes and still have a few problems.

 

Here is my updated sample program.  I renamed Ret to Open_File_Buffer and I am only using that variable after Open_File.lpstrFile:=Open_File_Buffer;  my problems still show up only if I try to set a default file with Open_File_Buffer:=Pchar(Target_File+#0+#0);   I’m not sure if I am doing this right.  It seems to put it in there but then if I select more than one file, it returns a False, and I also get crashes occasionally as well.  Open_File.lpstrInitialDir seems to work better but it only works if I do not try to set a default file name.  sometimes want a default file name, sometimes I do not, but I always want to set the initial directory, so I would like to learn the proper way to achieve both of these.

 

Thank you again for the help and the great suggestions!   It’s very much appreciated.

 

James

 

 

{$mode objfpc}{$H+}

//   https://docs.microsoft.com/en-us/windows/desktop/api/commdlg/nf-commdlg-getopenfilenamea

//   https://docs.microsoft.com/en-us/windows/desktop/api/commdlg/ns-commdlg-tagofna

Uses

  sysutils,Windows,Commdlg,Classes,CRT;

Var

File_Num           : Word;

Target_File        : AnsiString;

File_Stringlist    : tstringList;

{=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=}

Procedure Display_File_StringList(Var Display_String_List:tStringList);

Var

  SL_Loop : Word;

Begin

   If Display_String_List.Count=0 then

      Begin

         Textcolor(12);

         Writeln('0 Files Selected')

      End

   Else

   If Display_String_List.Count=1 then

      Begin

         TextColor(10);

         Writeln(Display_String_List[0]);

         Textcolor(14);

         Writeln('1 Files Selected');

      End

   Else

      Begin

         TextColor(13);

         Writeln('Path for all files: ',Display_String_List[0]);

         TextColor(10);

         For SL_Loop:= 1 to Display_String_List.Count-1 Do

            Writeln('File #',SL_Loop,': ',Display_String_List[SL_Loop]);

         Textcolor(14);

         Writeln(Display_String_List.Count-1,' Files Selected');

      End;

End;

{=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=}

Function Get_Files_Into_Stringlist(Var String_List:tStringList):Boolean;

Var

   Open_File_Result      : Boolean;

   Position_of_Filename  : Word;

   Open_File             : TOpenFileNameA;

   Open_File_Buffer      : array[0..100000] of char;

Begin

   String_List.Clear;

   fillchar(Open_File, sizeof(Open_File), 0);

   fillchar(Open_File_Buffer, sizeof(Open_File_Buffer), 0);

   Open_File.lStructSize:=sizeof(Open_File);

   Open_File.lpstrFile:=Open_File_Buffer;

   Open_File.nMaxFile:=SizeOf(Open_File_Buffer);

   Open_File.hwndOwner:=0;

   Open_File.Flags := OFN_EXPLORER or OFN_FILEMUSTEXIST or OFN_ALLOWMULTISELECT;

   Open_File.lpstrDefExt:='.txt';

   Open_File.lpstrTitle:='My Program - Open File';

   Open_File.lpstrFilter:='All Files (*.*)'+#0+'*.*'+#0;

   If Target_File<>'' then

       Begin

          // The line below makes GetOpenFileNameA return with False if I select more than one file.

          // It also causes the following occasionally:

          // An unhandled exception occurred at $00401B5A:

          // EAccessViolation: Access violation

          // $00401B5A  GET_FILES_INTO_STRINGLIST,  line 66 of i:/programming/gcode/test/getfilenamea to stringlist.pas

          // $00401E60  main,  line 99 of i:/programming/gcode/test/getfilenamea to stringlist.pas

          Open_File_Buffer:=Pchar(Target_File+#0+#0);

         //If the line below is un commmented, it selects multiple files from the correct directory, but only if the line above is commented out

          //Open_File.lpstrInitialDir:=Pchar(ExtractFilePath(Paramstr(1))+#0+#0);

       End;

   Open_File_Result:=GetOpenFileNameA(@Open_File);

   If Open_File_Result then

      Begin

         Position_of_Filename:=0;

         Repeat

            String_List.add(StrPas(@Open_File_Buffer[Position_of_Filename]));

            inc(Position_of_Filename,length(String_List[String_List.Count-1])+1);

         Until Open_File_Buffer[Position_of_Filename]=#0;

      End;

   Writeln(Open_File_Result);

   Get_Files_Into_Stringlist:=Open_File_Result;

End;

{=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=}

Procedure Process_File(Some_File: AnsiString);

Begin

   TextColor(11);

   Writeln('Processing File: ',Some_File);

End;

{=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=}

Begin {Main Program}

   File_Stringlist:=TStringlist.Create;

   If paramstr(1)<>'' then

      Begin

         Target_File:=paramstr(1);

         Process_File(Target_File);

      End

   else

      Target_File:='';

   Repeat

      Get_Files_Into_Stringlist(File_Stringlist);

      Display_File_StringList(File_Stringlist);

      If (File_Stringlist.Count=1) and FileExists(File_Stringlist[0]) Then

         Begin

            Target_File:=File_Stringlist[0];

            Process_File(Target_File);

         End

      Else

      If (File_Stringlist.Count>1) Then

         Begin

            Target_File:=IncludeTrailingPathDelimiter(File_Stringlist[0]);

            for file_num:=1 to File_Stringlist.count-1 do

               Process_File(Target_File+File_Stringlist[File_Num]);

         End;

   Until File_Stringlist.count=0;

   File_Stringlist.Free;

end.

{=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=}

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20190523/8e8fb19b/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Getfilenamea to Stringlist.pas
Type: application/octet-stream
Size: 4534 bytes
Desc: not available
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20190523/8e8fb19b/attachment.obj>


More information about the fpc-pascal mailing list