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

Help with project

klizder
Beginner
1,903 Views
Hi everyone, I need help with my project. I'm suppose to use (Compaq) Visual Fortran to do a simulation program. In a nutshell, it's very simple. The program has to take in a list of constants and plot graphs accordingly. But I'm getting so stressed out about this because of my lousy programming, not to mention this is my first time working with Fortran.

First up, I've created a dialog box to enter the variables, using edit boxes. Now, I can save these values, read as char, in a text file, but I am unable to read back these values as float/real values. Am I doing something very wrong here? It's really strange cos if I open the text file (.txt), and resave the file with notepad, I can read the values as float/real type with no problems.

I've been trying to think of ways to solve this, but none seems to work. I was thinking of seperating the value before and after the decimal and store as two integers instead, but I thought that would be really user unfriendly.

I'm really stressed about this now because I've been looking at this problem for weeks now. And it's still just the very beginning of the project! Next step would require me to make use of the relevant equation(s) proper and generate the values, before plotting a graph. I hope I've at least got the idea of this correct.

Please help. I really need all the advice I can get asap.
0 Kudos
18 Replies
anthonyrichards
New Contributor III
1,903 Views

To get helpful answers, you should

a) include a sample of the text you are trying to read in

b) includeany and allerror messages you are getting, when you say you are 'unable to read in' the data.

c) include a sample of the FORTRAN code you are using to try and open the text file and read data from it into variables in your program.

Otherwise we are none the wiser.

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,903 Views
It's strange that the file suddenly gets readable by simple resaving with notepad. It's difficult to tell offhand what's wrong; two reasons come to my mind:

1) You have a non-ASCII (maybe even invisible) character getting in there, like char(0), which Notepad strips in some way. Try opening the file before and after the saving in a hex editor (e.g. File/Open/Open as->"Binary") and take a close look at differences (or copy and paste hex codes into other two files and compare them using CVF's WinDiff tool).
2) You forgot to CLOSE the file after WRITEing it, so subsequent READing starts from the wrong end of the file.

Note that, if you have dialog GUI and the calculation in the same exe, you don't need a file as a mediator. You can simply fill in values from edit boxes directly into variables:
CHARACTER(20):: s
...
ret = DlgGet(Dlg, IDC_EDIT_WHATEVER, s)
READ(s, "(f10.0)", IOSTAT=iErr) realValue
IF (iErr.NE.0) THEN
MessageBox(..."Invalid real value in edit box"...)
END IF

Also note that edit boxes can have "Number" property, which reduces user's input only to integers. However, it can't be done for floating-point numbers, so you should guard against potential mis-entry.

HTH,
Jugoslav
0 Kudos
klizder
Beginner
1,903 Views
Thanks for the advice. Alright here goes, hope I can get it across clearly.

The data is simply any real number. eg. 123.45 or 67.098.

There is no compile error message. I just do not get the result I expect.

Here's the code I used to save the information. To make it simpler I'm using only 3 inputs here:

--------
!Variables
integer(4) iret
integer(4) MaxCharacters
integer(4) pinResist,pinSDL,pinThick

MaxCharacters = 10

if (LOWORD(uParam) .EQ. IDUPDATE) then !IDUPDATE button pressed

pinResist = " "C
pinSDL = " "C
pinThick = " "C

iret = GetDlgItemText(hDlg, IDC_PIN_RESISTIVITY, pinResist, MaxCharacters)
iret = GetDlgItemText(hDlg, IDC_PIN_SDL, pinSDL, MaxCharacters)
iret = GetDlgItemText(hDlg, IDC_PIN_THICK, pinThick, MaxCharacters)

open(unit=10, file="INPUT.txt", action="write")!status="replace",
write (10,'(6I10)') pinResist, pinSDL, pinThick
close (unit=10)

InputDlgProc = 0

return
----------

Opening INPUT.txt, I verified that the file contains the information I want to save.

In order to use the information, I have the following:

----------

integer(4) iret
integer OpenStatus, InputStatus
real x, y, z

if (LOWORD(uParam).EQ.IDOK) then
open(unit=10, file="INPUT.txt", status = "old", &
action = "read", iostat = OpenStatus)

if (OpenStatus > 0) then
iret = MessageBox(hDlg, "Input data does not exist! &
Please enter parameters first."C, &
"Input Error"C, MB_OK)

else
read(10,'(3F10.0)', IOSTAT = InputStatus) x, y, z
close(unit = 10)

if (InputStatus > 0) then
iret = MessageBox(hDlg, "Data Error!"C, &
"Input Error"C, MB_OK)

else
call CALCULATE(x1, x2, y1, y2, z1, z2)

end if

end if

-------

If I run this part (ie. to click on that particular OK button), I'll always get "Input Error". However, if I resave the INPUT.txt with notepad, it works as I want it to.

Another strange thing is that when intialising the input dialog window, I used the following code:

--------
call CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER))
MaxCharacters = 10

open(unit=10, file="INPUT.txt", status = "old", &
action = "read", iostat = OpenStatus)

if (OpenStatus <= 0) then
read (10,'(6I10)') pinResist, pinSDL, pinThick2

iret = SetDlgItemText(hDlg, IDC_PIN_RESISTIVITY, trim(adjustl(pinResist)))
iret = SetDlgItemText(hDlg, IDC_PIN_SDL, trim(adjustl(pinSDL)))
iret = SetDlgItemText(hDlg, IDC_PIN_THICK, trim(adjustl(pinThick)))

end if

close (unit=10)

InputDlgProc = 1

-------------

This part works fine if I do NOT resave INPUT.txt. If I did, a character which looks like and up-down-arrow is appended to each character string in the edit boxes.

From this, Im guessing that its because I wrote to file as CHAR type, making it not possible to read as REAL/float.
0 Kudos
klizder
Beginner
1,903 Views
Many thanks for confirming for me that I cannot read Edit boxes input as only integers or char and not floating point numbers.

So is it advisable to force the user to input the integer part and the decimal part seperately? This would guard against misentries, but it seems rather user unfriendly.

If the dialog window isn't open, can I still use the values from edit boxes directly instead from the file? I'm asking this cos I'm currently allowing the user to call the Calculate function without opening the Input dialog window...
0 Kudos
klizder
Beginner
1,903 Views
Hi again, sorry for making yet another post, but I gotta ask, what's the difference between the GetDlgItem/SetDlgItem functions and the DlgGet/DlgSet functions? I found them in separate books, the former being in a Compaq Visual Fortran book and the latter in a Digital Visual Fortran book. They're both available in the Help sections too. However I can't seem to get DlgGet/DlgSet functions to work. Am I just doing it wrongly?
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,903 Views
That compiles? Not in my CVF 6.6C:
Error: The type of the actual argument differs from the type 
of the dummy argument. [PINRESIST]
iret = GetDlgItemText(hDlg, IDC_PIN_RESISTIVITY, pinResist, MaxCharacters)
-------------------------------------------------^

You have a mixup of integers and strings. GetDlgItemText expects a string argument, and you're providing integer one. Even if it compiles on another version of the compiler, it suffers from several flaws... uh, where should I start...

First, Windows APIs are not very "Fortran-friendly", because they expect and return "C-style" (char(0)-terminated) strings. WRITE statement, on the other hand, doesn't expect a char(0) within string it read and will treat it as an error if it terminates an integer or real. As I suspected, with the current version, you're writing that char(0) into file, and subsequent WRITE cannot parse it; Notepad probably has some kind of mechanism to strip it off.

Instead, use strings throughout, strip off the char(0) and then convert it to a number using internal READ:
CHARACTER(20):: s
...
ret = GetDlgItemText(hDlg, IDC_EDIT_WHATEVER, s, LEN(s))
s = s(1:INDEX(s,char(0))-1)
READ(s, "(f10.0)", IOSTAT=iErr) realValue

GetDlgItemInt will also work for "Number" edit boxes, and it accepts integer argument (If I recall correctly, 3rd argument should be LOC(i) rather than just i).

(Note: F10.0 format ensures that "1234" is read as 1234., rather than 123.4 or .1234).

As for real numbers, I wouldn't prefer splitting the edit box into "whole" and "decimal" parts; it's bothersome for the user. Instead, you can use "post-mortem test" as I shown above; if the real value is invalid, display a message box or MessageBeep, and you can SetFocus(GetDlgItem(hDlg,IDC_EDIT_FOO)) for the offending control, to attract user's attention to the error.

Jugoslav
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,903 Views
Re DlgGet/GetDlgItem*:

- There are "native" Windows routines like DialogBox, CreateDialog, GetDlgItem* etc. They deal with dialog window handle hDlg. They're described in "Platform SDK" docs.
- On the top of these APIs, there is a library made by Compaq/Digital, called DFLOGM/IFLOGM. It wraps some functionality of native APIs, it's simpler to use and more fortran friendly (but somewhat less powerful). It deals with TYPE(DIALOG) and contains DlgInit, DlgModal, DlgGet, DlgSet etc. It is described in "Programmer's Guide" section of the manual.

E.g. VF Application Wizard gives you a DFLOGM version of the code to start with. You can (but it's not often necessary) use native APIs with dialog created with DFLOGM (DlgInit/DlgModal), because Dlg%hWnd member gives you the handle. However, the reverse is not true, because you can't get a TYPE(Dialog) out of nothing -- it's created by DlgInit fuction of DFLOGM.

You can check out my home page, www.xeffort.com or archives of this Forum for various samples.

Jugoslav
0 Kudos
klizder
Beginner
1,903 Views
Many many thanks Jugoslav!

Oops, my bad, the variables pinResist and so were suppose to be character(10) type, not integers.

I've tried your method of removing the char(0) and now it reads fine (thanks again!). However, converting string to real number still has problems. What if I do not wish to use F10.0 format, but instead F10.3? Using F10.3 I get 0.003 when the input is 3.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,903 Views
F10.0 should work as expected; F10.3 will suffer from exactly the problem you described.Simpler still, you can use list-directed internal read (READ(string, *)).
Jugoslav
0 Kudos
klizder
Beginner
1,903 Views
Thanks to you, I'm finally moving on to the next step =)

Now, I've been given 14 simultaneous equations to solve. How should I go about doing that with Fortran? I'm going to start reading up on this, any help and advice would be great!
0 Kudos
anthonyrichards
New Contributor III
1,903 Views

Algebraic or differential equations?
What methods of solution have been suggested to you?

0 Kudos
klizder
Beginner
1,903 Views
Hello hello, sorry for the slow reply, have been busy with the lunar new year ;P

And yea, to answer your question, it's algebraic equations, no differential ones.
0 Kudos
klizder
Beginner
1,903 Views
Dear all,

Here's what I wish to do. I have 20 Edit Boxes, each accompanied and labeled with a Radio button. All the Radio buttons are in the same group (I hope I'm making sense, I'm trying to allow only one Radio Button to be checked). When a Radio button is selected, I wish to have the corresponding Edit Box disabled. How do I do this?

Another question. For an Edit Box with Spin "buddied", how do I set maximum and minimum? Also, is it possible to set it such that up is increment and down is decrement?

Thanks in advance.
0 Kudos
anthonyrichards
New Contributor III
1,903 Views

Its all in the on-line help...

iret=DlgSet(dlg,IDC_EDITBOX, .false., DLG_STATE)

will disable an edit box identified by IDC_EDITBOX. As for managing the spin resource,just look for'dialog controls...indexes'and carry on from there...e.g. use DlgSet and DLG_POSITION, DLG_RANGEMIN,DLG_RANGEMAX.

0 Kudos
klizder
Beginner
1,903 Views
Sorry, where is this "online help"?

I tried using the DlgSet (under "case (WM_COMMAND)", but nothing happens. I tried using it when initialising under "case (WM_INITDIALOG)", nothing happens either. What else do I need to do? I think I'm doing all this wrong. Sigh.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,903 Views
In a Win32-handled dialog, you should use:
EnableWindow(GetDlgItem(hDlg, IDD_EDIT_n), TRUE/FALSE)


Tip: when you have an "array of controls" as in your case, it's useful to shorten the handling by making an array of consecutive integers for control IDs:

1) Open the resource.h file and edit the radio and edit IDs so that they're consecutive, like:
#define IDC_RADIO_1 1221
#define IDC_RADIO_2 1222
...
#define IDC_RADIO_20 1240
#define IDC_EDIT_1 1241
#define IDC_EDIT_2 1242
...
#define IDC_EDIT_20 1260

2)Then, your code will be as simple as:
CASE(WM_COMMAND)
idCommand = LOWORD(wParam)
SELECT CASE(idCommand)
CASE(IDC_RADIO_1:IDC_RADIO20)
iItem = idCommand - IDC_RADIO_1
!Disable all edits except the "selected" one
DO idEdit = IDC_EDIT_1, IDC_EDIT_20
iret = EnableWindow(GetDlgItem(hWnd,idEdit+iItem), &
iItem.EQ.idEdit-IDC_EDIT_1)
END DO
CASE(something else)
...
END SELECT
0 Kudos
klizder
Beginner
1,903 Views
Thank you so much Jugoslav, it's working as I want it now! Except for one thing, how do I set a radio button's checked state to true in a Win32-handled dialog?
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,903 Views
SendDlgItemMessage(hDlg, IDC_RADIOx, BM_SETCHECK, BST_CHECKED, 0)


Note that 99% of handling controls is done using messages (Send(DlgItem)Message), so you'd better get familiar with them. Button messages have prefix BM_, editbox ones EM_ etc.
0 Kudos
Reply