Announcement

Collapse
No announcement yet.

"Eating Messages" confusion

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

  • "Eating Messages" confusion

    This may be API 101, but I am totally confused.....

    Callbacks, (or even Subclassing), if my procedure handles the event, then I set Function = whatever the reply is supposed to be for the function....But farther down I set any unhandled functions to WindowProc, or MdiWindowProc or whatever....which may stick me in a "Blocking" call and I do not know it

    on the other hand, if I handle the event and exit the function, I could also get the same because I should not have exited the function.

    So since I am completely confused....what is the proper way to "Eat a message"? am I supposed to check if my function handled it, and what the message was before allowing or disallowing windows to handle what I did not handle?

    sorry if 101....but been a long week
    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
    Cliff,

    If I need to "block" or "eat" a message in a subclass procedure to prevent it from continuing, I simply just have it in my select case, and execute EXIT FUNCTION, before code gets to the 'CallWindowProc' function.
    Adam Drake
    Drake Software

    Comment


    • #3
      I guess I should have said...something more along the lines of
      "I handled it, but the next level needs to process, so how do I let it know I Already handled it?"
      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


      • #4
        Depends on the situation. Can you be more specific? If it is a situation where you need to do custom painting on a control after it's normal painting occurs under %WM_PAINT, inside the subclass procedure, you execute CallWindowProc first, do your processing, then exit function.

        If it is a situation for custom keyboard processing - you don't actually have to let it move on. EXIT FUNCTION will be sufficient.
        Adam Drake
        Drake Software

        Comment


        • #5
          Cliff,

          It is important to understand the difference between:

          Dialog Procedure
          Window Procedure
          Subclass WIndow procedure

          Let's start with:

          Window procedure.

          All window classes have a window procedure. If the class (ie. dialog class or a control class) is built into the operating system, the window procedure is in the operating system DLL's and not your app.

          If a window class is created (registered) by your app (custom class), then the window procedure will be in your apps code.

          When a message is processed in a window procedure it is usually either processed directly or the message is forwarded to the DefWindowProc API function (which processes based on defaults). If you write your own custom window class, then when you process a message (and don't want defaults), you process the message and then exit the function immediately. The return value for the function for that message is to be set based on the instructions in the API docs for that message. The return value has meaning.

          When subclassing a window, the messages are sent to the subclass procedure instead of the classes window procedure, no matter whether it is a custom class or not. If you process a message, then treat it the same way it would be with a window procedure according to the API docs instructions for that message. If the message is to be handle by the class defaults, it must be passed back to the original window procedure by calling the CallWindowProc API function.

          Now for:

          Dialog Procedures.

          Dialog Procedures are a little tricky, since they are not a window procedure and are treated differently. The Dialog class has its own window procedure in the operating system itself. That window procedure does an interesting thing. It forwards all messages to a user defined dialog procedure, before processing the messages. The user dialog procedure uses the return value to indicate to the original window procedure, whether it wants default processsing or not. If the return value of the dialog procedure (function) is non-zero, then the original window procedure does not process the message. It assumes the dialog procedure did the processing. There are just a few messages that actually can use the actual return value from the dialog procedure (ie. the WM_CTLCOLORxxx messages). The API docs explains which messages can do this.

          Most other messages though can not return a value in a dialog procedure. The return value simply indicates whether the original window procedure should process the message or not. If the return value is non-zero, the original window procedure does not process the message. The problem though is how do you pass back a return value, if the message needs a specific value ?

          This is done through a secondary mechanism in the dialog class, via the SetWindowLong API function. For the dialog class only, there is a flag for SetWindowLong which is DWL_MSGRESULT . If your dialog procedure processes a message, which the dialog class can't use the function return value, simple set the function return value to 1 (non-zero) to tell the original window procedure you processed the message and then use SetWindowLong with the DWL_MSGRESULT flag to pass back a return value the window procedure expects.

          Understanding the difference between a Dialog Procedure and a Window Procedure is important to use them properly.
          Chris Boss
          Computer Workshop
          Developer of "EZGUI"
          http://cwsof.com
          http://twitter.com/EZGUIProGuy

          Comment


          • #6
            Understanding the difference between a Dialog Procedure and a Window Procedure is important to use them properly
            IIRC, there's also some difference in handling DDT-Created dialogs versus CreateDialog- or DialogBox-created dialogs... I believe DDT looks only at the return from the dialog procedure and if that's true it does not forward to the default procedure. That is, I don't believe DDT-dialogs look at DWL_MSGRESULT.

            Practical effect... you can't return false to a DDT dialog with DWL_MSGRESULT set to true and expect DDT to skip the default processing. This is required for only a few select notification messages, but when you need it, you need it.
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              eating the message

              I've always enjoyed the table top meal time reference of 'eating the message'. As Adam stated I believe that term is only used with reference to subclassing, with the most common example being a keystroke. I believe subclassing a textbox is the most efficient way of preventing the user from entering invalid data in scenarios where for example only numeric, only dates, only alphabetic characters can be descriminated for/against. Its pretty much like the lone biscuit being passed around the dinner table. If you eat it, then no one else gets it. If somebody types in a letter 'b' in a numeric text box field, then your subclass procedure gets it before Window's internal procedure, and you 'eat' it, that is, not pass it on to the original WndProc, the address of which was returned to you when you installed the subclass.
              Fred
              "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

              Comment


              • #8
                To me a dialog is not so much more than a custom control.
                If you subclass a dialog you can also decide not to return any value.
                With some care.. i consider this technique 'restoring it to SDK behaviour'.

                Subclassing has the benefit that the hook proc is executed before the dialogproc can act.
                If a message is not passed to the original proc, 'he' won't know if something happened, fine by me.
                hellobasic

                Comment


                • #9
                  I don't think DDT dialogs work much different than those created using CreateDialog API's.

                  DDT likely doesn't have access to the dialog class window procedure, unless it does subclassing, which I doubt. DDT Dialogs are actual dialog class dialogs and not a custom dialog class.

                  DDT appears to create its own internal Dialog procedure hidden from your app for dialogs. That dialog procedure in turn forwards messages to your apps dialog procedure.

                  I reread the PB 8.0 docs and DDT nows passes back the dialog procedure return value to DWL_MSGRESULT for you if the return value is not zero and DWL_MSGRESULT is already zero.

                  I am not sure how you return back a zero value for a message though. I need to dig deeper on that one.

                  You will find this little program interesting. It demonstrates that DDT does indeed uses its own internal dialog procedure and then forwards the messages from that procedure to your forms dialog procedure.

                  Code:
                  ' ***************************************************************
                  '   This code can be used Royalty Free and Freely Distributed !
                  ' ***************************************************************
                  #COMPILE EXE
                  #REGISTER NONE
                  #DIM ALL          '  This is helpful to prevent errors in coding
                  
                  #INCLUDE "win32api.inc"   ' Must come first before other include files !
                  %FORM1_BUTTON1            = 100
                  ' --------------------------------------------------
                  DECLARE SUB ShowDialog_Form1(BYVAL hParent&)
                  DECLARE CALLBACK FUNCTION Form1_DLGPROC
                  ' --------------------------------------------------
                  DECLARE CALLBACK FUNCTION CBF_FORM1_BUTTON1()
                  '
                  GLOBAL hForm1&    ' Dialog handle
                  '
                  FUNCTION PBMAIN
                      LOCAL Count&
                      ShowDialog_Form1 0
                      DO
                          DIALOG DOEVENTS TO Count&
                      LOOP UNTIL Count&=0
                  END FUNCTION
                  '
                  SUB ShowDialog_Form1(BYVAL hParent&)
                      LOCAL Style&, ExStyle&
                      Style& = %WS_POPUP OR %DS_MODALFRAME OR %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU OR %DS_CENTER
                      ExStyle& = 0
                      DIALOG NEW hParent&, "Your Dialog", 0, 0,  267,  177, Style&, ExStyle& TO hForm1&
                      CONTROL ADD "Button", hForm1&,  %FORM1_BUTTON1,  "Display Dialog Procedure Addresses", 37, 62, 195, 49, _
                          %WS_CHILD OR %WS_VISIBLE OR %BS_PUSHBUTTON OR %WS_TABSTOP CALL CBF_FORM1_BUTTON1
                      DIALOG SHOW MODELESS hForm1& , CALL Form1_DLGPROC
                  END SUB
                  '
                  CALLBACK FUNCTION Form1_DLGPROC
                      SELECT CASE CBMSG
                          CASE ELSE
                      END SELECT
                  END FUNCTION
                  '
                  CALLBACK FUNCTION CBF_FORM1_BUTTON1
                      IF CBCTLMSG=%BN_CLICKED THEN
                            LOCAL T$
                            T$="Form Callback Dialog Prcoedure Address: "+STR$(CODEPTR(Form1_DLGPROC))+$CRLF
                            T$=T$+"Form TRUE Dialog Procedure Address: "+STR$(GetWindowLong(hForm1&, %DWL_DLGPROC))+$CRLF
                            T$=T$+"Dialog Class Window Procedure Address: "+STR$(GetWindowLong(hForm1&, %GWL_WNDPROC))+$CRLF
                            MSGBOX T$
                      END IF
                  END FUNCTION
                  Chris Boss
                  Computer Workshop
                  Developer of "EZGUI"
                  http://cwsof.com
                  http://twitter.com/EZGUIProGuy

                  Comment


                  • #10
                    I don't think DDT dialogs work much different than those created using CreateDialog API's.
                    Then I suggest you take a closer look. An important concept that DDT does not handle at all is default buttons.
                    I am not talking about IDOK here.

                    I am not sure how you return back a zero value for a message though.
                    You cannot. DDT took a workaround for a shortcoming in the dialog box manager and broke it.
                    Dominic Mitchell
                    Phoenix Visual Designer
                    http://www.phnxthunder.com

                    Comment


                    • #11
                      I am interested in an elaboration of both of your remarks
                      What's different besides IDOK?
                      In my tool i can show the black border fine if that's what you mean?

                      >You cannot. DDT took a workaround for a shortcoming in the dialog box manager and broke it.
                      You speak about a shortcoming in the dialog box?
                      Afaik the dialogbox allows 0 ??
                      hellobasic

                      Comment


                      • #12
                        What's different besides IDOK?
                        In my tool i can show the black border fine if that's what you mean?
                        The following is a simple example.
                        A dialog has the following controls:
                        Two edit boxes and a combobox
                        Three buttons with identifiers 1001, 1002 and 1003 respectively.
                        The button with the 1002 identifier has the BS_DEFPUSHBUTTON style.

                        When the user sets the focus to one of the edit controls and later presses the Enter key, the following happens:
                        1) The button with the 1002 ID is drawn it a heavy black border.
                        2) The user supplied dialog procedure receives the WM_COMMAND message.
                        3) The notification code is set to BN_CLICKED and the control ID is set to 1002.

                        Step 3, ID <> IDOK, is not supported by DDT.


                        You speak about a shortcoming in the dialog box?
                        Afaik the dialogbox allows 0 ??
                        If for example, a return value of zero means do not do the default behaviour, then you are out of luck with DDT.
                        For example, WM_QUERYENDSESSION where returning zero means abort shutdown.
                        Remember, with the non-DDT dialogs you only return 0 or 1 and set DWL_MSGRESULT separately.
                        DDT copies the return value to DWL_MSGRESULT which works fine in most cases, but will fail in a few important cases.
                        Dominic Mitchell
                        Phoenix Visual Designer
                        http://www.phnxthunder.com

                        Comment


                        • #13
                          1) >Step 3, ID <> IDOK, is not supported by DDT.
                          ? in Windows the control should be set to %IDOK.
                          Afaik it is not normal to use an other value for default button.

                          If you don't add these buttons but press enter on a dialog, wm_command is fired with IDOK anyway.
                          Same for IDCancel (ESC)

                          2) I knew there was an issue with this for DDT, but the way you put it it seemed a dialogbox issue, just a misunderstanding.
                          hellobasic

                          Comment


                          • #14
                            Afaik it is not normal to use an other value for default button.
                            How did you come to that conclusion?
                            The dialog box manager goes to great lengths to implement this via DM_GETDEFID,
                            DM_SETDEFID and WM_GETDLGCODE. If you are not using the dialog box manager, this
                            is something that you will have to code yourself.
                            In the case of property boxes or wizards with buttons on the pages, firing IDOK
                            everytime the Enter key is pressed is going to get you into trouble.
                            Dominic Mitchell
                            Phoenix Visual Designer
                            http://www.phnxthunder.com

                            Comment


                            • #15
                              Wow I started quite the debate, and all of which touched on the confusion I am am having.

                              In some cases its painting a MDI background (what to subclass, what to pass what to "EAT" etc...) in some its, whether to "destroy or not....that be the question" (which I get, that you get a chance to hide or allow a destroy, since its called next), but should there not be a set of rules as to what to do in your particular situation? I guess the answer is...(As MCM puts it) "Application Specific" as to what is it you are doing, and how to handle it.

                              Although keep up the discussion, I love seeing things I had not thought of, and this is a welcome exchange of ideas that I and others may refer back to when stuck in the same sort of situation.
                              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

                              Working...
                              X