- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
3 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page