Software Archive
Read-only legacy content
17061 Discussions

edit file from dialog box

Intel_C_Intel
Employee
1,234 Views
I am using 'getopenfilename' from samples-advanced-win32; unfortunately it does not allow to open a text or fortran file from the drop list. I appreciate Steve L's reply. Not being familiar with win32 API I like someone to provide me the Win32 API command which will open the file I select (using word or wordpad or anything else for that matter) and then again save the file after I am done editing(thing which we do everyday). The original code is included below:

! Example of calling the Win32 API routine GetOpenFileName
! This can be used from any application type, including Console
!
! GetSaveFileName is very similar.
!
program fileopen

use comdlg32
use dflib ! In case QuickWin is used
implicit none

! Declare structure used to pass and receive attributes
!
type(T_OPENFILENAME) ofn

! Declare filter specification. This is a concatenation of
! pairs of null-terminated strings. The first string in each pair
! is the file type name, the second is a semicolon-separated list
! of file types for the given name. The list ends with a trailing
! null-terminated empty string.
!
character*(*),parameter :: filter_spec = &
"Text Files"C//"*.txt"C// &
"Fortran Files"C//"*.f90;*.f"C//""C

! Declare string variable to return the file specification.
! Initialize with an initial filespec, if any - null string
! otherwise
!
character*512 :: file_spec = ""C
integer status,ilen
ofn%lStructSize = SIZEOF(ofn)
ofn%hwndOwner = NULL ! For non-console applications,
! set this to the Hwnd of the
! Owner window. For QuickWin
! and Standard Graphics projects,
! use GETHWNDQQ(QWIN$FRAMEWINDOW)
!
ofn%hInstance = NULL ! For Win32 applications, you
! can set this to the appropriate
! hInstance
!
ofn%lpstrFilter = loc(filter_spec)
ofn%lpstrCustomFilter = NULL
ofn%nMaxCustFilter = 0
ofn%nFilterIndex = 1 ! Specifies initial filter value
ofn%lpstrFile = loc(file_spec)
ofn%nMaxFile = sizeof(file_spec)
ofn%nMaxFileTitle = 0
ofn%lpstrInitialDir = NULL ! Use Windows default directory
ofn%lpstrTitle = loc(""C)
ofn%Flags = OFN_PATHMUSTEXIST
ofn%lpstrDefExt = loc("txt"C)
ofn%lpfnHook = NULL
ofn%lpTemplateName = NULL

! Call GetOpenFileName and check status
!
status = GetOpenFileName(ofn)
if (status .eq. 0) then
type *,'No file name specified'
else
! Get length of file_spec by looking for trailing NUL
ilen = INDEX(file_spec,CHAR(0))
type *,'Filespec is ',file_spec(1:ilen-1)
! Example of how to see if user said "Read Only"
!
if (IAND(ofn%flags,OFN_READONLY) /= 0) &
type *,'Readonly was requested'
end if
end program fileopen

Thanks
0 Kudos
12 Replies
isn-removed200637
1,234 Views
That is peculiar. I am using WIndows NT and I use GetOpenfilename to access files for my applications. When the Explorer window opens, I can right-mouse click on a filename listed in the selection box and get a list of options (such as 'Open with' or 'send to', or Print) which allow me
to open the file before selection and edit it, or whatever, besides selecting it for opening by my application. Maybe your Explorer is set up differently.
0 Kudos
Intel_C_Intel
Employee
1,234 Views
Hi Anthony,
Thank you for your reply. Yes by right clicking the particular file I am able to open up a file(no choice- only notepad). I just wonder when I run 'getopenfilename' from the samples/advanced/win32 area it opens up the windows dialog box 'open' which has also a 'open' button. Now if I select a file and click on open, instead of opening a file it writes filespec is ... on the dos window and waits for pressing any key to finish execution. I suggest that you try to run that program from the samples area and let me know about your experience. Thanks.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,234 Views
Am I missing something here? Do you mean open another application capable of editing text files? If so, you may consider ShellExecute (which is equal to the action when you double-click a file in Explorer). So, you should add something like the following:

 
file_spec = file_spec(1:ilen) !cut all but trailing zero 
dir_spec = file_spec(1:INDEX(file_spec,'',.TRUE.)-1)//CHAR(0) 
iSt=ShellExecute(NULL, "open"C, file_spec, NULL, dir_spec, 0) 


There's also CreateProcess which would enable you to explicitly specify what application will be used for opening, but that's a bit more complicated.
Note that both ShellExecute and CreateProcess will start the editor application asynchronously, i.e. they won't block your application.

Jugoslav
0 Kudos
Intel_C_Intel
Employee
1,234 Views
Hi Jugoslav,
Thank you very much. I included your lines to GETOPENFILE.f90; to get rid of few error messages I included:
character*512 :: dir_spec = ""C
integer status,ilen,iSt

Still I am getting the following message:
Program FilesMicrosoft Visual StudioDF98SAMPLESADVANCEDWIN32GETOPENFILENAMEGetOpenFilename.f90(67) : Error: This name does not have a type, and must have an explicit type. [SHELLEXECUTE]
iSt=ShellExecute(NULL, "open"C, file_spec, NULL, dir_spec, 0)
------^
So what can be done. My purpose is to select a file from windows open dialog box and open it using the open button on the dialog box.
0 Kudos
isn-removed200637
1,234 Views
IMHO, you should ignore the 'open button'.


You can do more by adding to the drop-down list that appears when you right click on the mouse with the file selected from the list of files available.


How this is done depends on what version of windows you are running.
When running Windows 9x, apparently you look for the 'Send To' folder in /Windows/ and edit in shortcuts to the applications you want to add to the drop-down list that appears when you right-mouse-click.


Whne running Windows NT, you look for the 'Send to' folder under 'Profiles' in /WINNT/ and add a shortcut to the application that you want to add to the 'Send to' list.


HIH


Tony Richards
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,234 Views
You have to USE appropriate header module also. It seems to be SHELL32. Note that USE DFWIN statement includes everything you might need for Win32 APIs (on the possible price of having bit slower compilation).
Having seen exact declaration of ShellExecute in Shell32.f90,
it seems that I made a slight error -- 4th parameter should be NULL_CHARACTER, not NULL.

Jugoslav
0 Kudos
Intel_C_Intel
Employee
1,234 Views
Hi Jugoslav,
Thank you very much. Using your advise i successfully compiled the routine and was able to open a file using the open button. There are few items I want some advise on:
1)The open dialog box has provision for text only or fortran type files; even if I select a file using the mouse and it shows up (file name) in the selection area, still I have to type in .txt to open a text file. Double click does not work; whereas in regular window applictions we are able to use double click as well as select a file and then click on open. It is not necessary to type in the file extension like .txt, .f, .m etc.
2)My purpose of opening and editing the file is for using it as an input for the program I am executing which will write many lines on the console window. Which will be the best thing to do:
Start program execution- come to a line and ask for the choice about file edit and once the editing is done and the file is saved, continue on with the program. And for the above is calling the getopenfilename as a subroutine will be good enough.
3)Alternatively I can have a 'edit input.dat y/n' on the main dialog box and depending on the choice, the open dialog box will pop up and rest will be same as above.
These are plain Jane in interactive programming, I am not so sure about the same with a dialog box.
I shall appreciate any suggestion from you along with any similar example if you have one.
Thanking you.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,234 Views
First of all, I don't think it's a good idea to let the user edit your file in Notepad or something similar. User can do it himself without that kind of "interaction". Now, I don't know what's your data structure, but a "real" interactive program should have a dialog which will enable the user to edit and inspect the data in more friendly manner. If your data structure is very complex, that will be a lot of work, of course. Let user open, save, edit data and start calculation from a dialog. Provide edit-boxes, check-buttons etc. for necessary entries.

Not that I'm against file-based approach, contrary. A "real stuff" would be to have a dialog which would have "Open" and "Save" buttons which would invoke GetOpenFileName/GetSaveFileName. However, the user need not see what's your file structure. Do you know file format of, say, Word .docs? Probably no -- neither do I -- why should I care? DFLOGM interface is relatively simple -- go ahead and use it.

Back to your your problem 1) -- adding .OR.OFN_EXPLORER (=#00080000, in case it isn't defined in dfwinty) in ofn%Flags would probably fix it.

Jugoslav
0 Kudos
Intel_C_Intel
Employee
1,234 Views
Hi Jugoslav,
Thanks again. I included your correction and recompiled, but result remained same.But I can see, a file is being opened, but it diappears fleetingly. Then when I do ctrl-alt-del I see a bunch of wordpad and notepads. Somehow some jobs are hanging in there. This is what I have now:

character*512 :: file_spec = ""C
character*512 :: dir_spec = ""C
integer status,ilen,iSt
ofn%lStructSize = SIZEOF(ofn)
ofn%hwndOwner = NULL ! For non-console applications,
! set this to the Hwnd of the
! Owner window. For QuickWin
! and Standard Graphics projects,
! use GETHWNDQQ(QWIN$FRAMEWINDOW)
!
ofn%hInstance = NULL ! For Win32 applications, you
! can set this to the appropriate
! hInstance
!
ofn%lpstrFilter = loc(filter_spec)
ofn%lpstrCustomFilter = NULL
ofn%nMaxCustFilter = 0
ofn%nFilterIndex = 2 ! Specifies initial filter value
ofn%lpstrFile = loc(file_spec)
ofn%nMaxFile = sizeof(file_spec)
ofn%nMaxFileTitle = 0
ofn%lpstrInitialDir =loc("c:test"C) ! Use Windows default directory
ofn%lpstrTitle = loc(""C)
!ofn%Flags = OFN_PATHMUSTEXIST
ofn%Flags = #00080000
ofn%lpstrDefExt = loc("dat"C)
ofn%lpfnHook = NULL
ofn%lpTemplateName = NULL

Please let me know whether there is any mistake. Even the right click does not work any more. May be it opens a file which remains invisible.
Thanks.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,234 Views
Sorry, haven't actually used ShellExecute myself -- just knew about it. Seems that the last argument (), contrary to the docs, is important when a "file" is "executed". The following code works OK with me:

 
PROGRAM OFNTEST 
 
USE DFWIN 
 
IMPLICIT NONE 
 
!DEC$ OBJCOMMENT LIB: "comdlg32.lib" 
!DEC$ OBJCOMMENT LIB: "shell32.lib" 
 
character*256 :: file_spec = ""C  
character*256 :: dir_spec = ""C  
character*64 :: filter_spec = "Data files"C//"*.dat"C//"Text files"C//"*.txt"C//CHAR(0) 
 
integer status,ilen,iSt  
type(T_OPENFILENAME)::  OFN 
 
ofn%lStructSize = SIZEOF(ofn)  
ofn%hwndOwner = NULL ! For non-console applications,  
                      ! set this to the Hwnd of the  
                      ! Owner window. For QuickWin  
                      ! and Standard Graphics projects,  
                      ! use GETHWNDQQ(QWIN$FRAMEWINDOW)  
                      !  
ofn%hInstance = NULL ! For Win32 applications, you  
                      ! can set this to the appropriate  
                      ! hInstance  
                      !  
ofn%lpstrFilter = loc(filter_spec)  
ofn%lpstrCustomFilter = NULL  
ofn%nMaxCustFilter = 0  
ofn%nFilterIndex = 2 ! Specifies initial filter value  
ofn%lpstrFile = loc(file_spec)  
ofn%nMaxFile = sizeof(file_spec)  
ofn%nMaxFileTitle = 0  
ofn%lpstrInitialDir =loc("D:Users"C) ! Use Windows default directory  
ofn%lpstrTitle = loc(""C)  
ofn%Flags = OFN_PATHMUSTEXIST .OR. #00080000  
ofn%lpstrDefExt = loc("dat"C)  
ofn%lpfnHook = NULL  
ofn%lpTemplateName = NULL  
 
iSt=GetOpenFileName(OFN) 
 
ilen=INDEX(file_spec,CHAR(0)) 
file_spec = file_spec(1:ilen) !cut all but trailing zero   
dir_spec = file_spec(1:INDEX(file_spec,'',.TRUE.)-1)//CHAR(0)   
iSt=ShellExecute(NULL, %VAL(0), file_spec, %VAL(0), dir_spec, SW_SHOW)   
 
END PROGRAM OFNTEST 


Jugoslav
0 Kudos
Intel_C_Intel
Employee
1,234 Views
Hi Jugoslav,
Thank you vey much, your routine worked beautifully. Now I am trying to put things together and having some problem- which are:
1)In my dialog box I have a question for editing a file with a combobox1 y/n-when the box comes up I do not have choice for y/n- only the preselected one shows up- I used the whizzy example for this.
2)In the dodialog I am also calling the hfeam which is the main program- if I did not have that the program terminates with access violation.
3)I the .dat file types I need to delete few *.dat files before I can execute the 'hfeam'. When the getopenfile opens up with .dat filetypes for input.dat editing I can as well right click on those .dat files and delete them one at a time. Is there a better method with winapi so that those files can be preselected and deleted with one click after deselecting ones not to be deleted.
I am enclosing the main routine and the resouce.fd for you.
Thanks.

! hfm.f90
!
! FUNCTIONS:
! hfm - Entry point of console application.
!

!****************************************************************************
!
! PROGRAM: mor
!
! PURPOSE: Entry point for the console application.
!
!****************************************************************************

program hfm
use dflogm
implicit none
include 'resource.fd'

Call DoDialog



end program hfm

!****************************************************************************
!
! SUBROUTINE: DoDialog
!
! PURPOSE: Displays the dialog box
!
!****************************************************************************

SUBROUTINE DoDialog( )
USE DFLOGM
IMPLICIT NONE
INCLUDE 'RESOURCE.FD'

INTEGER retint
LOGICAL retlog
TYPE (dialog) dlg
! EXTERNAL UpdateTemp
EXTERNAL hfminp,updatecombo
! Initialize.
IF ( .not. DlgInit( idd_dbox, dlg ) ) THEN
WRITE (*,*) "Error: dialog not found"
ELSE
! Set up temperature controls.
! retlog = DlgSet( dlg, IDC_SCROLLBAR_TEMPERATURE, 200, DLG_RANGEMAX)

retlog = DlgSet( dlg, IDC_COMBO1, 2 )
retlog = DlgSet( dlg, IDC_COMBO1, "N",1 )
retlog = DlgSet( dlg, IDC_COMBO1, "Y",2 )
retlog = DlgSetSub( dlg, IDC_COMBO1, UpdateCombo, dlg_selchange )
retlog = DlgSetSub( dlg, IDC_COMBO1, UpdateCombo, dlg_update )
call UpdateCombo( dlg, IDC_COMBO1, dlg_update )
retlog = DlgSet( dlg, IDC_COMBO2, 2 )
retlog = DlgSet( dlg, IDC_COMBO2, "N",1 )
retlog = DlgSet( dlg, IDC_COMBO2, "Y",2 )
!retlog = DlgSet( dlg, IDC_EDIT_PAYMENT,"")
! CALL hfminp( dlg, DLG_CHANGE)
! retlog = DlgSetSub( dlg, IDC_EDIT_CELSIUS, UpdateTemp )
! retlog = DlgSetSub( dlg, IDC_EDIT_PAYMENT, mort )

retlog = DlgSetSub( dlg, IDC_BUTTON_RUN, hfminp )
print 401
401 format('exit hfinp')

! retlog = DlgSetSub( dlg, IDC_SCROLLBAR_TEMPERATURE, UpdateTemp )
! Activate the modal dialog.
retint = DlgModal( dlg )

! Release dialog resources.
CALL DlgUninit( dlg )
END IF
END SUBROUTINE DoDialog

SUBROUTINE hfminp(dlg, callbacktype)

USE DFLOGM
IMPLICIT NONE
TYPE (dialog) dlg
INTEGER callb acktype,control_name
INCLUDE 'RESOURCE.FD'
CHARACTER(256) text
CHARACTER(1)edtdat
INTEGER retint
real i,pv,amt,pr,fint
LOGICAL retlog
! Suppress compiler warnings for unreferenced arguments.
INTEGER local_callbacktype

local_callbacktype = callbacktype


retlog = DlgGet( dlg, IDC_COMBO1, text )

READ (text, *, iostat=retint) edtdat

!retlog = DlgGet( dlg, IDC_EDIT_, text )
!READ (text, *, iostat=retint) i
!retlog = DlgGet( dlg, IDC_EDIT_YEARS,text )
!READ (text, *, iostat=retint) n


! Calculate

IF ( retint .eq. 0 ) THEN
IF(edtdat .eq. 'N') THEN
call fileopen
END IF
call mainsub
!WRITE (text,*,iostat=retint) amt
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,234 Views

1)In my dialog box I have a question for editing a file with a combobox1 y/n-when the box comes up I do not have choice for y/n- only the preselected one shows up- I used the whizzy example for this.



You probably just didn't stretch the combo's dropdown enough in rc editor. I bet you'll get "y" using arrow keys when combo has the focus. To fix that,
click on "arrow down" of combo box of editor and then stretch the dropdown as long as you want (in the actual app, the actual height will be MIN(#of items, adjusted height)). Btw, for your purpose a check-box is more appropriate.

2)In the dodialog I am also calling the hfeam which is the main program- if I did not have that the program terminates with access violation.


Didn't quite get you -- did you made a mix between hfeam and hfminp? How do you mean hfeam is the main program?

An apparent fishy thing is that your hfminp lacks the ID (2nd) argument -- I understand you don't need it, but in this way you'll get stack corruption. You have to define it and use it in the same way as callbacktype.

3)I the .dat file types I need to delete few *.dat files before I can execute the 'hfeam'. When the getopenfile opens up with .dat filetypes for input.dat editing I can as well right click on those .dat files and delete them one at a time. Is there a better method with winapi so that those files can be preselected and deleted with one click after deselecting ones not to be deleted.


Hmh, I understand GetOpenFileName is a handy tool, but its primary purpose is not to delete files from there. You can add OFN_ALLOWMULTISELECT flag to enable multiple deletion, but in this way
you'll also get a multiple selection capability. I've got a simple GetOpenFileName wrapper function which should be simpler to use and add
multi-select capability without much pain (otherwise you'll have to parse OFN%lpstrFile yourself). We can continue this by e-mail so that we don't burden the forum with much code.

Jugoslav

P.S. when posting please enclose your code in HTML tags:



...code here




so that the Forum software won't screw it.
0 Kudos
Reply