Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

List of files in a directory

dzallar
Beginner
2,376 Views
I am writing a dialog based program and I would like to have the all of the files in a specified directory populate a list box. Is there a command to list the files in a directory?

Thanks,

David
0 Kudos
22 Replies
Steven_L_Intel1
Employee
2,179 Views
GETFILEINFOQQ

Steve
0 Kudos
dzallar
Beginner
2,179 Views
Thanks. I knew they was an easy way, I just couldn't remember.
0 Kudos
sumitm
Beginner
2,179 Views
Hi,
I was trying to do something similar and was following this message.
How do I select a directory instead of a file as I want to list *.ext files in a particular directory in a list box. The help file said :
To display a dialog box that allows the user to select a directory instead of a file, call the SHBrowseForFolder function.

If anyone can provide an example, that would be great.
Thanks



0 Kudos
Steven_L_Intel1
Employee
2,179 Views
There are easier ways to do this. GetOpenFileName allows the user to browse to a folder and see a list of files (you can filter by file type). The user can select one or more of the files (depending on options you specify.) CVF supplies a sample by the same name that demonstrates this.

Steve
0 Kudos
Steven_L_Intel1
Employee
2,179 Views
Also of possible interest - attached routine recursively does a copy-folder operation, showing use of APIs for traversing a folder tree.

Steve
0 Kudos
sumitm
Beginner
2,179 Views
Steve,
Thanks for your inputs but please bear with me for some dumb questions. I use the GetOPENFILENAME extensively to select and open files.

I found that the string FILE_INP contains the entire path name to the file like c: est1filename.ext
FRED%LPSTRFILE = LOC(FILE_INP)

For using getfileinfoqq I need just the string c: est1 and the I was thinking of concatenating *.ext to list all the files of ext extension as I browse through different folders.

I was looking for an easy way to get the string c: est1 instead of trying to trim to the last backslash from the File_INP string.

Sorry, I am not too familiar with windows API usage. I try to get one set of code working and repeat it almost blindly in cases where I try to get similar functionality. Not an ideal situation but just to get by.

Thanks for your help
0 Kudos
Steven_L_Intel1
Employee
2,179 Views
I suppose you could use the lpStrFileTitle field to get the file name without the path, and from that get the length of the file name. Then you'd know how many characters to strip off the full path. Not really much better than doing a trailing INDEX search for ''.

I don't know how to get just the directory.

Steve
0 Kudos
Intel_C_Intel
Employee
2,179 Views
SplitPathQQ does the job.

Sabalan.
0 Kudos
sumitm
Beginner
2,179 Views
Thank you very much!
Sumit
0 Kudos
gregscvf
Beginner
2,179 Views
Jugoslav's probably still on vacation, but you can use his XBrowse wrapper in XFTLITE to open a directory. See here
Greg
0 Kudos
sumitm
Beginner
2,179 Views
Thank you for your help.
I have implemented most of my requirements (please see attached picture), excepting that I cannot select more than 1 item from the list box.I used the whizzy example.
With the mouse and shift key, I want to select more than one item to transfer to the other list box.
Any help would be appreciated.
Thanks
0 Kudos
Jugoslav_Dujic
Valued Contributor II
2,179 Views
You've probably sorted it out yourself, but...

On list box's property sheet in resource editor, select "Multiple" from "Selection" combo box. Retrieval of selected values from the list with dflogm is a bit tricky; should be something like:
n = 1
DO WHILE (DlgGet(Dlg, IDC_LIST_RIGHT, indSelected, n))
   lret = DlgGet(Dlg, IDC_LIST_RIGHT, sFileName, indSelected)
   !Do something with sFileName, e.g:
   lret = DlgSet(Dlg, IDC_LIST_LEFT, sFileName, DLG_ADDSTRING)
   n = n + 1
END DO
Jugoslav
0 Kudos
sumitm
Beginner
2,179 Views
Dear Jugoslav ,

Thanks for your help. Selecting Multiple or Extended allowed me to select all the items in the list box with 1 shot of mouseclick and shiftbutton.

However, I have a more serious problem now.
I get a dialog initiation error every second time I want to click on the browse button which activates nothing but a get fileopen file.
The error is " File open Dialog Failure"
" The common dialog box procedure failed during initialization. This error often occurs when insufficient memory is available."

This error message was in my cmdlgerr.f90 file and corresponds to case CDERR_INITIALIZATION

I do not think I am short of memory. There is something else going on when I exit the dialog box and launch an opengl graphics with a command button. This is a modal dialog box. I am attaching the OK button code which closes the dialog box and launches the opengl graphics (the graphics runs fine). Is there something wrong in the sequence of statements or is there a way to free resources (I thought unusedqq did that).
Thanks for any help

SUBROUTINE INP3DDXF_OK(DLG, ID, CALLBACKTYPE)
  USE DFLIB
  USE DFLOGM
  use inputinfo
  IMPLICIT NONE
  INCLUDE 'RESOURCE.FD'
  TYPE(DIALOG)DLG
  LOGICAL(KIND=4)RET, LERR
  integer i,j,k,NT 
  logical retlog
  INTEGER(KIND=4)IRET, ID, CALLBACKTYPE, IERR
  CHARACTER(LEN=55) CTEMP, MSG0, MSG1
  Character(256) tempfl(100),temp ,TEXT

  CALL UNUSEDQQ(ID, CALLBACKTYPE)
  LERR = .FALSE.

!* GET THE NEW INFORMATION 
 	retlog =DlgGet (dlg, IDC_Num_pts,text)
    read (text,*,IOstat=IERR) Num_Pts_vert
	retlog =DlgGet (dlg, IDC_Num_X,text)
    read (text,*,IOstat=IERR) Num_X
	retlog =DlgGet (dlg, IDC_Ang,text)
    read (text,*,IOstat=IERR) Ang_btwn
	retlog =DlgGet (dlg, IDC_DXF_FINAL,text)
    read (text,*,IOstat=IERR) NT
   Do j=1,NT
    retlog = DlgGet( dlg, IDC_DXF_FINAL, temp, j )
  tempfl(j)= trim(drive)//trim(dir)//trim(temp)
   end do

  IF(IERR /= 0)THEN
!* ERROR CONDITION, PRINT MESSAGE, DESTRO BOX AND RECREATE
    MSG0 = 'ERROR READING INFORMATION IN EDIT FIELD'C
    MSG1 = 'ERROR READING INFORMATION'C
    IRET = MESSAGEBOXQQ(MSG0,MSG1,MB$ICONEXCLAMATION .OR. MB$OK)
     LERR = .TRUE.
  ENDIF
  
  IF(.NOT. LERR)THEN
	CALL DLGSETRETURN(DLG, IDOK)
    CALL DLGEXIT(DLG)
  ENDIF
call Show3DDXF(num_pts_vert,NUM_X,ANG_btwn,'Y',tempfl) !Launches OPENGL

  RETURN
END SUBROUTINE INP3DDXF_OK



0 Kudos
Jugoslav_Dujic
Valued Contributor II
2,179 Views
I doubt the bug has relationship with the way you clean up. CDERR_INITIALIZATION is so broad that it can be caused by a lot of things. The most suspicious thing is that some OPENFILENAME members retain uninitialized, or somehow corrupted by a previous call.

As a first step, try to clean up OPENFILENAME structure before starting to fill in its members. The simplest way is

CALL ZeroMemory(LOC(OFN), SIZEOF(OFN))

Other than that, it could be some subtle error, such as stack corruption, but it's hard to guess without seeing the complete code. As a comparative test, try calling XGetOpenFile from my XFTFile.f90 instead.
0 Kudos
sumitm
Beginner
2,179 Views
Dear Jugoslav,
The call to Zeromemory does not resolve the issue. I am posting the entire code for the coomon dialog box. At a glance can you see something wrong.
Thanks for your help
Sumit
!*************************************************************
SUBROUTINE INPFILEDXF(DLG, ID, CALLBACKTYPE)

  USE DFLIB
  USE INPUTINFO
  USE DFWINTY
  USE DFWIN
  use dflogm
  IMPLICIT NONE
  INCLUDE 'RESOURCE.FD'
  TYPE(DIALOG)DLG
  INTEGER(KIND=4)ID, CALLBACKTYPE

  TYPE (T_OPENFILENAME)FRED

  LOGICAL(KIND=4)RET
  INTEGER(KIND=4)IERROR,LENGTH
  Integer i
  !CHARACTER(LEN=26)FILTER(7)
  CHARACTER(LEN=26*7)ALLFILTERS
  CHARACTER(LEN=60)DLGTITLE
  LOGICAL(KIND=4)CHECKED
  logical retlog
  character(256) checkstring
  character(10) text
  CALL UNUSEDQQ(ID,CALLBACKTYPE)

 CALL ZeroMemory(LOC(FRED), SIZEOF(FRED))
  ALLFILTERS = 'DXF CAD FILES(*.dxf)' // char(0) // &
               '*.dxf' // char(0) // &
			   'All files(*.*)' // char(0) // &
			   '*.*' // char(0) // char(0)

  DLGTITLE = 'Choose DXF File'C


  FRED%LSTRUCTSIZE = (BIT_SIZE(FRED%LSTRUCTSIZE) +        &
                       BIT_SIZE(FRED%HWNDOWNER) +        &
                       BIT_SIZE(FRED%HINSTANCE) +        &
                       BIT_SIZE(FRED%LPSTRFILTER) +        &
                       BIT_SIZE(FRED%LPSTRCUSTOMFILTER) +        &
                       BIT_SIZE(FRED%NMAXCUSTFILTER) +        &
                       BIT_SIZE(FRED%NFILTERINDEX) +        &
                       BIT_SIZE(FRED%LPSTRFILE) +        &
                       BIT_SIZE(FRED%NMAXFILE) +        &
                       BIT_SIZE(FRED%LPSTRFILETITLE) +        &
                       BIT_SIZE(FRED%NMAXFILETITLE) +        &
                       BIT_SIZE(FRED%LPSTRINITIALDIR) +        &
                       BIT_SIZE(FRED%LPSTRTITLE) +        &
                       BIT_SIZE(FRED%FLAGS) +        &
                       BIT_SIZE(FRED%NFILEOFFSET) +        &
                       BIT_SIZE(FRED%NFILEEXTENSION) +        &
                       BIT_SIZE(FRED%LPSTRDEFEXT) +        &
                       BIT_SIZE(FRED%LCUSTDATA) +        &
                       BIT_SIZE(FRED%LPFNHOOK) +        &
                       BIT_SIZE(FRED%LPTEMPLATENAME))/8

  FRED%HWNDOWNER = NULL
  FRED%HINSTANCE = NULL
  FRED%LPSTRFILTER = LOC(ALLFILTERS)
  FRED%LPSTRCUSTOMFILTER = NULL
  FRED%NMAXCUSTFILTER = NULL
  FRED%NFILTERINDEX = 1
  FRED%LPSTRFILE = LOC(DXF_INP) 
  FRED%NMAXFILE = LEN(DXF_INP) 
  FRED%LPSTRFILETITLE = NULL 
  FRED%NMAXFILETITLE = NULL
  FRED%LPSTRINITIALDIR = NULL
  FRED%LPSTRTITLE = LOC(DLGTITLE)
  FRED%FLAGS = NULL 
  FRED%NFILEOFFSET = NULL
  FRED%NFILEEXTENSION = NULL
  FRED%LPSTRDEFEXT = NULL
  FRED%LCUSTDATA = NULL
  FRED%LPFNHOOK = NULL
  FRED%LPTEMPLATENAME = NULL 


  RET = GETOPENFILENAME(FRED)

  CALL COMDLGER(IERROR)

length = SPLITPATHQQ(dxf_INP, drive, dir, flname, ext)

checkstring= trim(drive)//trim(dir)//'*.dxf'
call SHOWPERMISSION(checkstring)

	retlog = DlgSet( dlg,IDC_DXF_LIST, num_of_files )
	Do i=1,num_of_files
	retlog = DlgSet( dlg,IDC_DXF_LIST, flnm(i), i )
	end do

  DXF_FILE_INP = .FALSE.

  IF(RET .AND. (IERROR == 0))THEN
	CALL READ_DXF
	DXF_FILE_INP = .TRUE.
   
 ENDIF
 write (text,'(I5)') Num_pts_Vert
 retlog =DlgSet (dlg, IDC_Num_pts,text)
 
  RETURN
END SUBROUTINE INPFILEDXF

!*****************************************************
 SUBROUTINE SHOWPERMISSION(files)
 USE DFLIB
 use inputinfo
 CHARACTER(256)    files

 INTEGER(4)       handle, length
 C
HARACTER(5)     permit
 TYPE (FILE$INFO) info
 

num_of_files=0
 length = len(files) !GETSTRQQ(files)
 handle = FILE$FIRST
 DO WHILE (.TRUE.)
   length = GETFILEINFOQQ(files, info, handle)
   IF ((handle .EQ. FILE$LAST) .OR. &
     (handle .EQ. FILE$ERROR)) THEN
   SELECT CASE (GETLASTERRORQQ( ))
     CASE (ERR$NOMEM)
       WRITE (*,*) 'Out of memory'
     CASE (ERR$NOENT)
       EXIT
     CASE DEFAULT
       WRITE (*,*) 'Invalid file or path name'
   END SELECT
   END IF
  
  num_of_files=num_of_files+1
 flnm(num_of_files)=info%name

 END DO
 RETURN
 END SUBROUTINE
0 Kudos
Jugoslav_Dujic
Valued Contributor II
2,179 Views
I think your problem is explained in MS KB Q222003 -- briefly, you must ensure that dxf_inp is either valid or empty and char(0) terminated in both cases.

I see few more oddities:

1) You're calculating lStructSize in quite an odd way (and I'm not certain about the result either -- why dividing by 8?). Isn't it simpler to simply use SIZEOF(FRED) instead?

2) (Just a stylistic note) -- isn't it better to use flags OFN_FILEMUSTEXIST + OFN_PATHMUSTEXIST (+ OFN_EXPLORER)?

3) You should test return value RET from GetOpenFileName earlier -- what if user presses Cancel?

It looks as if you're using GetOpenFileName to select a directory (actually, a .dxf file within the directory), then find all .dxf's within it (variable flname is not used anymore)? Isn't it nicer & simpler to use ShBrowseForFolder or XFTFile::XBrowse?

Jugoslav
0 Kudos
sumitm
Beginner
2,179 Views
Thanks again!
I probably do not understand all of it but the following code atleast got the error out. So I just added //Char(0) to DXF_INP and it seemed to be fine.
Also I tried replacing 8 with sizeof(FRED) and got the error message" The lStructSize member of a structure for the corresponding common dialog box is invalid.
It is not causing me any problems right now but I would like to know what is the correct solution.
Thanks


SUBROUTINE INPFILEDXF(DLG, ID, CALLBACKTYPE)

  USE DFLIB
  USE INPUTINFO
  USE DFWINTY
  USE DFWIN
  use dflogm
  IMPLICIT NONE
  INCLUDE 'RESOURCE.FD'
  TYPE(DIALOG)DLG
  INTEGER(KIND=4)ID, CALLBACKTYPE

  TYPE (T_OPENFILENAME)FRED
  LOGICAL(KIND=4)RET
  INTEGER(KIND=4)IERROR,LENGTH
  Integer i
  CHARACTER(LEN=26*7)ALLFILTERS
  CHARACTER(LEN=60)DLGTITLE
  LOGICAL(KIND=4)CHECKED
  logical retlog
  character(256) checkstring
  character(10) text
  CALL UNUSEDQQ(ID,CALLBACKTYPE)
 CALL ZeroMemory(LOC(FRED), SIZEOF(FRED))

  ALLFILTERS = 'DXF CAD FILES(*.dxf)' // char(0) // &
               '*.dxf' // char(0) // &
			   'All files(*.*)' // char(0) // &
			   '*.*' // char(0) // char(0)

  DLGTITLE = 'Choose DXF File'C


  FRED%LSTRUCTSIZE = (BIT_SIZE(FRED%LSTRUCTSIZE) +        &
                       BIT_SIZE(FRED%HWNDOWNER) +        &
                       BIT_SIZE(FRED%HINSTANCE) +        &
                       BIT_SIZE(FRED%LPSTRFILTER) +        &
                       BIT_SIZE(FRED%LPSTRCUSTOMFILTER) +        &
                       BIT_SIZE(FRED%NMAXCUSTFILTER) +        &
                       BIT_SIZE(FRED%NFILTERINDEX) +        &
                       BIT_SIZE(FRED%LPSTRFILE) +        &
                       BIT_SIZE(FRED%NMAXFILE) +        &
                       BIT_SIZE(FRED%LPSTRFILETITLE) +        &
                       BIT_SIZE(FRED%NMAXFILETITLE) +        &
                       BIT_SIZE(FRED%LPSTRINITIALDIR) +        &
                       BIT_SIZE(FRED%LPSTRTITLE) +        &
                       BIT_SIZE(FRED%FLAGS) +        &
                       BIT_SIZE(FRED%NFILEOFFSET) +        &
                       BIT_SIZE(FRED%NFILEEXTENSION) +        &
                       BIT_SIZE(FRED%LPSTRDEFEXT) +        &
                       BIT_SIZE(FRED%LCUSTDATA) +        &
                       BIT_SIZE(FRED%LPFNHOOK) +        &
                       BIT_SIZE(FRED%LPTEMPLATENAME))/8

 DXF_INP=trim(DXF_INP)//char(0)

  FRED%HWNDOWNER = NULL
  FRED%HINSTANCE = NULL
  FRED%LPSTRFILTER = LOC(ALLFILTERS)
  FRED%LPSTRCUSTOMFILTER = NULL
  FRED%NMAXCUSTFILTER = NULL
  FRED%NFILTERINDEX = 1
  FRED%LPSTRFILE = LOC(DXF_INP) 
  FRED%NMAXFILE = LEN(DXF_INP) 
  FRED%LPSTRFILETITLE = NULL 
  FRED%NMAXFILETITLE = NULL
  FRED%LPSTRINITIALDIR = NULL
  FRED%LPSTRTITLE = LOC(DLGTITLE)
  FRED%FLAGS = OFN_FILEMUSTEXIST + OFN_PATHMUSTEXIST + OFN_EXPLORER   !NULL
  FRED%NFILEOFFSET = NULL
  FRED%NFILEEXTENSION = NULL
  FRED%LPSTRDEFEXT = NULL
  FRED%LCUSTDATA = NULL
  FRED%LPFNHOOK = NULL
  FRED%LPTEMPLATENAME = NULL 

  RET = GETOPENFILENAME(FRED)

  CALL COMDLGER(IERROR)
   DXF_FILE_INP = .FALSE.

   IF(RET .AND. (IERROR == 0))THEN
	CALL READ_DXF
	write (text,'(I5)') Num_pts_Vert
    retlog =DlgSet (dlg, IDC_Num_pts,text)
	DXF_FILE_INP = .TRUE.
 ENDIF

length = SPLITPATHQQ(dxf_INP, drive, dir, flname, ext)

checkstring= trim(drive)//trim(dir)//'*.dxf'
call SHOWPERMISSION(checkstring)

	retlog = DlgSet( dlg,IDC_DXF_LIST, num_of_files )
	Do i=1,num_of_files
	retlog = DlgSet( dlg,IDC
_DXF_LIST, flnm(i), i )
	end do 
  RETURN
END SUBROUTINE INPFILEDXF
0 Kudos
Jugoslav_Dujic
Valued Contributor II
2,179 Views
I meant simply
FRED%LSTRUCTSIZE = SIZEOF(FRED)
. That should be 76 (and it works for me). (Your approach actually works as well, I didn't realize that 8 stands per "8 bits in a byte").

"Size" members within some API structures are introduced by Microsoft for reasons of future compatibility. That is, they say, "maybe we'll enhance the functionality and the structure one day; the routine will check the size member and know whether it's an old application (written before new changes) or a new one". That already was the case with OPENFILENAME -- in Windows 2000, they added three new members. Compare versions from oldish CVF docs and MSDN. So, the definition from CVF DFWIN is outdated (but still works). Now, if you write:
FRED%LSTRUCTSIZE = SIZEOF(FRED)+12
, to be compatible with new version, with a little luck you'll get the "places bar" on dialog's left side (History, Desktop, My Documents, etc.) (Don't leave it so -- it may corrupt memory).

Jugoslav
0 Kudos
Steven_L_Intel1
Employee
2,179 Views
You don't want to use a size different from the declared structure size - if you do, Windows will merrily write over your other variables that happen to follow the structure.

We updated DFWIN in 2001 - has MS changed this structure since then?

Steve
0 Kudos
Jugoslav_Dujic
Valued Contributor II
2,031 Views
Re using bigger size than declared: you're certainly right, I meant it only as an experiment.

OPENFILENAME was updated with Windows 2000 (no big deal, pvReserved, dwReserved and FlagsEx.) The new three fields were protected using #if (_WIN32_WINNT >= 0x0500), and only the latter (and lStructSize) matters if lpfnHook is non-null.

Jugoslav

0 Kudos
Reply