Announcement

Collapse
No announcement yet.

Dynamic Callback for CONTROL ADD BUTTON

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

  • Dynamic Callback for CONTROL ADD BUTTON

    I want to know if its possible to use a variable or pointer or something as a callback in a CONTROL ADD BUTTON statement. Below is an example of what I've tried doing but didn't work.

    Code:
    #COMPILE EXE
    #DIM ALL
    
    TYPE DialogObject
       dHandle                    AS DWORD
       dText                      AS ASCIIZ * 65
       dWidth                     AS INTEGER
       dHeight                    AS INTEGER
    END TYPE
    
    TYPE ControlObject
       cID                        AS DWORD
       cCallback                  AS DWORD
       cType                      AS ASCIIZ * 33
       cText                      AS ASCIIZ * 33
       cXPos                      AS INTEGER
       cYPos                      AS INTEGER
       cWidth                     AS INTEGER
       cHeight                    AS INTEGER
    END TYPE
    
    FUNCTION addControl(BYVAL myControl AS ControlObject, BYVAL myDialogHandle AS DWORD) AS LONG
       SELECT CASE LCASE$(myControl.cType)
          CASE "button"
             CONTROL ADD BUTTON, myDialogHandle, myControl.cID, myControl.cText, myControl.cXPos, myControl.cYPos, myControl.cWidth, myControl.cHeight CALL DWORD myControl.cCallback
          CASE ELSE
             ' Do Nothing
       END SELECT
    END FUNCTION 
    
    CALLBACK FUNCTION button_Exit() AS LONG
       IF CB.MSG = %WM_COMMAND THEN
        IF CB.CTLMSG = %BN_CLICKED THEN
          DIALOG END CB.HNDL
          FUNCTION = 1
        END IF
      END IF
    END FUNCTION 
    
    FUNCTION PBMAIN()
       ' Variable Declaration
       DIM dMain                  AS DialogObject
       DIM cExit                  AS ControlObject
    
       ' Initialization
       dMain.dText                = "Test Program"
       dMain.dWidth               = 250
       dMain.dHeight              = 300
       cExit.cID                  = 1001
       cExit.cCallback            = CODEPTR(button_Exit)
       cExit.cType                = "button"
       cExit.cText                = "Exit"
       cExit.cXPos                = 5
       cExit.cYPos                = 5
       cExit.cWidth               = 240
       cExit.cHeight              = 24
       
       ' Dialog Creation
       DIALOG NEW PIXELS, 0, dMain.dText, , , dMain.dWidth, dMain.dHeight TO dMain.dHandle
       addControl(cExit, dMain.dHandle)
       DIALOG SHOW MODAL dMain.dHandle
       
    END FUNCTION
    Main reason I want to do this is for creating dynamic buttons which might point to different callback functions based on external data (for example a config file or something). I know ways around it could be creating a dialog callback and then just doing stuff in there based on which button was pressed or using a macro perhaps. Either way any help, comments are welcome. Thanks.

  • #2
    want to know if its possible to use a variable or pointer or something as a callback in a CONTROL ADD BUTTON statement
    No.

    That simplifies things, doesn't it?

    What you CAN *try* is...
    Code:
     CONTROL ADD BUTTON  hdlg, %ID_BUTTON ......   CALL MasterButtonCallback 
     dwProc  =     CODEPTR (ThisBUttonProc) 
     CONTROL SET USER hDlg, %ID_BUTTON, %CB_SUB, dwProc 
    
     CALLBACK FUNCTION MasterButtonCallback 
      LOCAL dwPRoc AS DWORD 
        CONTROL GET USER  CBHNDL, %ID_BUTTON, %CB_SUB to dwProc
        CALL DWORD  dwProc USING  prototype (CBHNDL, CBMSG,  CBWparam, CBLparam) 
    END FUNCTION
    
    CALLBACK FUNCTION ThisButtonProc ()
    
    END FUNCTION
    But I think you might be better served to use the CONTROL SET USER values with the "masterbuttoncallback" procedure, and use IF or SELECT CASE on that value in that proc to do different things at different times.

    WARNING: This CALL DWORD thing has got to be 'off the reservation' but I would not be surprised if it works; frankly I would be surprised if it doesn't.

    However, I cannot in good conscience "recommend" coding this way. I'd go with the CONTROL SET/GET USER thing.

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

    Comment


    • #3
      I tried the code above, and it took me a few minutes to figure out what "prototype" was, then I finally added a DlgCallback function to use as the prototype.

      The program does work as intended, I can create controls dynamically without knowing what callback functions they should link to at compile time. However it does seem kind of like a work around as opposed to a more proper way of doing this. I will continue to experiment with some of the other methods like CONTROL SET/GET USER and see which works the best for my program.

      Thanks for for your help.

      Comment


      • #4
        However it does seem kind of like a work around as opposed to a more proper way of doing this
        Using DDT, this is probably the ONLY way. What you want to accomplish is actually fairly easy to do with SDK-style programming, except SDK-Style does not support "control-level" callaback functions at all, unless you superclass or subclass the individual controls.

        However, I have to question your wish to do things this way.

        Personally, I'd think about not using control-level callbacks at all, handling everything through the messages sent to the owner window (the dialog itself).

        If all you are trapping for buttons is WM_COMMAND, seems to me using control-level callbacks just puts your source code in more places. Since you always know which button is sending the command and you can always store info at the control level using CONTROL SET USER , you can let your primary dialog procedure do stuff based on that value. eg,
        Code:
        CALLBACK  FUNCTION  MY_DIALOG_PROC () AS LONG 
        ....
        SELECT CASE AS LONG CBMSG 
           CASE %WM_COMMAND
              SELECT CASE AS LONG   CBCTLID 
                 CASE Id_button1, Id_button2... 
                    CONTROL GET USER  CBHNDL, CBCTLID, Subscript TO iValue 
                    SELECT CASE iValue 
                        CASE 1 
                            do something 
                        CASE 2 
                            do something else
                        ...
                   END SELECT  ' of user value 
             END SELECT  ' of control generating WM_COMMAND
        
          END SELECT ' of message
        MCM
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          Roberto,
          Is what you are describing along the lines of "Scripting"???

          AKA
          Load a text file, and create a dialog, and have functions act on it????

          Possible????....Yes
          Programmable???....Yes (depending on your use)
          Easy to read???.....NOT ON YOUR LIFE!!!! ( Just kidding, it depends on how much capability you need....but its a doozy even with just basics)


          Its a nice concept that I have looked at many times, but the time spent to make it feasible usually runs into a wall and I make a function to be called to cover the process

          (Although I will admit being able to "Script" your own code for processes that are similar, but different from the original intent, has long been a side pursuit I wish I had time for)
          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