Announcement

Collapse
No announcement yet.

DDT Check Box behaviour

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

  • DDT Check Box behaviour

    I have a large program which in one portion tests something and if conditions are met tries to tick a check box. The code in the check box section of dialog callback then does the changes required. The short program below shows the problem. If I click on the check box then the callback responds but if I post or send a click message to it nothing happens. If I set the state of the check box then work code doesn't execute. What am I missing? Why doesn't the check box respond to a post or send message?
    Code:
    #PBFORMS CREATED V1.51
    #COMPILE EXE
    #DIM ALL
    
    #PBFORMS BEGIN INCLUDES
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    #PBFORMS END INCLUDES
    
    #PBFORMS BEGIN CONSTANTS
    %Bcheck      = 1004
    %Bexit       = 1005
    %Bpost       = 1003
    %Bsend       = 1002
    %CBtest      = 1001
    %IDD_DIALOG1 =  101
    #PBFORMS END CONSTANTS
    
    DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
    DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    #PBFORMS DECLARATIONS
    
    FUNCTION PBMAIN()
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION
    
    SUB TCheck (Hdlg AS DWORD)
        CONTROL SET CHECK Hdlg, %CBtest, 1
    END SUB
    
    SUB Tpost (Hdlg AS DWORD)
        CONTROL POST Hdlg, %CBtest, %BN_CLICKED, 0, 0
    END SUB
    SUB Tsend (Hdlg AS DWORD)
        CONTROL SEND Hdlg, %CBtest, %BN_CLICKED, 0, 0
    END SUB
    CALLBACK FUNCTION ShowDIALOG1Proc()
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
    
            CASE %WM_NCACTIVATE
                STATIC hWndSaveFocus AS DWORD
                IF ISFALSE CBWPARAM THEN
                    hWndSaveFocus = GetFocus()
                ELSEIF hWndSaveFocus THEN
                    SetFocus(hWndSaveFocus)
                    hWndSaveFocus = 0
                END IF
    
            CASE %WM_COMMAND
                SELECT CASE AS LONG CBCTL
                    CASE %CBtest
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            'Note the above line was not added by PBForms 5.1
                            'in fact PBForms puts in no lines
                            ? "State changed so do work"
                        END IF
    
                    CASE %Bsend
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            Tsend CBHNDL
                        END IF
    
                    CASE %Bpost
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            Tpost CBHNDL
                        END IF
    
                    CASE %Bcheck
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            Tcheck CBHNDL
                        END IF
    
                    CASE %Bexit
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            DIALOG END CBHNDL
                        END IF
    
                END SELECT
        END SELECT
    END FUNCTION
    
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
    
    #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
        LOCAL hDlg  AS DWORD
    
        DIALOG NEW hParent, "Dialog1", 70, 70, 201, 58, TO hDlg
        CONTROL ADD CHECKBOX, hDlg, %CBtest, "Test Check Box", 55, 10, 75, 15
        CONTROL ADD BUTTON,   hDlg, %Bsend, "Send Msg", 5, 35, 45, 15
        CONTROL ADD BUTTON,   hDlg, %Bpost, "Post Msg", 53, 35, 45, 15
        CONTROL ADD BUTTON,   hDlg, %Bcheck, "Check", 101, 35, 45, 15
        CONTROL ADD BUTTON,   hDlg, %Bexit, "Exit", 149, 35, 46, 15
    #PBFORMS END DIALOG
    
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    
    #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
    #PBFORMS END CLEANUP
    
        FUNCTION = lRslt
    END FUNCTION

  • #2
    Your lparam and wParam parameters are wrong. (CBLPARAM and CBWPARAM).

    Should be as in....
    Code:
    MACRO PostButtonClick(hWnd,ctrlid)
     PostMessage hWnd, %WM_COMMAND, MAKDWD(ctrlid,%BN_CLICKED), GetDlgItem(hWnd,Ctrlid)
    END MACRO
    But with a check box why bother to send or post a message instead of using the eminently understandable 'CONTROL SET CHECK?'
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      Thanks Micheal but as you can see in the program and description I have tried CONTROL SET CHECK but then the code in the callback does not run so what is the message I should be looking for?
      And what is wrong with the two parameters as they aren't tested

      Comment


      • #4
        BN_CLICKED is not a window message so your code is incorrect.

        It is a notification message which is passed through the WM_COMMAND message.

        You need to be sending the WM_COMMAND message to the control, not BN_CLICKED. The BN_CLICKED notification code will be embeded in the parameters of the WM_COMMAND message.

        The syntax will be:

        SendMessage hDlg&, %WM_COMMAND, MAKLNG(%ControlID,%BN_CLICKED), hCtrl&
        Chris Boss
        Computer Workshop
        Developer of "EZGUI"
        http://cwsof.com
        http://twitter.com/EZGUIProGuy

        Comment


        • #5
          >I have tried CONTROL SET CHECK but then the code in the callback does not run ...

          Of course it doesn't because you didn't CLICK the checkbox control. But.. why would you need to do that anyway? At the point at which you do your "CONTROL SET CHECK" you can do whatever else needs to be done right at that time.

          >...so what is the message I should be looking for?

          Um, the message you are already processing?

          >And what is wrong with the two parameters ...
          Simply put yours are value zero and should be something else.

          >as they aren't tested

          I think you need to re-read the doc for CBCTL and CBCTLMSG. If that does not explain it see if you can find something in the help file under CONTROL SEND or CONTROL POST... that should explain it.



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

          Comment


          • #6
            Notification messages 101:

            There are two basic types of notification messages for controls.

            (1) Those passed through WM_COMMAND
            (2) Those passed through WM_NOTIFY

            Even though they are referred to as messages, they are not the same thing as window messages, so they can't be sent using sendmessage or postmessage (as the Msg parameter).

            Notification messages are embeded in the parameters of the WM_COMMAND or WM_NOTIFY window messages.

            WM_COMMAND has a simple syntax:

            SendMessage hParent&, %WM_COMMAND, MAKLNG(%MyControlID,%NotificationMessage), hCtrl&

            WM_NOTIFY has a slightly more complex syntax, in that a pointer to a structure is passed in the lParam parameter.

            The lParam value is a pointer for a unique structure for each control type (mostly common controls). You have to read the API docs to find out what the structure is and each control type may use different structures for different notification messages.

            Fortunately, this unique structure always has the following substructure (type) as the first member:

            Code:
            TYPE NMHDR
              hwndFrom AS DWORD
              idfrom AS DWORD
              code AS LONG  
            END TYPE
            The .code member of this structure is what contains the actual notification message value. This can be tested to see what notification message it is and then processed accordingly.

            It is important to note, that notification messages are not the same thing as window messages. They can't be sent (as the Msg parameter) via SendMessage. They are messages, which are embedded in actual window messages (WM_COMMAND or WM_NOTIFY).

            It is important to get their syntax right for both processing them, as well as when attempting to generate fake messages and sending/posting them.
            Chris Boss
            Computer Workshop
            Developer of "EZGUI"
            http://cwsof.com
            http://twitter.com/EZGUIProGuy

            Comment


            • #7
              Chris thank you but I am not using the API calls but the PB DDT commands which work fine with all other controls I have used them with, I assume PB translates them to the formats you are specifying.
              Micheal there is quite a lot of code in the real program which executes if the user clicks on the check box, so for efficiency I would rather not reproduce it when I wish to programatically change the check box state. Also the help files give no specific details Wparam$ and Lparam& and examples normally show 0 and 0. If in fact they contain the check state I would like I could work that out but as the callback never receives the message as shown by running the test program there is not much point.
              My reading shows that the check box only has two messages ie BN_clicked and BN_doubleclicked. So I guess my real question is why does a standard dialog callback not receive these messages like other controls when sent or posted the message ie sending or posting such mesages to a button etc works fine.

              Comment


              • #8
                John,

                My comments are directly related to DDT as well!

                Instead of SendMessage one would use CONTROL SEND or DIALOG SEND, but the syntax of the messages and the parameters for notification messages are exactly the same.

                It should be noted, that DDT is not some proprietary command set, in the sense that it does things differently than the API. It is a well designed command set which calls the API and uses similiar syntaxes.

                What I said definitelly effects all DDT users.

                It should be noted that DDT callback functions (for controls) is simply processing the WM_COMMAND message, so to generate a DDT callback event, one must send a WM_COMMAND message to the dialog and DDT will forward it to the callback function.

                DDT version of what I noted above:

                DIALOG SEND hDlg&, %WM_COMMAND, MAKLNG(%MyControlID,%NotificationMessage), hCtrl&
                Last edited by Chris Boss; 5 Feb 2008, 09:46 AM.
                Chris Boss
                Computer Workshop
                Developer of "EZGUI"
                http://cwsof.com
                http://twitter.com/EZGUIProGuy

                Comment


                • #9
                  John,
                  Try this..
                  Code:
                  SUB TCheck (Hdlg AS DWORD)
                    LOCAL TOGGLE AS Long 
                    CONTROL GET CHECK Hdlg, %CBtest To TOGGLE
                    CONTROL SET CHECK Hdlg, %CBtest, IIF(TOGGLE, 0, 1)
                    'CONTROL POST Hdlg, %CBtest, %BM_CLICK, 0, 0
                  END SUB
                   
                  SUB Tpost (Hdlg AS DWORD)
                      CONTROL POST Hdlg, %CBtest, %BM_CLICK, 0, 0
                  END SUB
                  SUB Tsend (Hdlg AS DWORD)
                      CONTROL SEND Hdlg, %CBtest, %BM_CLICK, 0, 0
                  END SUB
                  Rgds, Dave

                  Comment


                  • #10
                    box, so for efficiency I would rather not reproduce it when I wish to programatically change the check box state
                    Then write a SUB or FUNCTION to do what has to be done. You can call that anytime from anywhere in your program. (I also despise replicated code).
                    So I guess my real question is why does a standard dialog callback not receive these messages like other controls when sent or posted the message ie sending or posting such mesages to a button etc works fine.
                    Asked and answered (twice) but let me simplify it a little: Your POST and SEND statements are WRONG. Had you done them correctly you'd be getting the effect you seek.

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

                    Comment


                    • #11
                      DDT and the API 101:

                      To better appreciate what DDT is really doing, one really should gain an understanding of the Windows API's that DDT commands are calling to accomplish things.

                      DDT is far closer to the Windows API that one may realize and it uses a number of standard Dialog API's built into Windows.

                      The Callback function is not some proprietary engine which does its own tricks totally different than the API.

                      Callback functions in DDT are simply a means of forwarding API notification messages to a user defined function. Under the hood, DDT is simply processing the WM_COMMAND message for you (from the dialog procedure internally) and parsing out the parameters for the message into more readable data (the CBxxx functions). Thats all it is doing!

                      Experienced API programmers with experience with the Dialog API's can tell you that the DDT command set is a lean and mean command set which is a wrapper over many existing API's already in Windows.

                      When working with DDT, it is best not to view DDT as separate than the API, as if it were totally different. One should view DDT as simply a cleaner way of accessing the API, but with the same (or similiar) syntaxes as one would do when using the API.

                      Do not underestimate the value of the API docs, to better understand DDT and what it is doing.

                      If you understand the reasons why DDT commands work the way they do, you will be able to use them more effectively.
                      Chris Boss
                      Computer Workshop
                      Developer of "EZGUI"
                      http://cwsof.com
                      http://twitter.com/EZGUIProGuy

                      Comment


                      • #12
                        Ok,

                        Maybe I see the confusion here!

                        There is a big difference between:

                        BN_CLICKED

                        and

                        BM_CLICK

                        There are two types of messages defined for each control in the API docs.

                        (1) Actual window messages which can sent directly to the control classes window procedure (using SendMessage API or CONTROL SEND in DDT). Such window messages have a prefix for the class which usually ends with the letter M (for message).

                        For the button class (includes checkboxes) some of the messages are:

                        BM_CLICK (simulates a mouse click)
                        BM_GETCHECK
                        BM_SETCHECK
                        etc.

                        Notice the prefix BM_

                        (2) Notification messages which are not window messages, but are passed through the WM_COMMAND or WM_NOTIFY messages (DDT only passes WM_COMMAND to callbacks).

                        Notification messages, since they are not window messages use a different prefix than the window messages for the same class. Usually they end with the letter N (for Notification). These messages are never sent using SendMessage or CONTROL SEND as the Msg parameter!

                        Some notification messages for the button class are:

                        BN_CLICKED
                        BN_DBLCLK
                        BN_SETFOCUS
                        etc.

                        Notice the prefix BN_

                        Can you see the problem here ?

                        BM_CLICK (a window message)

                        and

                        BN_CLICKED (a notification message)

                        I think the problem here is the confusion between a window message and a notification message, by simply not noticing the M or N at the end of the message prefix.

                        The Windows API has a real reason for its naming conventions of constants and the M or N are the end of a prefix means a great deal.

                        Actually, John was attempting to do the right thing, but he simply made the mistake of using the BN_CLICKED notification message constant instead of the BM_CLICK constant for his CONTROL SEND call.

                        See how easy it is to get confused and use the wrong constant.

                        Now I see why he couldn't grasp my discussion of BN_CLICKED and WM_COMMAND!

                        He was trying to send a valid message (BM_CLICK), but simply used the wrong constant which was BN_CLICKED.

                        My points were valid, if he was actually trying to send a notification message, but he wasn't.

                        The lesson in this, is that be very careful of the constants you use. They may look similiar (like BM_CLICK and BN_CLICKED), but they are not.

                        The letters in a prefix of an API constant have real meaning and should be learned.

                        For me an experienced API programmer, the first thing I saw when I looked at Johns code was BN_ and the light went off in my head, NOTIFICATION message. It never dawned on me, that he was trying to send the valid window message BM_CLICK.

                        An experienced API program will quickly recognize constant prefixes and they have meaning so he will come to a specific conclusion.

                        Moral of the story:

                        Those constant prefixes have real meaning and are important.
                        Chris Boss
                        Computer Workshop
                        Developer of "EZGUI"
                        http://cwsof.com
                        http://twitter.com/EZGUIProGuy

                        Comment


                        • #13
                          I should give credit to Dave Biggs.

                          I wasn't until he posted code with the correct constant BM_CLICK that I realized the cause of confusion. I just assumed John was actually trying to use a notification message (BN_CLICKED) (which can be done to generate an event in a callback) and so no wonder my comments seemed strange.
                          Chris Boss
                          Computer Workshop
                          Developer of "EZGUI"
                          http://cwsof.com
                          http://twitter.com/EZGUIProGuy

                          Comment


                          • #14
                            Thank you Chris and Dave, yes changing the sent message to %BM_CLICK solved the problem, I was thowen off by the fact that that the control resonded to the %BN_CLICKED message if I actually clicked on the check box

                            Comment

                            Working...
                            X