Announcement

Collapse
No announcement yet.

Controlling live update of combo and text boxes

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

  • Controlling live update of combo and text boxes

    This isn't my real app, just thrown into forms to show what I want. I have several combo boxes and text boxes with numeric data. I want any given box to update based on the other ones. It works ok with combo boxes when you enter data manually, but doesn't update when the drop down list is used. If I try to go both ways, conflicts occur on start up, and depending on how data is entered. Is there some simple way to update on any action, and prevent confusion between the boxes?
    Code:
    #PBFORMS Created v1.51
    '------------------------------------------------------------------------------
    ' The first line in this file is a PB/Forms metastatement.
    ' It should ALWAYS be the first line of the file. Other
    ' PB/Forms metastatements are placed at the beginning and
    ' end of "Named Blocks" of code that should be edited
    ' with PBForms only. Do not manually edit or delete these
    ' metastatements or PB/Forms will not be able to reread
    ' the file correctly.  See the PB/Forms documentation for
    ' more information.
    ' Named blocks begin like this:    #PBFORMS BEGIN ...
    ' Named blocks end like this:      #PBFORMS END ...
    ' Other PB/Forms metastatements such as:
    '     #PBFORMS DECLARATIONS
    ' are used by PB/Forms to insert additional code.
    ' Feel free to make changes anywhere else in the file.
    '------------------------------------------------------------------------------
    
    #COMPILE EXE
    #DIM ALL
    
    '------------------------------------------------------------------------------
    '   ** Includes **
    '------------------------------------------------------------------------------
    #PBFORMS Begin Includes
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    #INCLUDE "PBForms.INC"
    #PBFORMS End Includes
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Constants **
    '------------------------------------------------------------------------------
    #PBFORMS Begin Constants
    %IDD_DIALOG1   =  101
    %IDC_COMBOBOX1 = 1001
    %IDC_COMBOBOX2 = 1002
    %IDC_TEXTBOX1  = 1003
    %IDC_LABEL1    = 1004
    %IDC_LABEL2    = 1005
    #PBFORMS End Constants
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Declarations **
    '------------------------------------------------------------------------------
    DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
    DECLARE FUNCTION SampleComboBox(BYVAL hDlg AS DWORD, BYVAL lID AS LONG, BYVAL _
        lCount AS LONG) AS LONG
    DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    #PBFORMS Declarations
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Main Application Entry Point **
    '------------------------------------------------------------------------------
    FUNCTION PBMAIN()
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** CallBacks **
    '------------------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
        SELECT CASE AS LONG CB.MSG
            CASE %WM_INITDIALOG
                ' Initialization handler
    
            CASE %WM_NCACTIVATE
                STATIC hWndSaveFocus AS DWORD
                IF ISFALSE CB.WPARAM 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 CB.CTL
                    CASE %IDC_COMBOBOX1
                        CALL UpdatePower(CB.HNDL)              'multiply 'em together- doesn't update with drop down list
    
                    CASE %IDC_COMBOBOX2
                        CALL UpdatePower(CB.HNDL)              'as above
    
                    CASE %IDC_TEXTBOX1
                        IF CB.CTLMSG = %EN_CHANGE THEN         'filter doesn't do much
                            'CALL UpdateOnNewPower(CB.HNDL)
                        END IF
                END SELECT
        END SELECT
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Sample Code **
    '------------------------------------------------------------------------------
    FUNCTION SampleComboBox(BYVAL hDlg AS DWORD, BYVAL lID AS LONG, BYVAL lCount _
        AS LONG) AS LONG
        LOCAL i AS LONG
    
        CONTROL SEND hDlg, lID, %CB_SETEXTENDEDUI, %TRUE, 0
    
        FOR i = 1 TO lCount
            COMBOBOX ADD hDlg, lID, STR$(i)
        NEXT i
    END FUNCTION
    
    SUB UpdatePower(BYVAL tBox AS DWORD)                    'update power calculation if V or R is changed
        LOCAL Vout AS STRING
        LOCAL Res AS STRING
        CONTROL DISABLE tBox, %IDC_TEXTBOX1
        CONTROL GET TEXT tBox, %IDC_COMBOBOX1 TO Vout
        CONTROL GET TEXT tBox, %IDC_COMBOBOX2 TO Res
        CONTROL SET TEXT tBox, %IDC_TEXTBOX1, FORMAT$(VAL(Vout)*VAL(Res), "##0.0")
        CONTROL ENABLE tBox, %IDC_TEXTBOX1
    END SUB
    
    SUB UpdateOnNewPower(BYVAL tBox AS DWORD)               'update V if power is changed
        LOCAL Pwr AS STRING
        LOCAL Res AS STRING
        CONTROL GET TEXT tBox, %IDC_TEXTBOX1 TO Pwr
        CONTROL GET TEXT tBox, %IDC_COMBOBOX2 TO Res
        CONTROL SET TEXT tBox, %IDC_COMBOBOX1, FORMAT$(VAL(Pwr)/VAL(Res), "####.###")
    END SUB
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Dialogs **
    '------------------------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt  AS LONG
    
    #PBFORMS Begin Dialog %IDD_DIALOG1->->
        LOCAL hDlg   AS DWORD
        LOCAL hFont1 AS DWORD
        LOCAL hFont2 AS DWORD
    
        DIALOG NEW hParent, "Dialog1", 122, 142, 201, 126, %WS_OVERLAPPED OR _
            %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_MINIMIZEBOX 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 COMBOBOX, hDlg, %IDC_COMBOBOX1, , 15, 10, 60, 60, %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %CBS_DROPDOWN, _
            %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
        CONTROL ADD COMBOBOX, hDlg, %IDC_COMBOBOX2, , 15, 45, 60, 60, %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %CBS_DROPDOWN, _
            %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
        CONTROL ADD TEXTBOX,  hDlg, %IDC_TEXTBOX1, "", 115, 15, 60, 30
        CONTROL ADD LABEL,    hDlg, %IDC_LABEL1, "=", 90, 20, 20, 20
        CONTROL ADD LABEL,    hDlg, %IDC_LABEL2, "X", 35, 25, 20, 15
    
        hFont1 = PBFormsMakeFont("MS Sans Serif", 24, 400, %FALSE, %FALSE, _
            %FALSE, %ANSI_CHARSET)
        hFont2 = PBFormsMakeFont("MS Sans Serif", 18, 400, %FALSE, %FALSE, _
            %FALSE, %ANSI_CHARSET)
    
        CONTROL SEND hDlg, %IDC_LABEL1, %WM_SETFONT, hFont1, 0
        CONTROL SEND hDlg, %IDC_LABEL2, %WM_SETFONT, hFont2, 0
    #PBFORMS End Dialog
    
        SampleComboBox hDlg, %IDC_COMBOBOX1, 30
        SampleComboBox hDlg, %IDC_COMBOBOX2, 30
    
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    
    #PBFORMS Begin CleanUp %IDD_DIALOG1
        DeleteObject hFont1
        DeleteObject hFont2
    #PBFORMS End CleanUp
    
        FUNCTION = lRslt
    END FUNCTION
    '------------------------------------------------------------------------------

  • #2
    Originally posted by Conrad Hoffman View Post
    ... but doesn't update when the drop down list is used. If I try to go both ways, conflicts occur on start up, and depending on how data is entered. Is there some simple way to update on any action, and prevent confusion between the boxes?
    my guess is that what you see is not what you get from CONTROL GET TEXT. I would think that by using the correct notifications (see help on CONTROL ADD COMBOBOX CB.CTLMSG values, you can update the calculation with the correct values.

    Comment


    • #3
      By not filtering at all, the subroutine should fire on *any* message, updating the answer, but there doesn't seem to be a message resulting from picking from the list.
      Last edited by Conrad Hoffman; 4 Oct 2008, 11:04 PM. Reason: confused!

      Comment


      • #4
        Good timing?

        Hi Conrad,

        It appears not to be a question of whether a message gets fired (it does - %CBN_SELCHANGE, I believe), but more a question of timing. Try this (although note that I've commented out all the PBForms fonts stuff, as I don't have PBForms and it won't compile otherwise):
        Code:
        #PBFORMS Created v1.51
        '------------------------------------------------------------------------------
        ' The first line in this file is a PB/Forms metastatement.
        ' It should ALWAYS be the first line of the file. Other
        ' PB/Forms metastatements are placed at the beginning and
        ' end of "Named Blocks" of code that should be edited
        ' with PBForms only. Do not manually edit or delete these
        ' metastatements or PB/Forms will not be able to reread
        ' the file correctly.  See the PB/Forms documentation for
        ' more information.
        ' Named blocks begin like this:    #PBFORMS BEGIN ...
        ' Named blocks end like this:      #PBFORMS END ...
        ' Other PB/Forms metastatements such as:
        '     #PBFORMS DECLARATIONS
        ' are used by PB/Forms to insert additional code.
        ' Feel free to make changes anywhere else in the file.
        '------------------------------------------------------------------------------
        
        #COMPILE EXE
        #DIM ALL
        
        '------------------------------------------------------------------------------
        '   ** Includes **
        '------------------------------------------------------------------------------
        #PBFORMS Begin Includes
        #IF NOT %DEF(%WINAPI)
            #INCLUDE "WIN32API.INC"
        #ENDIF
        '#INCLUDE "PBForms.INC"
        #PBFORMS End Includes
        '------------------------------------------------------------------------------
        
        '------------------------------------------------------------------------------
        '   ** Constants **
        '------------------------------------------------------------------------------
        #PBFORMS Begin Constants
        %IDD_DIALOG1   =  101
        %IDC_COMBOBOX1 = 1001
        %IDC_COMBOBOX2 = 1002
        %IDC_TEXTBOX1  = 1003
        %IDC_LABEL1    = 1004
        %IDC_LABEL2    = 1005
        #PBFORMS End Constants
        %UM_UPDATEPOWER = %WM_USER + 1001
        '------------------------------------------------------------------------------
        
        '------------------------------------------------------------------------------
        '   ** Declarations **
        '------------------------------------------------------------------------------
        DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
        DECLARE FUNCTION SampleComboBox(BYVAL hDlg AS DWORD, BYVAL lID AS LONG, BYVAL _
            lCount AS LONG) AS LONG
        DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        #PBFORMS Declarations
        '------------------------------------------------------------------------------
        
        '------------------------------------------------------------------------------
        '   ** Main Application Entry Point **
        '------------------------------------------------------------------------------
        FUNCTION PBMAIN()
            ShowDIALOG1 %HWND_DESKTOP
        END FUNCTION
        '------------------------------------------------------------------------------
        
        '------------------------------------------------------------------------------
        '   ** CallBacks **
        '------------------------------------------------------------------------------
        CALLBACK FUNCTION ShowDIALOG1Proc()
            SELECT CASE AS LONG CB.MSG
                CASE %WM_INITDIALOG
                    ' Initialization handler
        
                CASE %WM_NCACTIVATE
                    STATIC hWndSaveFocus AS DWORD
                    IF ISFALSE CB.WPARAM 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 CB.CTL
                        CASE %IDC_COMBOBOX1
                            PostMessage CB.HNDL, %UM_UPDATEPOWER, 0, 0
                            'CALL UpdatePower(CB.HNDL)              'multiply 'em together- doesn't update with drop down list
        
                        CASE %IDC_COMBOBOX2
                            PostMessage CB.HNDL, %UM_UpdatePower, 0, 0
                            'CALL UpdatePower(CB.HNDL)              'as above
        
                        CASE %IDC_TEXTBOX1
                            IF CB.CTLMSG = %EN_CHANGE THEN         'filter doesn't do much
                                'CALL UpdateOnNewPower(CB.HNDL)
                            END IF
                    END SELECT
        
                CASE %UM_UPDATEPOWER
                    CALL UpdatePower(CB.HNDL)
            END SELECT
        END FUNCTION
        '------------------------------------------------------------------------------
        
        '------------------------------------------------------------------------------
        '   ** Sample Code **
        '------------------------------------------------------------------------------
        FUNCTION SampleComboBox(BYVAL hDlg AS DWORD, BYVAL lID AS LONG, BYVAL lCount _
            AS LONG) AS LONG
            LOCAL i AS LONG
        
            CONTROL SEND hDlg, lID, %CB_SETEXTENDEDUI, %TRUE, 0
        
            FOR i = 1 TO lCount
                COMBOBOX ADD hDlg, lID, STR$(i)
            NEXT i
        END FUNCTION
        
        SUB UpdatePower(BYVAL tBox AS DWORD)                    'update power calculation if V or R is changed
            LOCAL Vout AS STRING
            LOCAL Res AS STRING
            CONTROL DISABLE tBox, %IDC_TEXTBOX1
            CONTROL GET TEXT tBox, %IDC_COMBOBOX1 TO Vout
            CONTROL GET TEXT tBox, %IDC_COMBOBOX2 TO Res
            CONTROL SET TEXT tBox, %IDC_TEXTBOX1, FORMAT$(VAL(Vout)*VAL(Res), "##0.0")
            CONTROL ENABLE tBox, %IDC_TEXTBOX1
        END SUB
        
        SUB UpdateOnNewPower(BYVAL tBox AS DWORD)               'update V if power is changed
            LOCAL Pwr AS STRING
            LOCAL Res AS STRING
            CONTROL GET TEXT tBox, %IDC_TEXTBOX1 TO Pwr
            CONTROL GET TEXT tBox, %IDC_COMBOBOX2 TO Res
            CONTROL SET TEXT tBox, %IDC_COMBOBOX1, FORMAT$(VAL(Pwr)/VAL(Res), "####.###")
        END SUB
        '------------------------------------------------------------------------------
        
        '------------------------------------------------------------------------------
        '   ** Dialogs **
        '------------------------------------------------------------------------------
        FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
            LOCAL lRslt  AS LONG
        
        #PBFORMS Begin Dialog %IDD_DIALOG1->->
            LOCAL hDlg   AS DWORD
            LOCAL hFont1 AS DWORD
            LOCAL hFont2 AS DWORD
        
            DIALOG NEW hParent, "Dialog1", 122, 142, 201, 126, %WS_OVERLAPPED OR _
                %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_MINIMIZEBOX 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 COMBOBOX, hDlg, %IDC_COMBOBOX1, , 15, 10, 60, 60, %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %CBS_DROPDOWN, _
                %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
            CONTROL ADD COMBOBOX, hDlg, %IDC_COMBOBOX2, , 15, 45, 60, 60, %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %CBS_DROPDOWN, _
                %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
            CONTROL ADD TEXTBOX,  hDlg, %IDC_TEXTBOX1, "", 115, 15, 60, 30
            CONTROL ADD LABEL,    hDlg, %IDC_LABEL1, "=", 90, 20, 20, 20
            CONTROL ADD LABEL,    hDlg, %IDC_LABEL2, "X", 35, 25, 20, 15
        
            'hFont1 = PBFormsMakeFont("MS Sans Serif", 24, 400, %FALSE, %FALSE, _
            '    %FALSE, %ANSI_CHARSET)
            'hFont2 = PBFormsMakeFont("MS Sans Serif", 18, 400, %FALSE, %FALSE, _
            '    %FALSE, %ANSI_CHARSET)
        
            'CONTROL SEND hDlg, %IDC_LABEL1, %WM_SETFONT, hFont1, 0
            'CONTROL SEND hDlg, %IDC_LABEL2, %WM_SETFONT, hFont2, 0
        #PBFORMS End Dialog
        
            SampleComboBox hDlg, %IDC_COMBOBOX1, 30
            SampleComboBox hDlg, %IDC_COMBOBOX2, 30
        
            DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
        
        #PBFORMS Begin CleanUp %IDD_DIALOG1
            DeleteObject hFont1
            DeleteObject hFont2
        #PBFORMS End CleanUp
        
            FUNCTION = lRslt
        END FUNCTION
        '------------------------------------------------------------------------------
        I think what's happening is that if you update the textbox when you get the notification message, the actual combo TEXT hasn't been updated yet, so you get the old value and hence calculate the old result. Posting a custom message puts the update at the end of the message queue, so it gets processed later, when the combo box has updated, so you get the correct text.

        I hope that helps.

        Regards,

        Pete.

        Comment


        • #5
          Multiple messages get sent. %CBN_SELCHANGE %CBN_EDITUPDATE are sent before the text box portion is updated, %CBN_EDITCHANGE is sent after.

          Once %CBN_EDITCHANGE is received then you can use CONTROL GET TEXT to retrieve the new info.

          Cheers,
          Dale

          Comment


          • #6
            Peter- that's exactly the sort of solution I was looking for, works a champ! Thanks! I started to mess with short sleep values here and there, which worked somewhat, but I always know the minute I need to insert delays, I'm way off on the wrong approach.

            Dale- from reading the help, I'd have expected it to work just as you describe, but there are still problems (thus my post here). Selecting from the list never fires editupdate or editchange at all. There is a close notification for the list, but it only works on the second try, indicating timing problems.

            Comment

            Working...
            X