|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
Martin_K
Joined: 09 Apr 2020 Posts: 227
|
Posted: Sun Apr 12, 2020 11:02 pm Post subject: How to bring dialog windows from subroutine to main program |
|
|
Hello to anyone!
I need to advise how to bring dialog windows defined in a subroutine
to main calling program (thanks in advance).
DESCRIPTION:
I defined a main window in the main program, where the user must define three variables (VARIABLE1: input file name with input data, VARIABLE2: output file name, where the new data will be written and VARIABLE3: to change or not the signs in the output data). When this is specified, all 3 variables are passed to a subroutine, which is called from main program and which - in fact - does the real job.
Since for the subroutine it takes some time (around 35 minutes) to finish the job, it is necessary to define a progress bar, otherwise the user sees nothing in the main window and can have such feeling that the program does not work (although it works). So, I defined within the called subroutine a progress bar window and - when subroutine finishes - a message window that the job is done and then it should be returned to main window of the main program. However, these windows are nowhere seen and never displayed.
The last iowin function in main program (placed directly before calling the subrouitine is:
1 ans=winio@('%3nl%taChange signs for DX and DY in the output TXT file? (y=yes, n=no)%`5.2ls',change,3l,selection)
The three iowin functions in the called subroutine, placed before the real job starts - it means before an outer DO loop) are:
ans=winio@('%ca[Progress bar]&')
ans=winio@('Current status ... %2nl&')
ans=winio@('%60br&',bar_fill,RGB@(255,255,0))
then immediately come three DO loops:
First: do i = 1,I_Pocet_X !outer DP loop
!
! defining the step of the progres bar (corresponds to 1%)
!
krok_bar_fill = 100.0/real(I_Pocet_X)
if (i.eq.1) then
bar_fill=0.0
else
bar_fill = bar_fill+krok_bar_fill
end if
!
! calling progress bar update for the value bar_fill (up to value 1)
! ---------------------------------------------------------
!
do while (bar_fill.lt.1.0) !beginning DO WHILE
CALL window_update@(bar_fill)
if (i.eq.1) then
I_X = I_Xmin
else
I_X = I_X + I_X_krok
end if
Inner1: do j = 1, I_Pocet_Y ! first inner DO loop - beginning
if (j.eq.1) then
I_Y = I_Ymin
else
I_Y = I_Y + I_Y_krok
end if
rewind 3
Inner2: do n = 1, k ! second inner DO loop - beginning
if (n.lt. then
read (3,*) riadok
cycle
else
read (3,*) I_XX, I_YY, DDX, DDY
end if
if (I_X.eq.I_XX.and.I_Y.eq.I_YY) then
if (selection.eq.2) then
write (4,37) I_XX, I_YY, DDX, DDY
37 format (I8,',',I7,',',F6.2, ',',F6.2)
else
DDX = -1.0*DDX
DDY = -1.0*DDY
write (4,95) I_XX, I_YY, DDX, DDY
95 format (I8,',',I7,',',F6.2, ',',F6.2)
end if
exit
else if (n.eq.k) then
write (4,33) I_X, I_Y, DX, DY
33 format (I8,',',I7,',',F6.2, ',',F6.2)
end if
end do Inner2
end do Inner1
end do !end do loop DO WHILE, when bar_fill, is less than 1
end do First
close (3)
close (4)
!
! Message window - conversion done
!
w=200
h=20
ans=winio@('%sz&',w,h)
ans=winio@('%ca%bf%fn[Arial][Program DATA_CONV - Info]&')
a |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2391 Location: Yateley, Hants, UK
|
Posted: Mon Apr 13, 2020 2:09 pm Post subject: |
|
|
You could launch a separate application, and use messaging to report back when the job is finished. Return the results in a Windows Message, or via a file named in a Windows message.
Eddie |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7942 Location: Salford, UK
|
Posted: Mon Apr 13, 2020 3:22 pm Post subject: |
|
|
Martin
Could you post a very short sample program outlining what you want to do.
Leave out the input statement, replacing them with a comment, the same for the computation. |
|
Back to top |
|
|
Martin_K
Joined: 09 Apr 2020 Posts: 227
|
Posted: Mon Apr 13, 2020 4:32 pm Post subject: |
|
|
Hi LitusSaxonicum,
Thanks for the advise, however, I wanted as simply solution as possible (since I am new to ClearWin+) and your tip sounds for me as additional complex programming. By the way - new finding: When I close the main program by clicking on the close icon (X) on the top right corner, then the required progres bar suddenly appears! However, it is never filled. Only when I click on its top right corner (X), then suddenly fills up to the half. When I click again on X icon, then jumps nearly to 100% and ends never. I have to kill the process by Windows task manager. So, I am stuck, since I see no error in my program. |
|
Back to top |
|
|
Martin_K
Joined: 09 Apr 2020 Posts: 227
|
Posted: Mon Apr 13, 2020 5:35 pm Post subject: |
|
|
Additional info - I have rewritten my source code in such manner that there is no subroutine and all is carried out in the main program - however the progress bar behaves exactly as when it was programmed in the subroutine. |
|
Back to top |
|
|
wahorger
Joined: 13 Oct 2014 Posts: 1217 Location: Morrison, CO, USA
|
Posted: Mon Apr 13, 2020 6:05 pm Post subject: |
|
|
I have my own status bars using winio@() statements. One just displays an integer (regardless of the actual end count), the other displays the status bar as filling as it approaches the end count.
The key to doing this is that the status bar has its own window that is not closable. I define this window as "always on top" when it is created so it is always displayed.
The calling routine has to set up the kind of counter, then update the current value. The subroutine that creates, updates, and closes the status bar is responsible for not trying to update the value too quickly because (a) it slows processing and (b) can cause a crash if you were to try every iteration. I have found every second (not sooner) is quite fast enough to keep the user's view occupied so they don't try to kill the processing or believe it is hung up.
The limitation is that it works for positive integers as start/end/current.
The code for the status bar that shows percentages is:
Code: | SUBROUTINE STATUS_BAR_windows(text,NM,NMAX,NCUR)
USE MSWIN
INTEGER:: NM
integer*4:: NMIN,NMAX,NCUR,i,ifill_val
integer*4:: ifill_last,iifill,ifill
integer,parameter:: col_width = 20 ! Allows the bar to be separated into 20 distinct increments
character*(*) text ! for labelling the status bar
REAL*8:: FILL,fill_value
REAL*8:: fill_last,fill_this
integer(7):: WINDOW_HANDLE!,ICOLOR
integer*4:: WINDOW_CLOSURE
integer,external:: button_refresh
! --- INITIALIZE THE STATUS BAR WHEN NCUR = 0
NMIN = NM
select case (ncur)
case (0) ! initialize
i = winio@("%ww[no_edge,no_maxbox,no_minbox,topmost]&") !
i = winio@('%ca@&',text) ! set the caption for the status bar
fill_value = 0.0d0 ! set the initial value
ifill_last = -999
iifill = 0
ifill_val = 0
i = winio@('Processing # %`rd of %wd%2nl&',ifill_val,nmax)
i = winio@('%20br[percentage]&',fill_value,rgb@(0,0,255)) ! a status bar
i = winio@('%hw%lw',window_handle,window_closure) ! save the handle (locally) and the window_closure flag (locally)
call dclock(fill_last) ! get the time of the window creation so we don't update it too often
case (-1) ! end the display
window_closure = 0
call window_update@(window_closure)
case default
ifill_val = ncur
call dclock(fill_this)
if(fill_this-fill_last.le.1.d0) return ! do not update more than once per second (1.0d0)
fill_last = fill_this
FILL=DBLE(NCUR-nmin)/DBLE(NMAX-NMIN) ! calculate a number between 0. and 1.
! this limiting is done to make SURE the control doesn't throw an exception
IF(FILL.Ge.1.0D0)FILL = 1.D0
if(fill.le.0.0d0) fill = 0.0d0
fill_value = fill
ifill = fill*dble(col_width)
iifill=int(fill*100.d0)
if(iifill.ne.ifill_last) then ! only update the status bar when there is a visibile change
call yield_program_control@(Y_Temporarily)
ifill_last = iifill
call window_update@(fill_value) ! update the status bar itself
call window_update@(ifill_val) ! update the count being displayed
endif
end select
return
END
|
Sample code of usage only:
Code: | call status_bar_window('This is a status bar',1,1000,0) ! initialize
do i=1,1000
call sleep1@(0.25)
call status_bar_windows(' ',1,1000,i) ! will show the progress of the count changing
end do
call sleep1@(3.)
call status_bar_windows(' ',1,1000,-1) ! close the status bar window
|
|
|
Back to top |
|
|
Martin_K
Joined: 09 Apr 2020 Posts: 227
|
Posted: Mon Apr 13, 2020 6:24 pm Post subject: |
|
|
Paul,
As I described in my first post regarding this issue, the purpose of the program is to re-structure the input data available in one TXT file and re-write them in a new required format to other TXT file which will serve as an input source for other program.
Below are ONLY declared the used winio functions in the main program
(without call back functions) and the called subroutine:
!Defining the main window with 3 selectable inputs (variables, which will
be passed to the called subroutine):
w=800
h=400
ans=winio@('%sz&',w,h)
ans=winio@('%ww[thin_border]&')
ans=winio@('%ca[Program: TXT_2_SGF]&')
!
! Select input file (variable called subor3)
!
ans=winio@('%3nl%ta%bf%fn[Courier New]Input TXT for SGF:%ta%bc[yellow]%`^bt[&Select input file]&','FILE_OPENR[Select file]',subor3,sb_vstup3)
ans=winio@('%bg[grey]&')
!
! variable subor3 placed in a box
!
ans=winio@('%2nl%ta%ob%80st%cb&',subor3)
!
! Select output file (variable called subor4)
!
ans=winio@('%3nl%ta%bf%fn[Courier New]Output TXT for SGF:%ta%bc[green]%^bt[&Define output file]&',&
'FILE_OPENW[define file]',subor4,sb_vstup4)
!
! variable subor4 placed in a box
! (however, the output file is NOT displayed in the box, I do not know why
!
ans=winio@('%2nl%ta%ob%80st%cb&',subor4)
!
! Changing the signs in front of DX, DY values - question
!
ans=winio@('%3nl%taChange DX and DY signs in the output file? (y=yes, n=no)%`5.2ls',zmena,3l,vybrate)
!
! Calling subroutine, which makes re-structuring the data
!
call TXT_PRE_SGF (s3, s4, vybrate)
And now - the subroutine follows (only the part, where progress bar is defined):
SUBROUTINE TXT_PRE_SGF (subor3, subor4, vybrate)
!
! Defining progress bar
!
ans=winio@('%ca[Progress bar]&')
ans=winio@('Processing ... %2nl&')
ans=winio@('%60br',bar_fill,RGB@(255,255,0))
!
!Defining the step for window_update@(bar_fill) calling
!
krok_bar_fill = 100.0/real(I_Pocet_X)
FIRST DO LOOP: do i = 1,I_Pocet_X
if (i.eq.1) then
bar_fill=0.0
else
bar_fill = bar_fill+krok_bar_fill
end if
if (bar_fill.le.1) then
CALL window_update@(bar_fill)
end if
if (i.eq.1) then
I_X = I_Xmin
else
I_X = I_X + I_X_krok
end if
INNER DO LOOP1: do j = 1, I_Pocet_Y
if (j.eq.1) then
I_Y = I_Ymin
else
I_Y = I_Y + I_Y_krok
end if
rewind 3
INNER DO LOOP2: do n = 1, k
if (n.lt. then
read (3,*) riadok
cycle
else
read (3,*) I_XX, I_YY, DDX, DDY
end if
if (I_X.eq.I_XX.and.I_Y.eq.I_YY) then
if (vybrate.eq.2) then
write (4,37) I_XX, I_YY, DDX, DDY
37 format (I8,',',I7,',',F6.2, ',',F6.2)
else
DDX = -1.0*DDX
DDY = -1.0*DDY
write (4,95) I_XX, I_YY, DDX, DDY
95 format (I8,',',I7,',',F6.2, ',',F6.2)
end if
exit
else if (n.eq.k) then
write (4,33) I_X, I_Y, DX, DY
33 format (I8,',',I7,',',F6.2, ',',F6.2)
end if
end do INNER DO LOOP2
end do INNER DO LOOP1
end do FIRST DO LOOP
close (3)
close (4)
!
! Info message
!
w=200
h=20
ans=winio@('%sz&',w,h)
ans=winio@('%ca%bf%fn[Arial][Program TXT_PRE_SGF - Info]&')
ans=winio@('%3nl%ta%sfReformatting done!%2nl %cn%9^bt[&Finish]','OK')
return
end subroutine |
|
Back to top |
|
|
Martin_K
Joined: 09 Apr 2020 Posts: 227
|
Posted: Tue Apr 14, 2020 10:55 am Post subject: |
|
|
Many thanks wahorger, I will try your approach! |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2391 Location: Yateley, Hants, UK
|
Posted: Thu Apr 16, 2020 12:12 am Post subject: |
|
|
Martin,
I answered your original post with the error.
Eddie |
|
Back to top |
|
|
Martin_K
Joined: 09 Apr 2020 Posts: 227
|
Posted: Thu Apr 16, 2020 9:37 pm Post subject: |
|
|
Hello wahorger,
Your approach (code) for a progress bar with percentage is perfectly universal and I thank you for it once again!
But, I still need some advise from you. I tried to implement your approach and have the following two (minor) questions and 2 essential questions:
NO-ESSENTIAL:
1. I noticed in your code that there is a declaration to an external function as follows: INTEGER, EXERNAL:: buttton_refresh
However, there is no such function declared, so I removed it. Is it OK?
2. There is also the variable IFILL declared (as INTEGER*4) which is connected with parameter declaration of cold_width=20 and later in the code, in the section CASE DEFAULT is ifill used in the assignment
IFILL=FILL*DBLE(col_width). But the value of IFILL is nowhere used in the code. What�s was the intention or meaning for it? (I removed it from the code, since I got compilation warning that IFILL is declared, but never used).
And now, two ESSENTIAL questions which are - in fact - my problems:
A) Despite the use the TOPMOST declaration in the code of your subroutine for %WW format code in the section CASE (0), when I specify the three required variables in my main program (variable1 - input file, variable2 - output file, variable3 - change or no change of the signs for DX, DY values)
my main program window remains active and the status/progress bar window does NOT appear as active window (is hidden and it seems as if nothing would be done). It appears ONLY then, when I kill my main window (which is unwanted). Where could be an error in my main program? Compiling and linking is OK.
B) The MOST important question (however, it can be irrelevant and can disappear, when question A will be solved):
When I kill my main window (after specifying of all three variables) to see the progress bar, ONLY CASE (0) is carried out and then I get the following run-time error: ERROR 112: Reference to undefined variable, array element or function result (/UNDEF).
And below the ERROR message is specified exactly the following:
STATUS_BAR_WINDOWS (in file ProgresBar.f95 at line 109 [+0339]
MAIN - in file (main.f95) at 291 [+0f4a]
The line 291 of my main program is as follows:
call status_bar_windows(' ',1,I_Pocet_X,i)
where I_Pocet_X is the upper limit of the main DO loop (which still has 2 nested DO loops) and was detected (the value I_Pocet_X) after reading whole input file. The status bar subroutine is called from the outer DO loop, immediately after the statement declared above.
The line 109 of the status_bar_windows subroutine is as follows:
if(fill_this-fill_last.le.1.d0) return
Do you have any idea what could be wrong?
REMARK: In the main program I use the function call ENABLE_UTF8@(1) and saved the whole source code file as Unicode(UFT-8 without signature) - Codepage 65001. In the subroutine I use the same function, but the source code file is saved as ASCII.
Many thanks in advance for your tips!
Martin |
|
Back to top |
|
|
wahorger
Joined: 13 Oct 2014 Posts: 1217 Location: Morrison, CO, USA
|
Posted: Fri Apr 17, 2020 4:00 am Post subject: |
|
|
Martin, thanks for the reply. This code has gone through some major revisions/tweaks and as such has some "fluff" left over. I'll answer your questions below
1. Yes, you can remove that. The function used to have a button you could press to cancel, but I found that was not prudent, nor needed for my needs.
2. The IFILL and column width help define the status bar length and the amount of the length that it consumes for a generic status bar that has no defined end point. Just a bar that appears and gets filled and cleared as the program progresses to give the user the idea that it is, indeed running. Again "fluff" left over from development.
BTW, thanks for pointing this fluff out.
Line 109 is the check to make sure at least 1 second has elapsed since the "marker" time. Once this interval has past, then a new marker is set with the current time, and the next call, this new marker is used to make sure at least 1 second has passsed.
Since this code requires variables set in one call to be used in another, it should be compiled with /SAVE option, or every variable needs the SAVE attribute set.
To get a variable to update in a window from the results of a running process, you'll need to call window_update@(xxxx) where xxxx is the name of the variable you wish to refresh. But, don't do this for EVERY trip through the loop unless each iteration takes at least 0.25 seconds. The window_update@() call can consume a lot of CPU resource, so use it sparingly.
Can you post your code again, or put it on DropBox (or other cloud service) and post a link here that I can download the code and take a look at why this might be having trouble at run-time? |
|
Back to top |
|
|
Martin_K
Joined: 09 Apr 2020 Posts: 227
|
Posted: Fri Apr 17, 2020 10:18 pm Post subject: |
|
|
Thanks for your answers, I will send you the code |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2391 Location: Yateley, Hants, UK
|
Posted: Sun Apr 19, 2020 7:22 pm Post subject: |
|
|
Martin,
I have some words of advice. If you invent a new way or organising the various operations like opening files in a Windows application, then you will have to face two problems. The first is that preparing your user manual and Help files will grow from a big job into a huge job. The second is that your users (who already know how to run Windows apps will hate you. This also applies if you are the only user!
The normal way to start the selection process for an existing datafile is a submenu �Open�� in the �File� menu. It is also common to have a toolbar button for it, but users will always look for the menu item. The three dots mean that selecting �Open�� leads the user on to further dialogs. �File|New��, �File|Save� and �File|Save As�� are only needed if you create and edit your datafile in your application.
My second bit of advice is to use only a few Clearwin+ format codes in any one WINIO@ call. It makes it much easier to see what is going on, and also easier to add or subtract things.
If you need to show the name of the input file continuously, then the right place to do it is in a status bar. Some apps do it in the caption bar. The same applies to an output file.
Have you thought about making your output file have the same basic name as the input file, just with the extension changed? This could cut down on one thing the user has to do. However, before you write you should do a check whether the file already exists and if it does, ask the user if they want to overwrite it.
Your third selection box really belongs in a dialog that you get to in a �Settings� or �Options� menu. You can always display the current option in the status bar.
Eddie |
|
Back to top |
|
|
Martin_K
Joined: 09 Apr 2020 Posts: 227
|
Posted: Mon Apr 20, 2020 10:07 am Post subject: |
|
|
Many thanks Eddie! I will take your advises into account! |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|