Announcement

Collapse
No announcement yet.

TranslateMessage DispatchMessage problems

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

  • TranslateMessage DispatchMessage problems

    More and more lately I have been noticing functions not running (Unless I move my mouse over my program) so I came up with a test to see if I was "Just seeing things" or if what I thought was happening was really happening.

    Code:
    #COMPILE EXE
    #DIM ALL
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    %IDD_DIALOG1 =  101
    %IDC_BUTTON1 = 1001
    %IDC_LABEL1  = 1002
    DECLARE FUNCTION PBMAIN()
    DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
    DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    DECLARE FUNCTION MsgPumpApp() AS LONG
    GLOBAL hDlg  AS DWORD
    
    FUNCTION PBMAIN()
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION
    
    CALLBACK FUNCTION ShowDIALOG1Proc()
        STATIC TrackMessages AS LONG
        STATIC LastCbMsg AS LONG
        LOCAL LastCbMsgText AS STRING
        SELECT CASE AS LONG CBMSG
             SELECT CASE TrackMessages
                   CASE %FALSE
                   CASE %TRUE
                        SELECT CASE CBMSG
                             CASE LastCbMsg
                             CASE ELSE
    '                              LastCbMsg = cbmsg
    '                              LastCbMsgText = GetMsgTxt(Cbmsg)
    '                              CONTROL SET TEXT hDlg, %IDC_LABEL1, "Msg = " + LastCbMsgText
                        END SELECT
              END SELECT
        END SELECT
        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
                             TrackMessages = %TRUE
                        END IF
    
                    CASE %IDC_LABEL1
    
                END SELECT
              CASE %WM_DESTROY
                   PostQuitMessage 0'%WM_QUIT
        END SELECT
    END FUNCTION
    
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
        DIALOG NEW hParent, "Dialog1", 70, 70, 197, 59, %WS_POPUP OR %WS_BORDER _
            OR %WS_DLGFRAME OR %WS_THICKFRAME OR %WS_CAPTION OR %WS_SYSMENU OR _
            %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX 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, "Start Test", 10, 5, 75, 20
        CONTROL ADD LABEL,  hDlg, %IDC_LABEL1, "Once Started DO NOTTT move mouse " + _
            "or touch anything", 5, 35, 190, 20
        DIALOG SHOW MODELESS hDlg, CALL ShowDIALOG1Proc TO lRslt
        MsgPumpApp
        FUNCTION = lRslt
    END FUNCTION
    
    FUNCTION MsgPumpApp()AS LONG
         LOCAL tmsg AS TagMsg                              ' message information
    '*** Acquire and dispatch messages until a WM_QUIT message is received.
         WHILE GetMessage(tmsg, BYVAL %NULL, 0, 0)<> -1
              TranslateMessage tmsg
              DispatchMessage tmsg
    '          if tmsg.wParam = %WM_QUIT then exit do
         WEND
         FUNCTION = tmsg.wParam
    END FUNCTION
    
    FUNCTION GetMsgTxt(iMsgNum AS LONG) AS STRING
      SELECT CASE iMsgNum
        CASE %WM_USER:FUNCTION = "%WM_USER"
        CASE %WM_CREATE:FUNCTION = "%WM_CREATE"
        CASE %WM_DESTROY:FUNCTION = "%WM_DESTROY"
        CASE %WM_ENABLE:FUNCTION = "%WM_ENABLE"
        CASE %WM_MOVE:FUNCTION = "%WM_MOVE"
        CASE %WM_SIZE:FUNCTION = "%WM_SIZE"
        CASE %WM_ACTIVATE:FUNCTION = "%WM_ACTIVATE"
        CASE %WM_SHOWWINDOW:FUNCTION = "%WM_SHOWWINDOW"
        CASE %WM_SETFOCUS:FUNCTION = "%WM_SETFOCUS"
        CASE %WM_KILLFOCUS:FUNCTION = "%WM_KILLFOCUS"
        CASE %WM_SETREDRAW:FUNCTION = "%WM_SETREDRAW"
        CASE %WM_SETTEXT:FUNCTION = "%WM_SETTEXT"
        CASE %WM_GETTEXT:FUNCTION = "%WM_GETTEXT"
        CASE %WM_GETTEXTLENGTH:FUNCTION = "%WM_GETTEXTLENGTH"
        CASE %WM_PAINT:FUNCTION = "%WM_PAINT"
        CASE %WM_CLOSE:FUNCTION = "%WM_CLOSE"
        CASE %WM_QUERYENDSESSION:FUNCTION = "%WM_QUERYENDSESSION"
        CASE %WM_QUIT:FUNCTION = "%WM_QUIT"
        CASE %WM_QUERYOPEN:FUNCTION = "%WM_QUERYOPEN"
        CASE %WM_ERASEBKGND:FUNCTION = "%WM_ERASEBKGND"
        CASE %WM_SYSCOLORCHANGE:FUNCTION = "%WM_SYSCOLORCHANGE"
        CASE %WM_ENDSESSION:FUNCTION = "%WM_ENDSESSION"
        CASE %WM_WININICHANGE,%WM_SETTINGCHANGE:FUNCTION = "%WM_WININICHANGE,%WM_SETTINGCHANGE"
        CASE %WM_DEVMODECHANGE:FUNCTION = "%WM_DEVMODECHANGE"
        CASE %WM_ACTIVATEAPP:FUNCTION = "%WM_ACTIVATEAPP"
        CASE %WM_FONTCHANGE:FUNCTION = "%WM_FONTCHANGE"
        CASE %WM_TIMECHANGE:FUNCTION = "%WM_TIMECHANGE"
        CASE %WM_CANCELMODE:FUNCTION = "%WM_CANCELMODE"
        CASE %WM_SETCURSOR:FUNCTION = "%WM_SETCURSOR"
        CASE %WM_HELP:FUNCTION = "%WM_HELP"
        CASE %WM_MOUSEACTIVATE:FUNCTION = "%WM_MOUSEACTIVATE"
        CASE %WM_CHILDACTIVATE:FUNCTION = "%WM_CHILDACTIVATE"
        CASE %WM_QUEUESYNC:FUNCTION = "%WM_QUEUESYNC"
        CASE %WM_GETMINMAXINFO:FUNCTION = "%WM_GETMINMAXINFO"
        CASE %WM_PAINTICON:FUNCTION = "%WM_PAINTICON"
        CASE %WM_ICONERASEBKGND:FUNCTION = "%WM_ICONERASEBKGND"
        CASE %WM_NEXTDLGCTL:FUNCTION = "%WM_NEXTDLGCTL"
        CASE %WM_SPOOLERSTATUS:FUNCTION = "%WM_SPOOLERSTATUS"
        CASE %WM_DRAWITEM:FUNCTION = "%WM_DRAWITEM"
        CASE %WM_MEASUREITEM:FUNCTION = "%WM_MEASUREITEM"
        CASE %WM_DELETEITEM:FUNCTION = "%WM_DELETEITEM"
        CASE %WM_VKEYTOITEM:FUNCTION = "%WM_VKEYTOITEM"
        CASE %WM_CHARTOITEM:FUNCTION = "%WM_CHARTOITEM"
        CASE %WM_SETFONT:FUNCTION = "%WM_SETFONT"
        CASE %WM_GETFONT:FUNCTION = "%WM_GETFONT"
        CASE %WM_SETHOTKEY:FUNCTION = "%WM_SETHOTKEY"
        CASE %WM_GETHOTKEY:FUNCTION = "%WM_GETHOTKEY"
        CASE %WM_QUERYDRAGICON:FUNCTION = "%WM_QUERYDRAGICON"
        CASE %WM_COMPAREITEM:FUNCTION = "%WM_COMPAREITEM"
        CASE %WM_COMPACTING:FUNCTION = "%WM_COMPACTING"
        CASE %WM_OTHERWINDOWCREATED:FUNCTION = "%WM_OTHERWINDOWCREATED"
        CASE %WM_OTHERWINDOWDESTROYED:FUNCTION = "%WM_OTHERWINDOWDESTROYED"
        CASE %WM_COMMNOTIFY:FUNCTION = "%WM_COMMNOTIFY"
        CASE %WM_WINDOWPOSCHANGING:FUNCTION = "%WM_WINDOWPOSCHANGING"
        CASE %WM_WINDOWPOSCHANGED:FUNCTION = "%WM_WINDOWPOSCHANGED"
        CASE %WM_POWER:FUNCTION = "%WM_POWER"
        CASE %WM_COPYDATA:FUNCTION = "%WM_COPYDATA"
        CASE %WM_CANCELJOURNAL:FUNCTION = "%WM_CANCELJOURNAL"
        CASE %WM_NOTIFY:FUNCTION = "%WM_NOTIFY"
        CASE %WM_INPUTLANGUAGECHANGEREQUEST:FUNCTION = "%WM_INPUTLANGUAGECHANGEREQUEST"
        CASE %WM_INPUTLANGUAGECHANGE:FUNCTION = "%WM_INPUTLANGUAGECHANGE"
        CASE %WM_TCARD:FUNCTION = "%WM_TCARD"
        CASE %WM_USERCHANGED:FUNCTION = "%WM_USERCHANGED"
        CASE %WM_NOTIFYFORMAT:FUNCTION = "%WM_NOTIFYFORMAT"
        CASE %WM_CONTEXTMENU:FUNCTION = "%WM_CONTEXTMENU"
        CASE %WM_STYLECHANGING:FUNCTION = "%WM_STYLECHANGING"
        CASE %WM_STYLECHANGED:FUNCTION = "%WM_STYLECHANGED"
        CASE %WM_DISPLAYCHANGE:FUNCTION = "%WM_DISPLAYCHANGE"
        CASE %WM_GETICON:FUNCTION = "%WM_GETICON"
        CASE %WM_SETICON:FUNCTION = "%WM_SETICON"
        CASE %WM_NCCREATE:FUNCTION = "%WM_NCCREATE"
        CASE %WM_NCDESTROY:FUNCTION = "%WM_NCDESTROY"
        CASE %WM_NCCALCSIZE:FUNCTION = "%WM_NCCALCSIZE"
        CASE %WM_NCHITTEST:FUNCTION = "%WM_NCHITTEST"
        CASE %WM_NCPAINT:FUNCTION = "%WM_NCPAINT"
        CASE %WM_NCACTIVATE:FUNCTION = "%WM_NCACTIVATE"
        CASE %WM_GETDLGCODE:FUNCTION = "%WM_GETDLGCODE"
        CASE %WM_NCMOUSEMOVE:FUNCTION = "%WM_NCMOUSEMOVE"
        CASE %WM_NCLBUTTONDOWN:FUNCTION = "%WM_NCLBUTTONDOWN"
        CASE %WM_NCLBUTTONUP:FUNCTION = "%WM_NCLBUTTONUP"
        CASE %WM_NCLBUTTONDBLCLK:FUNCTION = "%WM_NCLBUTTONDBLCLK"
        CASE %WM_NCRBUTTONDOWN:FUNCTION = "%WM_NCRBUTTONDOWN"
        CASE %WM_NCRBUTTONUP:FUNCTION = "%WM_NCRBUTTONUP"
        CASE %WM_NCRBUTTONDBLCLK:FUNCTION = "%WM_NCRBUTTONDBLCLK"
        CASE %WM_NCMBUTTONDOWN:FUNCTION = "%WM_NCMBUTTONDOWN"
        CASE %WM_NCMBUTTONUP:FUNCTION = "%WM_NCMBUTTONUP"
        CASE %WM_NCMBUTTONDBLCLK:FUNCTION = "%WM_NCMBUTTONDBLCLK"
        CASE %WM_KEYDOWN, %WM_KEYFIRST:FUNCTION = "%WM_KEYDOWN"
        CASE %WM_KEYUP:FUNCTION = "%WM_KEYUP"
        CASE %WM_CHAR:FUNCTION = "%WM_CHAR"
        CASE %WM_DEADCHAR:FUNCTION = "%WM_DEADCHAR"
        CASE %WM_SYSKEYDOWN:FUNCTION = "%WM_SYSKEYDOWN"
        CASE %WM_SYSKEYUP:FUNCTION = "%WM_SYSKEYUP"
        CASE %WM_SYSCHAR:FUNCTION = "%WM_SYSCHAR"
        CASE %WM_SYSDEADCHAR:FUNCTION = "%WM_SYSDEADCHAR"
        CASE %WM_KEYLAST:FUNCTION = "%WM_KEYLAST"
        CASE %WM_INITDIALOG:FUNCTION = "%WM_INITDIALOG"
        CASE %WM_COMMAND:FUNCTION = "%WM_COMMAND"
        CASE %WM_SYSCOMMAND:FUNCTION = "WM_SYSCOMMAND"
        CASE %WM_TIMER:FUNCTION = "%WM_TIMER"
        CASE %WM_HSCROLL:FUNCTION = "%WM_HSCROLL"
        CASE %WM_VSCROLL:FUNCTION = "%WM_VSCROLL"
        CASE %WM_INITMENU:FUNCTION = "%WM_INITMENU"
        CASE %WM_INITMENUPOPUP:FUNCTION = "%WM_INITMENUPOPUP"
        CASE %WM_MENUSELECT:FUNCTION = "%WM_MENUSELECT"
        CASE %WM_MENUCHAR:FUNCTION = "%WM_MENUCHAR"
        CASE %WM_ENTERIDLE:FUNCTION = "%WM_ENTERIDLE"
        CASE %WM_CTLCOLORMSGBOX:FUNCTION = "%WM_CTLCOLORMSGBOX"
        CASE %WM_CTLCOLOREDIT:FUNCTION = "%WM_CTLCOLOREDIT"
        CASE %WM_CTLCOLORLISTBOX:FUNCTION = "%WM_CTLCOLORLISTBOX"
        CASE %WM_CTLCOLORBTN:FUNCTION = "%WM_CTLCOLORBTN"
        CASE %WM_CTLCOLORDLG:FUNCTION = "%WM_CTLCOLORDLG"
        CASE %WM_CTLCOLORSCROLLBAR:FUNCTION = "%WM_CTLCOLORSCROLLBAR"
        CASE %WM_CTLCOLORSTATIC:FUNCTION = "%WM_CTLCOLORSTATIC"
        CASE %WM_MOUSEMOVE,%WM_MOUSEFIRST:FUNCTION = "%WM_MOUSEMOVE"
        CASE %WM_LBUTTONDOWN:FUNCTION = "%WM_LBUTTONDOWN"
        CASE %WM_LBUTTONUP:FUNCTION = "%WM_LBUTTONUP"
        CASE %WM_LBUTTONDBLCLK:FUNCTION = "%WM_LBUTTONDBLCLK"
        CASE %WM_RBUTTONDOWN:FUNCTION = "%WM_RBUTTONDOWN"
        CASE %WM_RBUTTONUP:FUNCTION = "%WM_RBUTTONUP"
        CASE %WM_RBUTTONDBLCLK:FUNCTION = "%WM_RBUTTONDBLCLK"
        CASE %WM_MBUTTONDOWN:FUNCTION = "%WM_MBUTTONDOWN"
        CASE %WM_MBUTTONUP:FUNCTION = "%WM_MBUTTONUP"
        CASE %WM_MBUTTONDBLCLK:FUNCTION = "%WM_MBUTTONDBLCLK"
        CASE %WM_MOUSEWHEEL,%WM_MOUSELAST:FUNCTION = "%WM_MOUSEWHEEL"
        CASE %WM_PARENTNOTIFY:FUNCTION = "%WM_PARENTNOTIFY"
        CASE %WM_ENTERMENULOOP:FUNCTION = "%WM_ENTERMENULOOP"
        CASE %WM_EXITMENULOOP:FUNCTION = "%WM_EXITMENULOOP"
        CASE %WM_SIZING:FUNCTION = "%WM_SIZING"
        CASE %WM_CAPTURECHANGED:FUNCTION = "%WM_CAPTURECHANGED"
        CASE %WM_MOVING:FUNCTION = "%WM_MOVING"
        CASE %WM_POWERBROADCAST:FUNCTION = "%WM_POWERBROADCAST"
        CASE %WM_DEVICECHANGE:FUNCTION = "%WM_DEVICECHANGE"
        CASE %WM_MDICREATE:FUNCTION = "%WM_MDICREATE"
        CASE %WM_MDIDESTROY:FUNCTION = "%WM_MDIDESTROY"
        CASE %WM_MDIACTIVATE:FUNCTION = "%WM_MDIACTIVATE"
        CASE %WM_MDIRESTORE:FUNCTION = "%WM_MDIRESTORE"
        CASE %WM_MDINEXT:FUNCTION = "%WM_MDINEXT"
        CASE %WM_MDIMAXIMIZE:FUNCTION = "%WM_MDIMAXIMIZE"
        CASE %WM_MDITILE:FUNCTION = "%WM_MDITILE"
        CASE %WM_MDICASCADE:FUNCTION = "%WM_MDICASCADE"
        CASE %WM_MDIICONARRANGE:FUNCTION = "%WM_MDIICONARRANGE"
        CASE %WM_MDIGETACTIVE:FUNCTION = "%WM_MDIGETACTIVE"
        CASE %WM_MDISETMENU:FUNCTION = "%WM_MDISETMENU"
        CASE %WM_DROPFILES:FUNCTION = "%WM_DROPFILES"
        CASE %WM_MDIREFRESHMENU:FUNCTION = "%WM_MDIREFRESHMENU"
        CASE %WM_MOUSEHOVER:FUNCTION = "%WM_MOUSEHOVER"
        CASE %WM_MOUSELEAVE:FUNCTION = "%WM_MOUSELEAVE"
        CASE %WM_CUT:FUNCTION = "%WM_CUT"
        CASE %WM_COPY:FUNCTION = "%WM_COPY"
        CASE %WM_PASTE:FUNCTION = "%WM_PASTE"
        CASE %WM_CLEAR:FUNCTION = "%WM_CLEAR"
        CASE %WM_UNDO:FUNCTION = "%WM_UNDO"
        CASE %WM_RENDERFORMAT:FUNCTION = "%WM_RENDERFORMAT"
        CASE %WM_RENDERALLFORMATS:FUNCTION = "%WM_RENDERALLFORMATS"
        CASE %WM_DESTROYCLIPBOARD:FUNCTION = "%WM_DESTROYCLIPBOARD"
        CASE %WM_DRAWCLIPBOARD:FUNCTION = "%WM_DRAWCLIPBOARD"
        CASE %WM_PAINTCLIPBOARD:FUNCTION = "%WM_PAINTCLIPBOARD"
        CASE %WM_VSCROLLCLIPBOARD:FUNCTION = "%WM_VSCROLLCLIPBOARD"
        CASE %WM_SIZECLIPBOARD:FUNCTION = "%WM_SIZECLIPBOARD"
        CASE %WM_ASKCBFORMATNAME:FUNCTION = "%WM_ASKCBFORMATNAME"
        CASE %WM_CHANGECBCHAIN:FUNCTION = "%WM_CHANGECBCHAIN"
        CASE %WM_HSCROLLCLIPBOARD:FUNCTION = "%WM_HSCROLLCLIPBOARD"
        CASE %WM_QUERYNEWPALETTE:FUNCTION = "%WM_QUERYNEWPALETTE"
        CASE %WM_PALETTEISCHANGING:FUNCTION = "%WM_PALETTEISCHANGING"
        CASE %WM_PALETTECHANGED:FUNCTION = "%WM_PALETTECHANGED"
        CASE %WM_HOTKEY:FUNCTION = "%WM_HOTKEY"
        CASE %WM_PRINTCLIENT:FUNCTION = "%WM_PRINTCLIENT"
        CASE %WM_PENWINFIRST:FUNCTION = "%WM_PENWINFIRST"
        CASE %WM_PENWINLAST:FUNCTION = "%WM_PENWINLAST"
        CASE %WM_ENTERSIZEMOVE:FUNCTION = "WM_ENTERSIZEMOVE"
        CASE %WM_EXITSIZEMOVE:FUNCTION = "WM_EXITSIZEMOVE"
        CASE %WM_NULL:FUNCTION = "%WM_NULL"
        CASE ELSE:FUNCTION = "Custom Msg: " + FORMAT$(iMsgNum)
      END SELECT
    END FUNCTION
    With this code as a test, If I run in debugger (in Animation mode), then leave my mouse off the the dialog/window the loop for my msg pump stops at the end of the loop until my mouse is over the dialog/window.

    Either I am completely misunderstanding the purpose of a message pump or coded poorly in my example (as well as my real) but I can not for the life of me understand how a loop can just "STOP" until the mouse is over the Dialog/Window?????

    My real uses a thread to read a port, and display in my main program, but will not display if mouse is not over my program???? (is there a way around this??? or what am I misunderstanding???)

    I am not "Missing" messages (that I know of anyways) but more an idea that the messages stack up until the mouse is over my program. (Even though my program is the one with focus when the mouse is not over it)

    Also in the example, I am making some other fundamental mistake that when I close, the window disappears, but does not end......Is this related? or something I am missing that should be obvious???
    Engineer's Motto: If it aint broke take it apart and fix it

    "If at 1st you don't succeed... call it version 1.0"

    "Half of Programming is coding"....."The other 90% is DEBUGGING"

    "Document my code????" .... "WHYYY??? do you think they call it CODE? "

  • #2
    The purpose of the Message Pump is that when you call GetMessage, you are releasing your CPU time back to Windows unless there's a message pending for your window, in which case the function returns with the message. If there's no message, Windows does not return control to your program.
    Furcadia, an interesting online MMORPG in which you can create and program your own content.

    Comment


    • #3
      This is wrong: WHILE GetMessage(tmsg, BYVAL %NULL, 0, 0)<> -1. Must be: WHILE GetMessage(tmsg, BYVAL %NULL, 0, 0)<> 0.
      Forum: http://www.jose.it-berater.org/smfforum/index.php

      Comment


      • #4
        Your message loop code is not correct.

        First of all, since this is DDT, you should just use a DDT message loop:
        Code:
        DO 
           DIALOG DOEVENTS 
        LOOP UNTIL something_as_shown_in_help_file
        But let's just "assume" you have some good reason (which I'd really like to hear!) for using an SDK-style message loop in this program.

        GetMessage does NOT return "-1" on WM_QUIT, it returns TRUE.

        When writing a message loop for a window of one of the dialog classes, you need to (well "should" if you want it to work correctly) an IsDialogMessage() call.

        If you are using accelerators, you would also need a TranslateAccelerator() call in there.

        (a DDT "DOEVENTS" loop will handle all this for you).

        If you really want to see what messages you are getting, you can either use one of the many fine "spy-type" programs available, or you can get the message inside your CALLBACK FUNCTION....
        Code:
        CALLBACK FUNCTION  whatever 
        
               CALL LogMessageAndParams (CNHNDL, CBMSG, CBWPARAM, CBLPARAM) 
               SELECT CASE AS LONG CBMSG
                    CASE %WM_COMMAND....
        
        ...
        MCM
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          Oops. my bad...
          I have been noticing functions not running (Unless I move my mouse over my program)
          Show failing code. This is almost certainly an error in your dialog procedure which someone will be able to spot.

          oops, my real bad....

          My real uses a thread to read a port,
          Mismanagement of multiple threads is quite easy to accomplish when a GUI is involved. If a function is not executing until the mouse is moved, it really sounds like you have jimmied up some communication between the thread function and the main dialog procedure function, or have issued a blocking call without realizing it.

          "Show failing code" is even more important now.
          Last edited by Michael Mattias; 16 Mar 2009, 05:40 PM.
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            But let's just "assume" you have some good reason (which I'd really like to hear!) for using an SDK-style message loop in this program.
            For example, if you need to forward the message to an ActiveX control hosted in a container such ATL.
            Forum: http://www.jose.it-berater.org/smfforum/index.php

            Comment


            • #7
              If you really want to see what messages you are getting, you can either use one of the
              many fine "spy-type" programs available, or you can get the message inside your CALLBACK FUNCTION....
              Code:
              Code:
              CALLBACK FUNCTION  whatever 
              
                     CALL LogMessageAndParams (CNHNDL, CBMSG, CBWPARAM, CBLPARAM) 
                     SELECT CASE AS LONG CBMSG
                          CASE %WM_COMMAND....
              A spy utility will work, but code that tries to monitor the messages received by an application
              from a window procedure or DDT callback function will miss a lot of messages.
              To effectively monitor messages, one must use a combination of hooks, namely WH_CALLWNDPROC,
              WH_CALLWNDPROCRET and WH_GETMESSAGE.
              Dominic Mitchell
              Phoenix Visual Designer
              http://www.phnxthunder.com

              Comment


              • #8
                Colin brings up a good point
                The purpose of the Message Pump is that when you call GetMessage, you are releasing your CPU time back to Windows unless there's a message pending for your window, in which case the function returns with the message. If there's no message, Windows does not return control to your program.
                but that does not explain (at least in my mind why a loop "Stops" and does not loop to check if a message is for me, until there is a message there to get?????

                MCM brought up a good point with
                But let's just "assume" you have some good reason (which I'd really like to hear!) for using an SDK-style message loop in this program.

                GetMessage does NOT return "-1" on WM_QUIT, it returns TRUE.
                which makes me wonder if I am falling into the infamous trap of DDT<>SDK and not realizing it??? My initial attempt was to demo problems, not make a full blown SDK when common examples known to "Both Camps" would help me most

                That said, I did not know DDT had a message pump (outside of "Dialog Dovents" which does not handle any of the SDK like below)
                (or maybe it does)

                SDK though I would have to correct as my docs state:
                If the function retrieves a message other than WM_QUIT, the return value is nonzero.
                If the function retrieves the WM_QUIT message, the return value is zero.
                If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid window handle.
                To me would mean 0 = no message (keep looping), -1 = nvalid message (keep looping or escape depending on the error), or some non-zero and non-error (keep looping) and handle the message.

                I will have to triple check, but 0 could be no message, or %WM_QUIT (but that is a grasp at staws till I look again to be sure)

                Mismanagement of multiple threads is quite easy to accomplish when a GUI is involved. If a function is not executing until the mouse is moved, it really sounds like you have jimmied up some communication between the thread function and the main dialog procedure function, or have issued a blocking call without realizing it.
                I have been thinking about that, and if I am mixing and matching DDT vs SDK and not realizing it.

                MCM///
                "Show failing code" is even more important now.
                I thought I did??? (or at least as stripped down to demo as I could since this demo shows the same problem, no ports, no threads, just plain jane "OOOOooooops problem is deeper than what I thought???"
                (Including commented tests that I was working on in case someone could spot what I could not???)

                How much more need I post that is not "Application Specific"?????
                Engineer's Motto: If it aint broke take it apart and fix it

                "If at 1st you don't succeed... call it version 1.0"

                "Half of Programming is coding"....."The other 90% is DEBUGGING"

                "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                Comment


                • #9
                  Cliff,
                  but that does not explain (at least in my mind why a loop "Stops" and does not loop to check if a message is for me, until there is a message there to get?????
                  The name of the GetMessage function is probably causing your confusion. Intead of calling it GetMessage maybe it should have been called WaitForAMessageForMe

                  Paul.
                  Last edited by Paul Dixon; 16 Mar 2009, 07:34 PM.

                  Comment


                  • #10
                    Originally posted by Paul Dixon View Post
                    WaitForAMessageForMe
                    Or "GoToSleepUntilUserDoesSomething"
                    Furcadia, an interesting online MMORPG in which you can create and program your own content.

                    Comment


                    • #11
                      Oops, real bad. I saw the inline numeric literal "-1" and got all excited.

                      Nonetheless ...

                      As pointed out above, GetMessage returns TRUE if the message is not WM_QUIT...
                      If the function retrieves a message other than WM_QUIT, the return value is nonzero.
                      ... and minus one is its own special value ...
                      If there is an error, the return value is -1.
                      ... meaning the posted message loop....
                      Code:
                       WHILE GetMessage(tmsg, BYVAL %NULL, 0, 0)<> -1
                                TranslateMessage tmsg
                                DispatchMessage tmsg
                      '          if tmsg.wParam = %WM_QUIT then exit do
                           WEND
                      .. will loop until an error occurs... Which won't happen, because about the only way to get an error on GetMessage is to pass an invalid hWnd... but this loop is not passing an hWnd, it's passing NULL (meaning "give me messages for all windows owned by this thread"). (BTW, even if the commented line were not commented out, the value WM_QUIT will not be found in tMsg.wParam, it will be found in tMsg.message)

                      Ergo, the expected behavior of posted code is to run forever, doing nothing. I can think of simpler ways to code that.
                      To effectively monitor messages, one must use a combination of hooks...
                      To monitor messages sent to this dialog procedure, I think the simple approach suggested is adequate... and in context , more than adequate.

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

                      Comment


                      • #12
                        To monitor messages sent to this dialog procedure, I think the simple approach suggested is adequate...
                        and in context , more than adequate.
                        Monitoring from a dialog procedure? Yeah right. On top of that he has controls on the dialog.
                        Look at the messages he is monitoring. You seem to be ignoring the purpose of
                        the DispatchMessage function.
                        Dominic Mitchell
                        Phoenix Visual Designer
                        http://www.phnxthunder.com

                        Comment


                        • #13
                          ok so I am obviously committing a CNDS, but do not see it.
                          Can someone post a commented version of what I posted to show me the mistakes???

                          (sometimes I am a glutton for punishment, but at least I learn more from mistakes, than I do from blindly following examples not meant for the scope of the question)

                          Engineer's Motto: If it aint broke take it apart and fix it

                          "If at 1st you don't succeed... call it version 1.0"

                          "Half of Programming is coding"....."The other 90% is DEBUGGING"

                          "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                          Comment


                          • #14
                            Code:
                                DIALOG SHOW MODELESS hDlg, CALL ShowDIALOG1Proc TO lRslt
                                WHILE GetMessage(Msg, BYVAL %NULL, 0, 0) > 0
                                    ' IF ISFALSE TranslateAccelerator(hDlg, hAccel, Msg) THEN
                                        TranslateMessage Msg
                                        DispatchMessage Msg
                                    ' END IF
                                WEND
                            Because I found myself in need to rewrite something due to resource accelerators being used, ...

                            And yes, in ShowDIALOG1Proc I have:
                            Code:
                                    CASE %WM_DESTROY
                                        PostQuitMessage 0
                            The proper way would be to use a DO / LOOP and in the loop, assign the return from GetMessage to a variable and test if it's -1 in which case you do error handling and bail. Or bail if it's Zero.

                            GetMessage
                            Return Value
                            If the function retrieves a message other than WM_QUIT, the return value is nonzero.

                            If the function retrieves the WM_QUIT message, the return value is zero.

                            If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid window handle or lpMsg is an invalid pointer. To get extended error information, call GetLastError.

                            @Cliff, if you're wanting the program to be "more active", then you'd want to use a timer to periodically "interrupt" the OS and make it send a WM_TIMER message to the program.
                            Furcadia, an interesting online MMORPG in which you can create and program your own content.

                            Comment


                            • #15
                              I don't think you want to use an SDK message loop and PostQuitMessage on WM_DESTROY with a DDT dialog.

                              If using a DDT dialog, use a DDT message loop and a DIALOG END at the appropriate place.

                              Or, use "all-SDK" coding with the SDK-Style modeless dialog, in which case you need a DestroyWindow() call somewhere.. and now you WILL want a PostQuitMessage on WM_DESTROY.

                              Right now I would guess the DDT engine thinks this dialog is still alive, since it never got an END DIALOG command. However, the program is ending because after WM_QUIT WinMain runs out of stuff to do. That is, I think the destruction of the window is out of synch with the ending of the program because you have mixed and matched coding styles.

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

                              Comment


                              • #16
                                I have not caught on (yet) to the mix and matching that MCM mentioned (maybe just too intent in solution to take a step back)

                                This is what I have come up with from past code that did mix and match, although a few trouble points

                                Code:
                                     FUNCTION MsgPumpApp(WindowToPump AS LONG, ClientWindowToPump AS LONG)AS LONG
                                          ON ERROR GOTO ErrorHandler
                                          LOCAL ErrFunc AS LONG
                                          ErrFunc = %FALSE
                                          LOCAL tMsg AS TagMsg                              ' message information
                                          LOCAL hAccel AS DWORD                             'Win32Api.inc shows this as DWORD rather than Long
                                          LOCAL ErrorBuff AS ASCIIZ * %MAX_PATH
                                          LOCAL MsgBoxTxt AS STRING
                                          LOCAL MsgBoxStyle AS LONG
                                          LOCAL MsgBoxTitle AS STRING
                                          STATIC LastMsgTime AS LONG
                                          LastMsgTime = TIMER
                                     '*** Acquire and dispatch messages until a WM_QUIT message is received.
                                     '     WHILE GetMessage(tmsg, BYVAL %NULL, 0, 0)<> -1
                                          WHILE ISTRUE GetMessage(tmsg, BYVAL %NULL, 0, 0)                                'While GetMessage exists
                                '               select case GetMessage(tmsg, BYVAL %NULL, 0, 0)
                                '                    case %INVALID_VALUE                                                   'GetMessage returns -1 (%INVALID_VALUE) if an error
                                '                         ErrFunc = GetLastError
                                '                         FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %NULL, ErrFunc, %NULL, ErrorBuff, SIZEOF(ErrorBuff), BYVAL %NULL
                                '                         MsgBoxTxt = "Error in " + FUNCNAME$ + STR$(ErrFunc) + $TAB + ErrorBuff
                                '                         MsgBoxStyle = %MB_SYSTEMMODAL OR %MB_ICONERROR
                                '                         MsgBoxTitle = $AppName
                                '                         MSGBOX MsgBoxTxt, MsgBoxStyle, MsgBoxTitle
                                '                         exit loop
                                '                    case else                                                             'If Non-Zero, and not an error then resume checks
                                '*** TranslateMDISysAccel checks
                                                         SELECT CASE TranslateMDISysAccel(ClientWindowToPump, tMsg)
                                                              CASE 0                                                                'No Mdi Accelerator Keys
                                '*** TranslateAccelerator checks
                                                                   SELECT CASE TranslateAccelerator(WindowToPump, hAccel, tMsg)
                                                                        CASE 0                                                      'TranslateAccelerator returned error
                                                                             ErrFunc = GetLastError
                                                                             SELECT CASE ErrFunc
                                                                                  CASE 0                                            'Error was due to No key to translate to a hotkey
                                                                                       ErrFunc = TranslateMessage(tMsg)             'Translate virtual-key messages into character messages (Return 0 if not posted to queue)
                                                                                       ErrFunc = DispatchMessage(tMsg)              'Dispatch Msg to proper callback or procedure window (Return value varies on Message sent)
                                                                                  CASE 5                                            'Error was due to No key to translate to a hotkey
                                                                                       ErrFunc = TranslateMessage(tMsg)             'Translate virtual-key messages into character messages since Accelerator table was not created by LoadAccelerators or CreateAcceleratorTable
                                                                                       ErrFunc = DispatchMessage(tMsg)              'Dispatch Msg to proper callback or procedure window (Return value varies on Message sent)
                                '*** <--- Add Message checking routines later if needed but docs state (The return value specifies the value returned by the window procedure. Although its meaning depends on the message being dispatched, the return value generally is ignored.)
                                                                                  CASE ELSE
                                                                                       FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %NULL, ErrFunc, %NULL, ErrorBuff, SIZEOF(ErrorBuff), BYVAL %NULL
                                                                                       MsgBoxTxt = "Error in " + FUNCNAME$ + STR$(ErrFunc) + $TAB + ErrorBuff
                                                                                       MsgBoxStyle = %MB_SYSTEMMODAL OR %MB_ICONERROR
                                                                                       MsgBoxTitle = $AppName
                                                                                       MSGBOX MsgBoxTxt, MsgBoxStyle, MsgBoxTitle
                                                                             END SELECT
                                                                        CASE ELSE                                                   'TranslateAccelerator Returns TRUE           '<--- (not sure if -1 or just non-zero = TRUE in this case?
                                                                   END SELECT
                                '*** End TranslateAccelerator checks
                                                              CASE ELSE                                                             'Mdi Accelerator keys exist and are passed on to appropriate window
                                                         END SELECT
                                '*** End TranslateMDISysAccel checks
                                '               end select
                                '*** End GetMessage Checks
                                '*** Following line does not work and can not close without taskmanager
                                '               If isfalse GetMessage(tmsg, BYVAL %NULL, 0, 0) then SetTimer WindowToPump, %UpdateTimer, 1, BYVAL %NULL         'Requires %WM_TIMER event to kill timer when handled
                                '*** Issuing a timer refresh (within reason) seems to clear things up and force a refresh if mouse is not over app
                                               SELECT CASE LastMsgTime
                                                    CASE < TIMER - (1/18)         '(1/100 for NT, but chose 1/18 for earlier platforms (aka PbDoc's)
                                                         SetTimer WindowToPump, %UpdateTimer, 1, BYVAL %NULL         'Requires %WM_TIMER event to kill timer when handled
                                                         LastMsgTime = TIMER
                                                    CASE ELSE
                                               END SELECT
                                          WEND
                                          IF ErrFunc <> 0 THEN ErrFunc = %FALSE                                           'Reset ErrFunc due to no real error and escaped loop
                                '*** End Message Pump loop
                                     '     FUNCTION = tmsg                                                                 'Return Msg Structure for checks if errors
                                          FUNCTION = ErrFunc
                                          EXIT FUNCTION
                                     ErrorHandler:
                                          FUNCTION = ERR
                                     END FUNCTION
                                Commented code for errors cause their own "Lockups" but adding timer (although I do not like this solution) seems to keep the pump still pumping
                                Engineer's Motto: If it aint broke take it apart and fix it

                                "If at 1st you don't succeed... call it version 1.0"

                                "Half of Programming is coding"....."The other 90% is DEBUGGING"

                                "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                                Comment


                                • #17
                                  Cliff, you're making it too complex, a message pump only needs to be 4 lines, 6 if you're using an accelerator table loaded from a resource file. With dialogs, the only purpose of the pump is to keep the modeless dialog alive on the desktop, other wise if you're NOT using accelerator's, (loaded from a resource that is), and can use the desktop as the parent, the DDT engine works just fine as is.

                                  99% of your "calls from the OS that there's a message to be handled" will be sent to the dialog's designated callback. INCLUDING TIMER MESSAGES.

                                  DIALOG SHOW MODELESS hDlg, CALL ShowDIALOG1Proc TO lRslt

                                  If you want to monitor what calls are being made, that's the function which the messages go to.

                                  Notation, you do need at least the four main lines to have the message pump work, if you don't provide processing for the messages, the dialog don't work.
                                  Last edited by colin glenn; 23 Mar 2009, 09:10 PM.
                                  Furcadia, an interesting online MMORPG in which you can create and program your own content.

                                  Comment


                                  • #18
                                    Cliff, you're making it too complex, a message pump only needs to be 4 lines, 6 if you're using
                                    Four? Six?
                                    Code:
                                       DIALOG SHOW MODELESS hDlg, CALL ShowDIALOG1Proc TO lRslt
                                    1  DO
                                    2        DIALOG DOEVENTS TO X
                                    3  LOOP WHILE X
                                    TranslateAccelerator handled by DDT
                                    If TranslateSysMDIAccelerator is in there, this is not a DDT dialog application
                                    If modeless SDK dialog above, IsDialogMessage() missing.

                                    DDT/SDK syntax choices are radio buttons, not checkboxes.

                                    PS
                                    With dialogs, the only purpose of the pump is to keep the modeless dialog alive on the desktop
                                    I think I would have phrased this the way it is phrased in the help file:
                                    DIALOG DOEVENTS statement
                                    Purpose Process pending window or dialog messages for MODELESS dialogs....

                                    ....

                                    Restrictions
                                    The DIALOG DOEVENTS loop must run for the duration of the modeless dialog(s), or they will not respond or be redrawn correctly.
                                    Michael Mattias
                                    Tal Systems (retired)
                                    Port Washington WI USA
                                    [email protected]
                                    http://www.talsystems.com

                                    Comment

                                    Working...
                                    X