- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In an application I am opening different files residing in different folders. To perform the assignment, I try to force Windows to display the correct folder. in the way that if I want to open an .INP file, the FileOpen dialog should list the content of the INP directory aso. However, the FileOpen dialog box lists the file content of the most recent directory. In the example below, the files in the "InputDir" should be listed and this happens. But next, when I will open a PLT file (not shown here), the dialog box list the files in the InputDir, and vice versa...
What could be done to fix the problem ?
! get open file dialog box
Ofn%Flags = null
szfilter = &
"TVC input files(*.INP)"C//"*.INP"C// &
"Simulation input files(*.SIN)"C//"*.SIN"C//""C
Ofn%LPSTRINITIALDIR = loc(trim(InputDir)//Char(0))
iret = CHDIR(InputDir)
iret = InitializeOpen()
bret = GETOPENFILENAME(Ofn)
bret=.true.
! check to see if the OK button has been pressed
if(bret == 0) then ! check for error
call COMDLGER(ierror)
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I consider the line
Ofn%LPSTRINITIALDIR = loc(trim(InputDir)//Char(0))
to be especially problematic. You are taking the address of an expression and storing it in the OFN structure. By the time the very next statement executes, this address will already be invalid. I would declare a helper variable
CHARACTER(LEN(InputDir)+1), TARGET :: InputDir1
then you could copy the data to there and append the trailing NUL that C requires
InputDir1 = TRIM(InputDir) // Char(0)
Ofn%LPSTRINITIALDIR = loc(InputDir1)
let us know if this helps.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You have set szfilter to the file selection mask, but I do not see where you used it in the file open dialog to limit the file names returned.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
RepeatOffender's reply is probably the key to your problem. Here is a more complete code sample which works as expected to set the path for file reading/writing:
LOGICAL FUNCTION DlgFileIO (rw_mode, hwndParent, filter, fullpath, ncfn, extn, ncextn, path) IMPLICIT NONE CHARACTER(LEN=1), INTENT(IN) :: rw_mode INTEGER(HANDLE), INTENT(IN) :: hwndParent CHARACTER(LEN=*), INTENT(IN) :: filter CHARACTER(LEN=*), INTENT(IN) :: extn CHARACTER(LEN=*), INTENT(INOUT) :: fullpath INTEGER, INTENT(INOUT) :: ncfn, ncextn CHARACTER(LEN=*), INTENT(INOUT) :: path INTEGER :: rval TYPE(T_OPENFILENAME) :: ofn ofn%lStructSize = SIZEOF(ofn) ofn%hwndOwner = hwndParent ofn%hInstance = ghInstance ofn%lpstrFilter = LOC(filter) ofn%nFilterIndex = 0 ! force use of 1st filter entry, ofn%lpstrCustomFilter = 0 ! restricts to single file type ofn%lpstrFile = LOC(fullpath) ofn%nMaxFile = LEN(fullpath) ofn%lpstrInitialDir = LOC(path) ofn%lpstrDefExt = LOC(extn) ofn%nMaxCustFilter = 0 ofn%nMaxFileTitle = 0 ofn%lpstrTitle = loc(""C) ofn%lpfnHook = NULL ofn%lpTemplateName = NULL IF (rw_mode == 'R') THEN ofn%Flags = MOR(OFN_HIDEREADONLY, OFN_PATHMUSTEXIST, & OFN_FILEMUSTEXIST, OFN_SHAREAWARE ) DlgFileIO = GetOpenFileName (ofn) ELSE ofn%Flags = MOR(OFN_HIDEREADONLY, OFN_CREATEPROMPT, & OFN_PATHMUSTEXIST, OFN_OVERWRITEPROMPT) IF (dataprime) ofn%Flags = IOR(ofn%Flags, OFN_NONETWORKBUTTON) DlgFileIO = GetSaveFileName (ofn) END IF ncfn = ofn%nFileOffset + 1 ncextn = ofn%nFileExtension + 1 END FUNCTION DlgFileIO
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
RepeatOffender.: I tested your proposal but it didn't change anything. Be aware that I always reset the Ofn%LPSTRINITIALDIR parameter before execution of iret = InitializeOpen() : bret = GETOPENFILENAME(Ofn)
mecef4: The filter only limit the types of file to be displayed in the dialogue..
Paul: The function you suggest looks nice. I tried to compile it, but the IVF compiles does not accept the "MOR" function. I also noticed that some parameter TYPE(T_OPENFILENAME) declarations was not accepted by
Intel® Fortran Compiler 14.0 - Sp1. A clarification along with an example of application would be helpful..
Cheers
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Since Paul's code effectively incorporates my proposal and is much more complete, I suggest you add
USE IFWIN, ONLY: T_OPENFILENAME
before his IMPLICIT NONE statement and replace
MOR(a,b,c,d)
with
IANY([a,b,c,d])
which I wish Paul would do throughout his code base because everyone seems to have trouble with that usage.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
One other issue with interoperable filenames is the C/Windows side expects (requires) null terminated strings. While it is relatively easy to remember this and tack on a null character to TRIM'd variable, it is just as easy to overlook that TRIM does not trim out NULL characters. You must account for this when concatenating partial path//name//type that may contain embedded NULL character.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I did as suggested in post #6, and the code looks like shown below, logfila is Attached..
LOGICAL FUNCTION DlgFileIO (rw_mode, hwndParent, filter, fullpath, ncfn, extn, ncextn, path)
USE IFWIN, ONLY: T_OPENFILENAME
IMPLICIT NONE
CHARACTER(LEN=1), INTENT(IN) :: rw_mode
INTEGER(HANDLE), INTENT(IN) :: hwndParent
CHARACTER(LEN=*), INTENT(IN) :: filter
CHARACTER(LEN=*), INTENT(IN) :: extn
CHARACTER(LEN=*), INTENT(INOUT) :: fullpath
INTEGER, INTENT(INOUT) :: ncfn, ncextn
CHARACTER(LEN=*), INTENT(INOUT) :: path
INTEGER :: rval
logical dataprime ! by rjt
TYPE(T_OPENFILENAME) :: ofn
ofn%lStructSize = SIZEOF(ofn)
ofn%hwndOwner = hwndParent
ofn%hInstance = hInstance !ghInstance
ofn%lpstrFilter = LOC(filter)
ofn%nFilterIndex = 0 ! force use of 1st filter entry,
ofn%lpstrCustomFilter = 0 ! restricts to single file type
ofn%lpstrFile = LOC(fullpath)
ofn%nMaxFile = LEN(fullpath)
ofn%lpstrInitialDir = LOC(path)
ofn%lpstrDefExt = LOC(extn)
ofn%nMaxCustFilter = 0
ofn%nMaxFileTitle = 0
ofn%lpstrTitle = loc(""C)
ofn%lpfnHook = NULL
ofn%lpTemplateName = NULL
IF (rw_mode == 'R') THEN
ofn%Flags = IANY(OFN_HIDEREADONLY, OFN_PATHMUSTEXIST, &
OFN_FILEMUSTEXIST, OFN_SHAREAWARE )
DlgFileIO = GetOpenFileName (ofn)
ELSE
ofn%Flags = IANY(OFN_HIDEREADONLY, OFN_CREATEPROMPT, &
OFN_PATHMUSTEXIST, OFN_OVERWRITEPROMPT)
IF (dataprime) ofn%Flags = IOR(ofn%Flags, OFN_NONETWORKBUTTON)
DlgFileIO = GetSaveFileName (ofn)
END IF
ncfn = ofn%nFileOffset + 1
ncextn = ofn%nFileExtension + 1
END FUNCTION DlgFileIO
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
OK, that's progress. We seem to be down to 3 issues:
- Change USE IFWIN, ONLY: T_OPENFILENAME to USE IFWIN
- Change ofn%hinstance = hinstance to ofn%hinstance = 0_HANDLE
- Remember the array construtor syntax for IANY: IANY([a,b,c,d]) not IANY(a,b,c,d)
I didn't notice that so much stuff from IFWIN was being accessed, so just USE the whole module. Paul's code likely was in a module where hinstance was declared, but the docs for GetOpenFileName (Google GetOpenFileName MSDN) indicate that ofn%hinstance will be ignored for this value of ofn%Flags. IANY operates on one array, not several scalars.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You guys are so darn picky. My code samples are obviously extracted from a much larger multimodule Windows program, which obviously USEs large parts of IFWIN and IFWINTY. The point is to provide a quick guide which is actually useful for these sort of Windows methods using F90, all of which have been solved, somewhere, for decades. And, my MOR() function is simply a concatenation of Multiple IORs to set a bunch of bitflags at once; worth abstracting into a function since this is done a lot in Win32 setups.
If your program is a native Win32 program (ie, not a console), here is where you get the global instance and module handle:
INTEGER FUNCTION WinMain(hInstance, hPrevInstance, lpszCmdLine, nCmdShow) !DEC$ IF DEFINED(_X86_) !DEC$ ATTRIBUTES STDCALL, ALIAS : '_WinMain@16' :: WinMain !DEC$ ELSE !DEC$ ATTRIBUTES STDCALL, ALIAS : 'WinMain' :: WinMain !DEC$ ENDIF !USE i f w i n USE globals ! also USEs IFWIN components USE kernel32 IMPLICIT NONE SAVE INTEGER(HANDLE), INTENT(IN) :: hInstance INTEGER(HANDLE), INTENT(IN) :: hPrevInstance INTEGER, INTENT(IN) :: lpszCmdLine INTEGER, INTENT(IN) :: nCmdShow ! intialize global instance; these are held in the Globals module ghInstance = hInstance ghModule = GetModuleHandle(NULL)
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page