Announcement

Collapse
No announcement yet.

Message pump.

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

  • Message pump.

    I have installed the pump as per below at the very end of setting up a modeless dialog, and it appears to function. Since I am still waiting for delivery of the Petzold book, everything I do is necessarily experimental to begin with, and when it WORKS, I use it - though it may quite possibly be a bad solution, the sole criterion has to be, for the nonce, whether it works or not.

    (... code placing controls on dialog here ...)
    Dialog Show Modeless hDlg& Call hDlgProc
    End Select
    Do
    Dialog DoEvents
    Dialog Get Size hDlg& To X0&,X0&
    If X0&>0 Then FormOK$=CheckFields (ScrnName$)
    Loop Until IsFalse X0&
    End Function

    The DLL function called CheckFields refers to the parameter which tells which screen is in action, and checks whether any essential information for that screen has been omitted. If so, it returns a string listing these, otherwise it returns "OK.

    It appears to me (in my ignorance) that this "pump" pumps all the time, no matter what one does, even when just staring at the screen. Is this correct? If so, one could use this to ensure that the user does not leave the current screen before it is complete and correct. Would be quite something if this is so, and it almost seems as if it is! Excuse an old DOS programmer's
    fumbling in the dark, but any comments would be appreciated.


  • #2
    Yes, it "pumps" all the time, but if there is no message in the thread message queue, then there is very little overhead. This is how modeless dialogs and pure SDK-style applications must work. In fact, even modal dialogs have a message pump like this, but it is handled "trabsparently" by the dialog box engine.

    You can do what you like within the DIALOG DOEVENTS loop, but you should be aware that this loop *must* run if you want the modeless dialog to ba able to redraw itself (ie, if uncovered by another windows), or the dialog if moved, or... If you slow up this loop, you app may look hesitant or slow to respond to the user.

    With that in mind, you should never place code in the pump loop that validates the dialog or it's controls... that breaks the concept of the dialog callback (the window procedure of a dialog) handling all the events and message processing related directly to that dialog. For example, of you changed the dialog callback significantly but forget to "fix" the message pump loop, you stand a good chance of introducing a new bug to your code. In otherwords, your code becomes less "maintainable".

    To validate a dialog it is more usual to trap the %WM_CLOSE or %WM_SYSCOMMAND|%SC_CLOSE messages in the dialog callback (or in the handler for the OK/CLOSE/etc buttons - it depends on what your code does!).

    Petzold will fill in some of the blanks for you! Getting to grips with how Windows operates is quite a challenge at first

    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    Lance
    mailto:[email protected]

    Comment


    • #3
      Your basic splash screen example:
      Declares are not in but good enough example
      This is from my nuclear timeclock program, you can only guess what the wave that is playing is (Air alarm of nuke)..


      Code:
      Function PBMain()
      SplashScreen
      Exit function
      
      '========================<SPLASH CODE>================================
      '----------------------------------------------------------------------------------------
      Function SplashScreen() As Long
        Dialog New 0, "",,, 305,158, %WS_POPUP Or %WS_DLGFRAME  To sDlg
        Control Add Image, sDlg, -1,"#1030",1,1,305,158
        Result = PlayWavFromResource(hInstance,WAVE + "1",WAV + "01")
        Dialog Show Modal sDlg Call SplashScreen
      End Function
      
      '------------------------------------------------------------------------------
      
      CallBack Function SplashProc() As Long
        Local hInst  As Long
        Local wMsg   As Long
        Local wParam As Long
        Local lParam As Long
      
        wMsg = CbMsg
        lParam = CbLparam
        wparam = CbWparam
        hInst = hInstance
      '  MousePtr 11 'BUSY
      
        Select Case wMsg
      
          Case %WM_INITDIALOG
                SetTimer  sDlg, %IDT_TIMER1,  3500, ByVal %NULL
              Function =  0
              Exit Function
      
          Case %WM_DESTROY
               KillTimer sDlg,  %IDT_TIMER1
      
          Case %WM_TIMER
              Select Case CbWparam
                Case %IDT_TIMER1
                   MousePtr 0
                   Dialog End sDlg, 1
              End Select
      
        End Select
       End Function
      '-----------------------------------------------------------------------------------

      ------------------
      Scott
      mailto:[email protected][email protected]</A>
      Scott Turchin
      MCSE, MCP+I
      http://www.tngbbs.com
      ----------------------
      True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

      Comment


      • #4
        Scott, maybe I'm missing something... what does this have to do with a modeless dialog message pump?


        ------------------
        Lance
        PowerBASIC Support
        mailto:[email protected][email protected]</A>
        Lance
        mailto:[email protected]

        Comment


        • #5
          Thank you, Lance. If I understand rightly, this means that a "pump", looking like this --

          Do
          Dialog DoEvents
          Dialog Get Size hDlg& To X0&,X0&
          Loop Until IsFalse X0&

          -- is necessary, even though it does not appear to have any useful function. The example I posted above (with the extra line in place), is in fact the first time I do have such a pump in any dialog callback function, and even before that I encountered no problems with redraw or whatever (as far as I know!) - and this exe already compiles to close on 300K, with MANY different dialogs, though many of these share a common callback function which relies on the unique ID's of controls to differentiate. This makes it possible, on the other hand, to re-use control ID's with identical requirements and yet differentiate even then by use of a thing like the ScrnName$ which is unique per dialog on display.

          Oh, there WAS one redraw oddity: a diagram similar to the one I sent you long ago, but a more complex one (an interlocking carton as cut before folding) - the what-if changes wouldn't update the picture. I then (wait for it) added a small label to the screen, and KILLed it again immediately - and THAT fixed it! I will test now if the pump would do the job in that situation instead.

          I am equally puzzled by Scott's posting.


          ------------------

          Comment


          • #6
            The effect of creating and then destroying a child control effectively triggered a %WM_PAINT event, which in turn forced your "redraw" to occur.

            The correct way to force an update to the dialog would have been to call InvalidateRect() followed immediately by a UpdateWindow() call. You could also use the RedrawWindow() API, but it is a tad more complex then the former technique.

            Regarding the message loop questions, the following is a "general" discription of what happens below the surface of DDT's DIALOG DOEVENTS statement.

            As Petzold will explain in detail, the message pump translates and routes messages to the appropriate window procedure. When your dialog or window needs to know about something, such as a mouse click on a control, a message is placed in the application message queue (ie, %WM_COMMAND). It is possible for a whole bunch of these messages to be sent to an application, and somehow the application must be able to process them. It can't do them all at the same time, and they often must be processed in a particular order. The concept of a queue solves this little issue, enabling the application to take one message at a time, and process it accordingly.

            Generally speaking, the message loop is idle (or halted, depending on how the loop is implemented) until a message appears in the thread's message queue (or a non-queued message arrives).

            At that point the message loop code retrieves the message from the queue and "translates" it (if the message needs translating - most don't). This "translation" converts keyboard messages (WM_KEYDOWN, WM_KEYUP, etc) into %WM_CHAR messages, etc, which are required by the controls themselves. It also helps handle Tab, Enter and Escape key presses, etc.

            Finally, it dispatches the translated message to the apropriate dialog/window procedure (your callback function), for your code to process in the form of %WM_xxxx messages.

            As you can probably gather from this brief description, if the loop is not operational, then messages don't get dispatched, and the callback code is not executed. No callback execution means non-operational window(s) or dialog(s)!

            Internally, a message loop (aka DIALOG DOEVENTS) is a set of API calls (using anywhere from three to eight or more API calls). The minimum set comprises GetMessage() or PeekMessage(), TranslateMessage() and DispatchMessage(). This set of API's is often expanded to handle keyboard accelerators, tab control to shift focus, etc, using such calls as IsDialogMessage(), etc. For more information, consult the WIN32.HLP file on these api's.

            I hope this helps you gather a better understanding of the purpose of the message pump. As I said, Petzold will explain it better than I can because he spreads it out over a multitude of pages!


            ------------------
            Lance
            PowerBASIC Support
            mailto:[email protected][email protected]</A>
            Lance
            mailto:[email protected]

            Comment


            • #7
              Thanks again, Lance. I do notice that both the Petzold example (Sysmets3) and the Samples file Skeleton.bas both use the form "to be avoided" according to Win32API help:

              Quote --

              Note that the function return value can be TRUE, FALSE, or -1. Thus, you should avoid code like this:

              while (GetMessage( lpMsg, hWnd, 0, 0)) ...


              Apart from that, is it a miracle or not, that my rather big application
              exe file (which handles the GUI part, and calls DLL subs/functions for the background work) has grown to its present size WITHOUT A SINGLE MESSAGE PUMP - until a day or two ago when I started experimenting. AND it works like a charm! However, I shall try the pump as per the specimen code mentioned above, and see if it then still needs sub-classing etc. which I'm pretty sure it does.

              One unrelated, but nagging question: how to get the GUI side to be consistent on different PC's with different screens or screen settings?
              Does Dialog Units to Pixels (or vice versa) do the job? I have looked for something, like Environ$, but one which furnishes info on the hardware, but found nothing so far. Please, can you suggest anything?

              ------------------

              Comment


              • #8
                Develop for the lowest common denominator - standard 640x480 mode. Not pretty, but it will work in most cases.

                A better technique is to query the workspace size (don't rely on the resolution of the screen as you will ignore the size and position of the taskbar) and resize your dialogs/windows dynamically when they load up.

                I wrote a (commercial) custom control to make dynamic window/dialog resizing much easier... I'll send you a demo of RESIZE32 if you are interested. Email me via my personal email address mailto:[email protected][email protected]</A>


                ------------------
                Lance
                PowerBASIC Support
                mailto:[email protected][email protected]</A>
                Lance
                mailto:[email protected]

                Comment

                Working...
                X