Updating Dialog text continuosly

Updating Dialog text continuosly

Am currently using Digital Version (soon to upgrade to Compaq). Trying to get a modeless or modal dialog box to update continuously (like a timer). Currently it only shows the last value in the edit box when I hit the apply button. I want to use the dialog box for a realtime data display for a simulation. The function dlgflush is not available in my version (looks like what I might need). How do I get the edit box to update whenever I change the control?

  win32fortran.f90 
!
!  FUNCTIONS:
!	WinMain()      - Entry point for the application; 
!                    displays the main window; processes the message loop
!	win32fortranSub()  - Callback routine for the main dialog box
!	win32fortranApply()- Callback routine for the APPLY button
!

!****************************************************************************
!
!  FUNCTION: WinMain( hInstance, hPrevInstance, lpszCmdLine, nCmdShow )
!
!  PURPOSE:  Entry point for the application
!
!  COMMENTS: Displays the main window and processes the message loop
!
!****************************************************************************

integer*4 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 dfwin
	use dflogm
	use win32fortranGlobals

	implicit none

	integer*4 hInstance
	integer*4 hPrevInstance
	integer*4 lpszCmdLine
	integer*4 nCmdShow

	include 'resource.fd'

	external win32fortranSub
	external win32fortranApply

	! Variables
	type (dialog)			dlg
	type (T_MSG)            mesg
	integer*4			    ret
	logical*4				lret


	ghInstance = hInstance
	ghModule = GetModuleHandle(NULL)

	lret = DlgInit(IDD_WIN32FORTRAN_DIALOG, dlg)
	lret = DlgSetSub(dlg, IDD_WIN32FORTRAN_DIALOG, win32fortranSub)
	lret = DlgSetSub(dlg, IDM_APPLY, win32fortranApply)
	lret = DlgSet(dlg, IDC_EDIT1, "TEST TEXT")
     
	lret = DlgModeless(dlg,nCmdShow)

	! Read and process messsages
 	do while( GetMessage (mesg, NULL, 0, 0) ) 
 	   if ( DlgIsDlgMessage(mesg) .EQV. .FALSE. ) then
 		   lret = TranslateMessage( mesg )
 		   ret  = DispatchMessage( mesg )
 	   end if
	   
 	end do
	call DlgUninit(dlg)

	WinMain = mesg.wParam
	return

99999 &

	ret = MessageBox(ghwndMain, "Error initializing application win32fortran"C, &
					 "Error"C, MB_OK)
	WinMain = 0

end 

!****************************************************************************
!
!  FUNCTION: win32fortranSub ( dlg, id, callbacktype )
!
!  PURPOSE:  Dialog box callback for initialization and destroy
!
!  COMMENTS:
!
!****************************************************************************

SUBROUTINE win32fortranSub( dlg, id, callbacktype )

  use dfwin
  use dflogm

  implicit none

  type (dialog) dlg
  integer id, callbacktype

  if (callbacktype == dlg_destroy) then
	call PostQuitMessage(0)
  endif

  END SUBROUTINE win32fortranSub

!****************************************************************************
!
!  FUNCTION: win32fortranApply ( dlg, id, callbacktype )
!
!  PURPOSE:  Dialog box callback for APPLY button
!
!  COMMENTS:
!
!****************************************************************************

SUBROUTINE win32fortranApply( dlg, id, callbacktype )

  use dflogm
  use dflib
  use dfwin

  implicit none
  include 'resource.fd'

  type (dialog) dlg
  integer id, callbacktype,i
  character*5 mychar
  logical*4				lret

  if (callbacktype == dlg_
clicked) then
	! TO DO; Add your APPLY logic here

	do 100 i = 1,10
	    write(mychar,"(i5)") i
		lret = DlgSet(dlg, IDC_EDIT1, mychar)
		
		call SLEEPQQ(250)


100 continue

  endif

  END SUBROUTINE win32fortranApply

  


4 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Hmm, there's more in the topic than meets the eye. First, have in mind that an application is single-threaded unless you tell otherwise; that means that it cannot SLEEPQQ and update any screen contents at the same time. As it is now, GUI part of your app will be stone-dead as long as APPLY loop is in progress.

Depending on nature of your data source, I'd recommend you examining two samples from my home page:

1) If your "apply" logic is heavy computing which updates the edit box from time to time, take a look at ThreadDlg sample. Briefly, the GUI spawns a "worker" thread which works its business and can update dialog contents from time to time. The sample actually does not contain communication from the worker to GUI thread, but it would be trivial to insert a DlgSet (or SetDlgItemText) somewhere in the main worker loop. This is a trivial example of "notify" logic -- "Server" thread (which does the job) "notifies" "client thread" that it has done something.

2) If your "apply" logic is just querying for data at certain rate, take a look at XFLOGM sample app. It does not use threads, but creates a timer which triggers every n millseconds and then the timer callback does some job and updates dialog contents. This is an example of "polling" logic. Note that the app can be single threaded in this case, because timer message can be processed (quickly) when the application is idle; that isn't applicable in cases of heavy computing.

Jugoslav

Jugoslav
www.xeffort.com

Thanks for the reply. I'm still having a problem - must be missing something simple. Using your ThreadDlg example, I added a line after the write to the screen to update an edit box that I placed in the dialog. Still to no avail. Through the common block, if I place an update in the OnStop routine, I get the correct (last) value in the edit box, so I know the values are being communicated correctly. Do I need some type of other event in the worker thread?

PROGRAM ThreadDlg

USE DFLOGM

IMPLICIT NONE

INTEGER::         iDummy
TYPE (DIALOG)::   Dlg
EXTERNAL          OnRun, OnStop 

INCLUDE "Resource.fd"

iDummy=DlgInit(IDD_DIALOG1, Dlg)

iDummy=DlgSetSub(Dlg, IDC_BUTTON_RUN, OnRun)
iDummy=DlgSetSub(Dlg, IDC_BUTTON_STOP, OnStop)

iDummy=DlgModal(Dlg)

END PROGRAM

!------------------------------------------------------

SUBROUTINE OnRun(Dlg, ID, iAction)
USE DFWIN
USE DFLOGM
IMPLICIT NONE

INCLUDE "Resource.fd"



TYPE(Dialog):: Dlg
INTEGER::      ID, iAction, idThread, hEvent, hThread, iDummy
TYPE (T_SECURITY_ATTRIBUTES),POINTER::   NULL_SA

COMMON/Thread/ hThread
COMMON/myval/ival
integer ival,i
character*8 cval

INTERFACE
    INTEGER(4) FUNCTION mainsub(hEvent)
    !DEC$ATTRIBUTES STDCALL:: mainsub
    INTEGER hEvent
    END FUNCTION
END INTERFACE

!This is Windows Event object used for simplest interthread/
!interprocess communication. It can only have TRUE and FALSE
!state.
hEvent = CreateEvent(NULL_SA, .FALSE., .FALSE., "MyEvent"C)
!Here, we start mainsub, but in a new thread
hThread = CreateThread(NULL_SA, 0, LOC(mainsub), hEvent, 0, LOC(idThread))

! Disable 'Run' Button so that another calculation cannot be
! concurrently started
iDummy = DlgSet(Dlg, ID, .FALSE., DLG_ENABLE)




END SUBROUTINE OnRun
!------------------------------------------------------
SUBROUTINE OnStop(Dlg, ID, iAction)

USE DFWIN
USE DFLOGM

IMPLICIT NONE

TYPE(Dialog):: Dlg
INTEGER::      ID, iAction, idThread, hEvent, hThread, iDummy
CHARACTER*6 cval

COMMON/Thread/ hThread
COMMON/myval/ival
integer ival

INCLUDE "Resource.fd"

hEvent = OpenEvent(EVENT_ALL_ACCESS, .FALSE., "MyEvent"C)

!Setting event (raising its state to TRUE) will cause
!the thread to exit when first testing event state
iDummy = SetEvent(hEvent)

!Disable "Stop" button while terminating thread
iDummy = DlgSet(Dlg, ID, .FALSE., DLG_ENABLE)

iDummy = WaitForSingleObject(hThread, 500)
IF (iDummy.EQ.WAIT_TIMEOUT) THEN
     !Thread didn't exit within 0.5s , kill it (_DANGEROUS_)
     iDummy = TerminateThread(hThread, 0)
END IF

!Reenable buttons
iDummy = DlgSet(Dlg, IDC_BUTTON_RUN, .TRUE., DLG_ENABLE)
iDummy = DlgSet(Dlg, ID, .TRUE., DLG_ENABLE)
!write(cval,"(i5)") ival
!iDummy = DlgSet(Dlg, IDC_EDIT1, cval)
iDummy = CloseHandle(hEvent)

END SUBROUTINE OnStop
!------------------------------------------------------
!Finally, you'll have to redesign your mainsub so that it 
!looks like this. It _mustn't_ have more than one argument.
!------------------------------------------------------
INTEGER(4) FUNCTION mainsub(hEvent)
!DEC$ATTRIBUTES STDCALL:: mainsub
USE DFLIB
USE DFLOGM
USE DFWIN
INCLUDE "Resource.fd"
TYPE(Dialog):: Dlg

COMMON/myval/ival
integer ival,idummy
character*8 cval

INTEGER:: hEvent, i
!------------------------------------------------------
!then, you'll have to test whether hEvent is signalled
!every while in the routine. If there's main iterative
!loop(s), putting it there would be OK. Note that
!thread can't be terminated at any time - it has to 
!"cooperate".
!---
---------------------------------------------------

DO i=1,2000
   CALL SLEEPQQ(50)
   WRITE(*,*) i
   ival = i
   write(cval,"(I5)") i
   idummy = DlgSet(Dlg,IDC_EDIT1,cval)
   IF (IsCancelSignalled(hEvent).EQ.1) THEN
      mainsub=0
      RETURN
   END IF
END DO

mainsub=1

END FUNCTION mainsub
!------------------------------------------------------
!It's usually a good idea to wrap some system-specific 
!code in a separate routine. In this way you 
INTEGER(4) FUNCTION IsCancelSignalled(hEvent)
USE DFWIN

INTEGER:: hEvent

IF (WaitForSingleObject(hEvent, 0).EQ.WAIT_OBJECT_0) THEN
      IsCancelSignalled=1
ELSE
      IsCancelSignalled=0
END IF

END FUNCTION IsCancelSignalled

You have another Dlg variable which is local to the mainsub -- thus your DlgSet call goes nowhere. You have to make Dlg global via a MODULE or COMMON.

Jugoslav
www.xeffort.com

Leave a Comment

Please sign in to add a comment. Not a member? Join today