- 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