Announcement

Collapse
No announcement yet.

Loosing control on Dialog Window

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Loosing control on Dialog Window

    In the program I am writing there is a function call by a callback function that lasts several minutes.
    During processing the Dialog Window is constantly updated, but if I move the window I miss the window refresh.

    Code:
    #PBFORMS CREATED V1.51
    
    #COMPILE EXE
    #DIM ALL
    
    '------------------------------------------------------------------------------
    '   ** Includes **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN INCLUDES
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    #INCLUDE "PBForms.INC"
    #PBFORMS END INCLUDES
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Constants **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN CONSTANTS
    %IDD_DIALOG1 =  101
    %IDC_BUTTON1 = 1001
    %IDC_LABEL1  = 1002
    %IDC_LABEL2  = 1003
    #PBFORMS END CONSTANTS
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Declarations **
    '------------------------------------------------------------------------------
    DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
    DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    #PBFORMS DECLARATIONS
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Main Application Entry Point **
    '------------------------------------------------------------------------------
    FUNCTION PBMAIN()
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** CallBacks **
    '------------------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
                ' Initialization handler
    
            CASE %WM_NCACTIVATE
                STATIC hWndSaveFocus AS DWORD
                IF ISFALSE CBWPARAM THEN
                    ' Save control focus
                    hWndSaveFocus = GetFocus()
                ELSEIF hWndSaveFocus THEN
                    ' Restore control focus
                    SetFocus(hWndSaveFocus)
                    hWndSaveFocus = 0
                END IF
    
            CASE %WM_COMMAND
                ' Process control notifications
                SELECT CASE AS LONG CBCTL
                    CASE %IDC_BUTTON1
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            CALL funct(CBHNDL)
                        END IF
                END SELECT
        END SELECT
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Dialogs **
    '------------------------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
    
    #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
        LOCAL hDlg   AS DWORD
        LOCAL hFont1 AS DWORD
    
        DIALOG NEW hParent, "Dialog1", 198, 154, 155, 45, %WS_POPUP OR %WS_BORDER _
            OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
            %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR _
            %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT _
            OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
        CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "CallFunction", 5, 5, 145, 20
        CONTROL ADD LABEL,  hDlg, %IDC_LABEL1, "I'm elaborating from (sec):", 5, _
            30, 85, 10
        CONTROL ADD LABEL,  hDlg, %IDC_LABEL2, "0", 95, 30, 55, 10, %WS_CHILD OR _
            %WS_VISIBLE OR %SS_RIGHT, %WS_EX_LEFT OR %WS_EX_LTRREADING
    
        hFont1 = PBFormsMakeFont("MS Sans Serif", 8, 700, %FALSE, %FALSE, %FALSE, _
            %ANSI_CHARSET)
    
        CONTROL SEND hDlg, %IDC_LABEL2, %WM_SETFONT, hFont1, 0
    #PBFORMS END DIALOG
    
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    
    #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
        DeleteObject hFont1
    #PBFORMS END CLEANUP
    
        FUNCTION = lRslt
    END FUNCTION
    '------------------------------------------------------------------------------
    '** My Function **
    '-----------------------
    
    FUNCTION funct(BYVAL hDlg AS DWORD) AS LONG
        LOCAL StartTime, CurrentTime AS INTEGER
        LOCAL PrevTime AS STRING
        StartTime=INT(TIMER)
        DO WHILE TIMER<>0
            CONTROL GET TEXT hDlg, %IDC_LABEL2 TO PrevTime
            CurrentTime=INT(TIMER)
            IF PrevTime<>STR$(CurrentTime-StartTime) THEN
                CONTROL SET TEXT hDlg, %IDC_LABEL2, STR$(CurrentTime-StartTime)
            END IF
        WEND
    END FUNCTION

  • #2
    When your dialog is processes a message (in this CASE WM_COMMAND/ IDC_BUTTON1), it is not going to process any more messages until it finishes processing the current message; this includes all the messages which result in the screen being refreshed when moved or something moves over it.

    In your case, your screen will not refresh until the called function 'Funct' completes.

    So.. you need to run 'Funct' in a separate thread of execution.

    Demo here (includes 'abort' option) :
    GUI + Worker Thread + Abort Demo

    MCM
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      BTW, I sure hope 'Funct' is only for demonstration/learning purposes, because there are many better ways to handle waiting for a time certain or an interval. (Waiting in a loop like this just eats up CPU).

      But first, you need to get your multiple-thread-of-execution working, so we'll save the "waiting" for later.
      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #4
        Here is one method:

        Code:
        #PBFORMS CREATED V1.51
        #COMPILE EXE
        #DIM ALL
        '------------------------------------------------------------------------------
        '   ** Includes **
        '------------------------------------------------------------------------------
        #PBFORMS BEGIN INCLUDES
        #IF NOT %DEF(%WINAPI)
            #INCLUDE "WIN32API.INC"
        #ENDIF
        #INCLUDE "PBForms.INC"
        #PBFORMS END INCLUDES
        '------------------------------------------------------------------------------
        '------------------------------------------------------------------------------
        '   ** Constants **
        '------------------------------------------------------------------------------
        #PBFORMS BEGIN CONSTANTS
        %IDD_DIALOG1 =  101
        %IDC_BUTTON1 = 1001
        %IDC_LABEL1  = 1002
        %IDC_LABEL2  = 1003
        #PBFORMS END CONSTANTS
        '------------------------------------------------------------------------------
        '------------------------------------------------------------------------------
        '   ** Declarations **
        '------------------------------------------------------------------------------
        DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
        DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        #PBFORMS DECLARATIONS
        '------------------------------------------------------------------------------
        '------------------------------------------------------------------------------
        '   ** Main Application Entry Point **
        '------------------------------------------------------------------------------
        '
        GLOBAL App_ExitApp&
        FUNCTION PBMAIN()
            LOCAL CT&
            App_ExitApp&=0
            ' change dialog to modeless (you don't want modal)
            ShowDIALOG1 %HWND_DESKTOP
            DO
                 DIALOG DOEVENTS TO CT&
            LOOP UNTIL CT&=0
        END FUNCTION
        '------------------------------------------------------------------------------
        '------------------------------------------------------------------------------
        '   ** CallBacks **
        '------------------------------------------------------------------------------
        CALLBACK FUNCTION ShowDIALOG1Proc()
            SELECT CASE AS LONG CBMSG
                CASE %WM_INITDIALOG
                    ' Initialization handler
                CASE %WM_NCACTIVATE
                    STATIC hWndSaveFocus AS DWORD
                    IF ISFALSE CBWPARAM THEN
                        ' Save control focus
                        hWndSaveFocus = GetFocus()
                    ELSEIF hWndSaveFocus THEN
                        ' Restore control focus
                        SetFocus(hWndSaveFocus)
                        hWndSaveFocus = 0
                    END IF
                CASE %WM_SYSCOMMAND
                    IF (CBWPARAM AND &HFFF0)=%SC_CLOSE THEN
                         IF App_ExitApp&=1 THEN
                              BEEP
                              App_ExitApp&=2
                              SetWindowLong CBHNDL, %DWL_MSGRESULT,0
                              FUNCTION=1   ' prevent close
                              EXIT FUNCTION
                         END IF
                    END IF
                CASE %WM_COMMAND
                    ' Process control notifications
                    SELECT CASE AS LONG CBCTL
                        CASE %IDC_BUTTON1
                            IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                CONTROL DISABLE CBHNDL,%IDC_BUTTON1
                                CALL funct(CBHNDL)
                                CONTROL ENABLE CBHNDL,%IDC_BUTTON1
                            END IF
                    END SELECT
            END SELECT
        END FUNCTION
        '------------------------------------------------------------------------------
        '------------------------------------------------------------------------------
        '   ** Dialogs **
        '------------------------------------------------------------------------------
        FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
            LOCAL hDlg   AS DWORD
            LOCAL hFont1 AS DWORD
            DIALOG NEW hParent, "Dialog1", 198, 154, 155, 45, %WS_POPUP OR %WS_BORDER _
                OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
                %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR _
                %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT _
                OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
            CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "CallFunction", 5, 5, 145, 20
            CONTROL ADD LABEL,  hDlg, %IDC_LABEL1, "I'm elaborating from (sec):", 5, _
                30, 85, 10
            CONTROL ADD LABEL,  hDlg, %IDC_LABEL2, "0", 95, 30, 55, 10, %WS_CHILD OR _
                %WS_VISIBLE OR %SS_RIGHT, %WS_EX_LEFT OR %WS_EX_LTRREADING
            hFont1 = PBFormsMakeFont("MS Sans Serif", 8, 700, %FALSE, %FALSE, %FALSE, _
                %ANSI_CHARSET)
            CONTROL SEND hDlg, %IDC_LABEL2, %WM_SETFONT, hFont1, 0
        #PBFORMS END DIALOG
            DIALOG SHOW MODELESS hDlg, CALL ShowDIALOG1Proc
        #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
            DeleteObject hFont1
        #PBFORMS END CLEANUP
            FUNCTION = 1
        END FUNCTION
        '------------------------------------------------------------------------------
        '** My Function **
        '-----------------------
        FUNCTION funct(BYVAL hDlg AS DWORD) AS LONG
            LOCAL StartTime, CurrentTime AS INTEGER
            LOCAL CT&, LP&
            LOCAL PrevTime AS STRING
            App_ExitApp&=1
            StartTime=INT(TIMER)
            DO WHILE TIMER<>0
                CONTROL GET TEXT hDlg, %IDC_LABEL2 TO PrevTime
                CurrentTime=INT(TIMER)
                IF PrevTime<>STR$(CurrentTime-StartTime) THEN
                    CONTROL SET TEXT hDlg, %IDC_LABEL2, STR$(CurrentTime-StartTime)
                    ' must add exit to routine
                    CT&=CT&+1
                    IF CT&=30 THEN EXIT DO
                END IF
                LP&=LP&+1
                IF LP&=10 THEN
                     ' periodically call doevents
                     DIALOG DOEVENTS 1
                     LP&=0
                END IF
                IF App_ExitApp&=2 THEN EXIT DO
            WEND
            App_ExitApp&=0
            CONTROL SET TEXT hDlg, %IDC_LABEL2, "Done!"
        END FUNCTION
        Chris Boss
        Computer Workshop
        Developer of "EZGUI"
        http://cwsof.com
        http://twitter.com/EZGUIProGuy

        Comment


        • #5
          > periodically call doevents

          No style points for you today.

          MCM
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            I am trying to understand the functioning of THREAD, but I have a problem with the command "WaitForSingleObject.
            I changed the above example to make it work as THREAD.
            I was expecting to come "WaitForSingleObject", the main program will stop, and THREAD continued to update the window indefinitely; instead the program crashes.

            Code:
            #PBFORMS CREATED V1.51
            
            #COMPILE EXE
            #DIM ALL
            
            '------------------------------------------------------------------------------
            '   ** Includes **
            '------------------------------------------------------------------------------
            #PBFORMS BEGIN INCLUDES
            #IF NOT %DEF(%WINAPI)
                #INCLUDE "WIN32API.INC"
            #ENDIF
            #INCLUDE "PBForms.INC"
            #PBFORMS END INCLUDES
            '------------------------------------------------------------------------------
            
            '------------------------------------------------------------------------------
            '   ** Constants **
            '------------------------------------------------------------------------------
            #PBFORMS BEGIN CONSTANTS
            %IDD_DIALOG1 =  101
            %IDC_BUTTON1 = 1001
            %IDC_LABEL1  = 1002
            %IDC_LABEL2  = 1003
            #PBFORMS END CONSTANTS
            '------------------------------------------------------------------------------
            
            '------------------------------------------------------------------------------
            '   ** Declarations **
            '------------------------------------------------------------------------------
            
            DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
            DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
            #PBFORMS DECLARATIONS
            '------------------------------------------------------------------------------
            
            '------------------------------------------------------------------------------
            '   ** Main Application Entry Point **
            '------------------------------------------------------------------------------
            FUNCTION PBMAIN()
                ShowDIALOG1 %HWND_DESKTOP
            END FUNCTION
            '------------------------------------------------------------------------------
            
            '------------------------------------------------------------------------------
            '   ** CallBacks **
            '------------------------------------------------------------------------------
            CALLBACK FUNCTION ShowDIALOG1Proc()
                LOCAL hThread AS DWORD
                LOCAL iret AS DWORD
                SELECT CASE AS LONG CBMSG
                    CASE %WM_INITDIALOG
                        ' Initialization handler
            
                    CASE %WM_NCACTIVATE
                        STATIC hWndSaveFocus AS DWORD
                        IF ISFALSE CBWPARAM THEN
                            ' Save control focus
                            hWndSaveFocus = GetFocus()
                        ELSEIF hWndSaveFocus THEN
                            ' Restore control focus
                            SetFocus(hWndSaveFocus)
                            hWndSaveFocus = 0
                        END IF
            
                    CASE %WM_COMMAND
                        ' Process control notifications
                        SELECT CASE AS LONG CBCTL
                            CASE %IDC_BUTTON1
                                IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                    THREAD CREATE funct(CBHNDL) SUSPEND TO hThread
                                    SetThreadPriority  hThread, %THREAD_PRIORITY_BELOW_NORMAL
                                    THREAD RESUME hThread  TO iRet
            
            'now wait that "funct" make all its job?
                                    WaitForSingleObject hThread, %INFINITE
            
                                END IF
                        END SELECT
                END SELECT
            END FUNCTION
            '------------------------------------------------------------------------------
            
            '------------------------------------------------------------------------------
            '   ** Dialogs **
            '------------------------------------------------------------------------------
            FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                LOCAL lRslt AS LONG
            
            #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
                LOCAL hDlg   AS DWORD
                LOCAL hFont1 AS DWORD
            
                DIALOG NEW hParent, "Dialog1", 198, 154, 155, 45, %WS_POPUP OR %WS_BORDER _
                    OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
                    %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR _
                    %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT _
                    OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
                CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "CallFunction", 5, 5, 145, 20
                CONTROL ADD LABEL,  hDlg, %IDC_LABEL1, "I'm elaborating from (sec):", 5, _
                    30, 85, 10
                CONTROL ADD LABEL,  hDlg, %IDC_LABEL2, "0", 95, 30, 55, 10, %WS_CHILD OR _
                    %WS_VISIBLE OR %SS_RIGHT, %WS_EX_LEFT OR %WS_EX_LTRREADING
            
                hFont1 = PBFormsMakeFont("MS Sans Serif", 8, 700, %FALSE, %FALSE, %FALSE, _
                    %ANSI_CHARSET)
            
                CONTROL SEND hDlg, %IDC_LABEL2, %WM_SETFONT, hFont1, 0
            #PBFORMS END DIALOG
            
                DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
            
            #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
                DeleteObject hFont1
            #PBFORMS END CLEANUP
            
                FUNCTION = lRslt
            END FUNCTION
            '------------------------------------------------------------------------------
            '** My Function **
            '-----------------------
            
            FUNCTION funct(BYVAL hDlg AS DWORD) AS LONG
                LOCAL StartTime, CurrentTime AS INTEGER
                LOCAL PrevTime AS STRING
                StartTime=INT(TIMER)
                DO WHILE TIMER<>0
                    CONTROL GET TEXT hDlg, %IDC_LABEL2 TO PrevTime
                    CurrentTime=INT(TIMER)
                    IF PrevTime<>STR$(CurrentTime-StartTime) THEN
                        CONTROL SET TEXT hDlg, %IDC_LABEL2, STR$(CurrentTime-StartTime)
                    END IF
                WEND
            END FUNCTION

            Comment


            • #7
              Code:
              'now wait that "funct" make all its job?
                                      WaitForSingleObject hThread, %INFINITE
              No, you don't want to wait on the thread object there; that's the same as just calling 'FUNCT" directly. In the demo, the program waits on a 'READY' event handle at this point (hEventReady), not the thread handle.

              The wait on the ready event is to allow the thread function to copy its parameters to its local variables before returning to the calling thread. This 'copy' is "usually" not a big deal, but it costs nothing and is a good habit to acquire, because NOT waiting can cause you problems if you start passing LOCAL variables which go out of scope before the thread function's turn to process comes again.. the wait on the ReadyEvent ensures that your CALLBACK FUNCTION will never be exited UNTIL the parameter variables have been copied to the thread function's stack (local vars).

              MCM
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                BTW, you DO get style points today for giving it an honest try!
                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                • #9
                  Originally posted by Michael Mattias View Post
                  When your dialog is processes a message (in this CASE WM_COMMAND/ IDC_BUTTON1), it is not going to process any more messages until it finishes processing the current message; this includes all the messages which result in the screen being refreshed when moved or something moves over it.

                  In your case, your screen will not refresh until the called function 'Funct' completes.

                  So.. you need to run 'Funct' in a separate thread of execution.

                  Demo here (includes 'abort' option) :
                  GUI + Worker Thread + Abort Demo

                  MCM
                  I have tried to solve the problem with THREAD, but is not the right way to solve the main problem, process messages during the execution of a function very long.

                  By studying Win32 ® Programmer's Reference, perhaps I found a better way.
                  I need help, however, because the execution is very slow, I think there is a problem with the window handle that parameter is not properly inserted.

                  Code:
                  FUNCTION funct(BYVAL hdlg AS LONG) AS LONG
                      LOCAL StartTime, CurrentTime AS INTEGER
                      LOCAL PrevTime AS STRING
                      LOCAL heventReady   AS LONG
                      LOCAL Msg AS tagMsg
                  
                      StartTime=INT(TIMER)
                      DO WHILE TIMER<>0
                  
                  'Take message from only Dialog1?
                              GetMessage(Msg, hdlg, 0, 0)
                              
                              DispatchMessage Msg
                      
                          CONTROL GET TEXT hDlg, %IDC_LABEL2 TO PrevTime
                          CurrentTime=INT(TIMER)
                          IF PrevTime<>STR$(CurrentTime-StartTime) THEN
                              CONTROL SET TEXT hDlg, %IDC_LABEL2, STR$(CurrentTime-StartTime)
                          END IF
                      WEND
                  END FUNCTION

                  Comment


                  • #10
                    The code I posted solves your problem.

                    The DIALOG DOEVENTS command is DDT's version of GetMessage/Dispatch message, but you can control how long it waits.

                    The problem with GetMessage is that it waits until a message occurs. This means your code does not loop until a new message occurs.
                    Chris Boss
                    Computer Workshop
                    Developer of "EZGUI"
                    http://cwsof.com
                    http://twitter.com/EZGUIProGuy

                    Comment


                    • #11
                      What exactly are you trying to do?

                      Make your program wait until some time certain before it will once again accept commands?

                      Or wait until it does some real work? In both cases, with the screen refreshing?

                      In any event.. if you want your main screen refreshed WHILE YOUR DIALOG PROCEDURE IS PROCESSING A MESSAGE (i.e., executing code in that procedure), you need to either use the "DIALOG DOEVENTS" somewhere (often) in the code being executed; or do the work in another thread of execution. Lanuching a second thread of execution (THREAD CREATE) returns immediately, allowing you to exit your dialog procedure, which makes your dialog procedure ready to process the "I need to be redrawn" messages.

                      The "I need to be redrawn" messages are processed for you as a default. You "can" if you want intercept those, but there is no reason to do so here.


                      MCM
                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #12
                        Originally posted by Chris Boss View Post
                        The code I posted solves your problem.

                        The DIALOG DOEVENTS command is DDT's version of GetMessage/Dispatch message, but you can control how long it waits.

                        The problem with GetMessage is that it waits until a message occurs. This means your code does not loop until a new message occurs.
                        I understand! But is WaitMessage that suspend program execution and wait for a message?
                        If I say the truth; at this point I have to manually send a fake message every time I want to refresh the window.
                        I still have a problem in creating the message with the "MSG."

                        Code:
                        FUNCTION funct(BYVAL hdlg AS LONG) AS LONG
                            LOCAL StartTime, CurrentTime AS INTEGER
                            LOCAL PrevTime AS STRING
                            LOCAL heventReady   AS LONG
                            LOCAL lpMsg AS tagMsg
                        
                            StartTime=INT(TIMER)
                            DO WHILE TIMER<>0
                                GetMessage(lpMsg, hdlg, 0, 0)
                                DispatchMessage lpMsg
                                CONTROL GET TEXT hDlg, %IDC_LABEL2 TO PrevTime
                                CurrentTime=INT(TIMER)
                                IF PrevTime<>STR$(CurrentTime-StartTime) THEN
                                    CONTROL SET TEXT hDlg, %IDC_LABEL2, STR$(CurrentTime-StartTime)
                        
                        'How to complete this istruction?            
                        'lpMSg = MSG(          )
                        
                                    PeekMessage (lpMsg, %NULL, 0,0, %PM_NOREMOVE)
                                END IF
                            WEND
                        END FUNCTION
                        Last edited by CERRATO Roberto; 24 Apr 2008, 08:46 AM.

                        Comment


                        • #13
                          Originally posted by Michael Mattias View Post
                          What exactly are you trying to do?

                          Make your program wait until some time certain before it will once again accept commands?

                          Or wait until it does some real work? In both cases, with the screen refreshing?

                          In any event.. if you want your main screen refreshed WHILE YOUR DIALOG PROCEDURE IS PROCESSING A MESSAGE (i.e., executing code in that procedure), you need to either use the "DIALOG DOEVENTS" somewhere (often) in the code being executed; or do the work in another thread of execution. Lanuching a second thread of execution (THREAD CREATE) returns immediately, allowing you to exit your dialog procedure, which makes your dialog procedure ready to process the "I need to be redrawn" messages.

                          The "I need to be redrawn" messages are processed for you as a default. You "can" if you want intercept those, but there is no reason to do so here.


                          MCM
                          I'm trying to solve a "bug" in a program that I have already written without having to redesign all the functions to work with threads or DDT from modal to modeless.
                          The code is published just one example of how I presented the bug.

                          Comment


                          • #14
                            >But is WaitMessage that suspend program execution and wait for a message?

                            Yes.

                            The WaitMessage function yields control to other threads when a thread has no other messages in its message queue. The WaitMessage function suspends the thread and does not return until a new message is placed in the thread's message queue.
                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                            • #15
                              A point that needs to be appreciated about Windows is that an application needs to keep its message loop continually running.

                              For a window to respond to the mouse or keyboard as well as repaint itself regularly, the message loop must be running.

                              There are different ways to execute a long running task (or one that needs to execute periodically), such a using Timers, Threads, etc. But no matter what the app does the message loop (or a temporary replacement) must regularly execute to keep the windows responsive.

                              If this can not be done by the main message loop, then code must regularly use PeekMessage. The DDT form of this is the DIALOG DOEVENTS command. Using the API, the PeekMessage (and the appropriate translate calls) function is used. These allow code to test to see if any messages are pending and to have them executed, but will also return quickly if no messages are pending.

                              If you write code which does not regularly test for pending messages, then a window will appear to be unresponsive to the mouse.

                              It is also important to make sure code does not run an infinite loop without some way to exit when the app needs it, since this may force an app to stay in memory and not terminate properly.

                              It is not good to call functions that run for a long time continuously.

                              If code needs to be executed periodically, use a Timer (SetTimer API function).

                              If code needs to run continously while the app runs, then use a Thread, but make sure the thread can be forced to terminate properly when the app needs to terminate.
                              Chris Boss
                              Computer Workshop
                              Developer of "EZGUI"
                              http://cwsof.com
                              http://twitter.com/EZGUIProGuy

                              Comment


                              • #16
                                'm trying to solve a "bug" in a program that I have already written without having to redesign all the functions to work with threads or DDT from modal to modeless
                                Assuming the "bug" to which you refer is the failure of the screen to refresh when moved, I have good news and I have bad news.

                                The good news is, you don't have a programming error. ("bug").

                                That bad news is, you can put a sow in an evening dress and lipstick and call her 'Monique' but she'll still be a pig.

                                Which translates to, your design was faulty, not your coding. Slipping in a couple of "DIALOG DOEVENTS" is a cheap and dirty (I won't use the 'L-word' but by golly I am tempted) "thing to try" which may or may not solve your problem.

                                The bottom line is, if you want to do two or more things at once, you need to support two or more threads of execution. What that takes in your code I don't know but unless your code is chock-full of GLOBAL variables it's not really all that hard to do.

                                And you were sooooo close to having the multi-thread approach working... except for an honest-to-goodness "bug:" waiting on hThread instead of hEventReady, which sure looks like a transposition error when porting the demo code.

                                MCM
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #17
                                  Roberto,
                                  I've modified your code slightly - it doesn't take much to convert funct() to operate as a seperate thread..
                                  Code:
                                   
                                  #PBFORMS CREATED V1.51
                                   
                                  #COMPILE EXE
                                  #DIM ALL
                                   
                                  '------------------------------------------------------------------------------
                                  '   ** Includes **
                                  '------------------------------------------------------------------------------
                                  #PBFORMS BEGIN INCLUDES
                                  #IF NOT %DEF(%WINAPI)
                                      #INCLUDE "WIN32API.INC"
                                  #ENDIF
                                  #INCLUDE "PBForms.INC"
                                  #PBFORMS END INCLUDES
                                  '------------------------------------------------------------------------------
                                   
                                  '------------------------------------------------------------------------------
                                  '   ** Constants **
                                  '------------------------------------------------------------------------------
                                  #PBFORMS BEGIN CONSTANTS
                                  %IDD_DIALOG1 =  101
                                  %IDC_BUTTON1 = 1001
                                  %IDC_LABEL1  = 1002
                                  %IDC_LABEL2  = 1003
                                  #PBFORMS END CONSTANTS
                                  '------------------------------------------------------------------------------
                                   
                                  '------------------------------------------------------------------------------
                                  '   ** Declarations **
                                  '------------------------------------------------------------------------------
                                  DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
                                  DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                                  #PBFORMS DECLARATIONS
                                  '------------------------------------------------------------------------------
                                   
                                  '------------------------------------------------------------------------------
                                  '   ** Main Application Entry Point **
                                  '------------------------------------------------------------------------------
                                  FUNCTION PBMAIN()
                                      ShowDIALOG1 %HWND_DESKTOP
                                  END FUNCTION
                                  '------------------------------------------------------------------------------
                                   
                                  '------------------------------------------------------------------------------
                                  '   ** CallBacks **
                                  '------------------------------------------------------------------------------
                                  CALLBACK FUNCTION ShowDIALOG1Proc()
                                   
                                      SELECT CASE AS LONG CBMSG
                                          CASE %WM_INITDIALOG
                                              ' Initialization handler
                                   
                                          CASE %WM_NCACTIVATE
                                              STATIC hWndSaveFocus AS DWORD
                                              IF ISFALSE CBWPARAM THEN
                                                  ' Save control focus
                                                  hWndSaveFocus = GetFocus()
                                              ELSEIF hWndSaveFocus THEN
                                                  ' Restore control focus
                                                  SetFocus(hWndSaveFocus)
                                                  hWndSaveFocus = 0
                                              END IF
                                   
                                          CASE %WM_COMMAND
                                              ' Process control notifications
                                              SELECT CASE AS LONG CBCTL
                                                  CASE %IDC_BUTTON1
                                                      IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                                          'CALL funct(CBHNDL)
                                   
                                                          LOCAL hThread, hRes AS LONG             ' extra variables 
                                                          Thread Create funct(CbHndl) To hThread  ' Run funct as a seperate thread
                                                          Thread Close hThread TO hRes            ' Release handle - no longer rqd -
                                                                                                  ' thread terminates itself.
                                                      END IF
                                              END SELECT
                                      END SELECT
                                  END FUNCTION
                                  '------------------------------------------------------------------------------
                                   
                                  '------------------------------------------------------------------------------
                                  '   ** Dialogs **
                                  '------------------------------------------------------------------------------
                                  FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                                      LOCAL lRslt AS LONG
                                   
                                  #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
                                      LOCAL hDlg   AS DWORD
                                      LOCAL hFont1 AS DWORD
                                   
                                      DIALOG NEW hParent, "Dialog1", 198, 154, 155, 45, %WS_POPUP OR %WS_BORDER _
                                          OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
                                          %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR _
                                          %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT _
                                          OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
                                      CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "CallFunction", 5, 5, 145, 20
                                      CONTROL ADD LABEL,  hDlg, %IDC_LABEL1, "I'm elaborating from (sec):", 5, _
                                          30, 85, 10
                                      CONTROL ADD LABEL,  hDlg, %IDC_LABEL2, "0", 95, 30, 55, 10, %WS_CHILD OR _
                                          %WS_VISIBLE OR %SS_RIGHT, %WS_EX_LEFT OR %WS_EX_LTRREADING
                                   
                                      hFont1 = PBFormsMakeFont("MS Sans Serif", 8, 700, %FALSE, %FALSE, %FALSE, _
                                          %ANSI_CHARSET)
                                   
                                      CONTROL SEND hDlg, %IDC_LABEL2, %WM_SETFONT, hFont1, 0
                                  #PBFORMS END DIALOG
                                   
                                      DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
                                   
                                  #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
                                      DeleteObject hFont1
                                  #PBFORMS END CLEANUP
                                   
                                      FUNCTION = lRslt
                                  END FUNCTION
                                  '------------------------------------------------------------------------------
                                  '** My Function **
                                  '-----------------------
                                   
                                  FUNCTION funct(BYVAL hDlg AS DWORD) AS LONG
                                      LOCAL StartTime, CurrentTime AS INTEGER
                                      LOCAL PrevTime AS String 
                                      LOCAL x AS Long                     ' var for program window dimensions
                                      StartTime=INT(TIMER)
                                      DO WHILE TIMER<>0
                                          CONTROL GET TEXT hDlg, %IDC_LABEL2 TO PrevTime
                                          CurrentTime=INT(TIMER)
                                          IF PrevTime<>STR$(CurrentTime-StartTime) THEN
                                              CONTROL SET TEXT hDlg, %IDC_LABEL2, STR$(CurrentTime-StartTime)
                                          END If 
                                   
                                          DIALOG DOEVENTS 1               ' Release time slices - dont let thread hog CPU.
                                          DIALOG GET SIZE hDlg TO x, x    ' Lets the thread loop know when the main program has ended
                                          If x = 0 Then Exit Loop         ' - avoids trips to the task manager / End Process!
                                                                          ' Thread terminates when WHILE loop exited
                                      WEND
                                  END Function
                                  Rgds, Dave

                                  Comment

                                  Working...
                                  X