BBC BASIC for Windows
Programming >> User Interface >> Identifying changes to controls
http://bb4w.conforums.com/index.cgi?board=ui&action=display&num=1401706771

Identifying changes to controls
Post by g3nrw on Jun 2nd, 2014, 10:59am

Another question if I may.

I need to identify when a user changes the value of a control. I have been using "*SYS 1", and then "ON SYS PROCcontrolChange".

"PROCcontrolChange" reads "@msg%" and "@wparam%" to identify the affected control. In every case, @msg% = 273 (WM_COMMAND).

"@wparam% AND &FFFF" correctly identifies individual List boxes, Text boxes, Combo boxes and Numeric Variable up/down boxes. However, Radio Buttons and Checkboxes are incorrectly identified as Text boxes.

Is there a BB4W example anywhere that shows how to do this properly?

--
Ian

Re: Identifying changes to controls
Post by rtr on Jun 2nd, 2014, 12:03pm

on Jun 2nd, 2014, 10:59am, g3nrw wrote:
Is there a BB4W example anywhere that shows how to do this properly?

There is no one 'proper' way. For example if it is essential to know in which order the ON SYS events occurred then you will need to use an event queue, but if you don't care about the order then that may be unnecessary.

Similarly if it is essential that you never miss an event then that will put certain requirements on the code, whereas if you don't mind missing an event (so long as you are guaranteed to see the last event of a 'burst') that points to a different technique being appropriate.

This Wiki article discusses some of those issues, and offers various different approaches depending on the needs of your program:

http://bb4w.wikispaces.com/Queueing+event+interrupts

You can also consider using the EVENTLIB library.

Richard.

Re: Identifying changes to controls
Post by g3nrw on Jun 2nd, 2014, 7:59pm

Thanks Richard. All understood.

I finally tracked down your message describing EVENTLIB at:

http://bb4w.conforums.com/index.cgi?board=libraries&action=display&num=1331378257

I think this will do the trick.

--
Ian

Re: Identifying changes to controls
Post by g3nrw on Jun 6th, 2014, 8:45pm

Getting closer here, but still no cigar.

Here is a skeleton program using EVENTLIB that I thought would let me identify a control when a user clicks on it. The program is essentially DLGDEMO, but with an extra checkbox thrown in for good measure.

The "INTERESTING BIT" is at the end, and is hopefully self-explanatory. Basically, what I hoped would happen is the that message box reports the control ID, but this does not happen every time.

Sometimes msgbox reports multiple times, with previous (wrong) IDs, before it finally reports the correct ID.

Sometimes msgbox reports the correct ID multiple times.

Ideas?

Code:
      REM. Program to demonstrate a Dialogue Box
      INSTALL @lib$+"WINLIB2"

      BS_DEFPUSHBUTTON = &1
      CB_ADDSTRING = &143
      CB_SETCURSEL = &14E
      CBS_DROPDOWNLIST = &3
      ES_AUTOHSCROLL = &80
      ES_NUMBER = &2000
      LB_ADDSTRING = &180
      LB_GETCURSEL = &188
      UDM_SETRANGE = &465
      UDS_ALIGNRIGHT = &4
      UDS_AUTOBUDDY = &10
      UDS_SETBUDDYINT = &2
      WS_CHILD = &40000000
      WS_GROUP = &20000
      WS_VISIBLE = &10000000
      WM_COMMAND = 273

      editboxTextBox% = 900

      editboxNumber% = 901

      dlgctrlNumberBox% = 902

      comboboxDropDown% = 903

      listboxList% = 904

      radiobuttonButton1% = 905
      radiobuttonButton2% = 906

      checkboxCheckbox1% = 907
      checkboxCheckbox2% = 908

      pushbuttonOK% = 1
      pushbuttonCancel% = 2


      dlg%=FN_newdialog("Dialogue box", 20, 20, 160, 128, 8, 1024)
      PROC_groupbox(dlg%, "Group box", 0, 4, 4, 152, 96, WS_GROUP)

      PROC_editbox(dlg%, "Text box", editboxTextBox%, 12, 20, 64, 12, ES_AUTOHSCROLL)

      PROC_editbox(dlg%, "123456", editboxNumber%, 82, 20, 64, 12, ES_NUMBER)
      PROC_dlgctrl(dlg%, "", dlgctrlNumberBox%, 0, 0, 12, 12, WS_VISIBLE OR WS_CHILD OR \
      \ UDS_AUTOBUDDY OR UDS_ALIGNRIGHT OR UDS_SETBUDDYINT, "msctls_updown32")

      PROC_combobox(dlg%, "", comboboxDropDown%, 12, 40, 64, 60, CBS_DROPDOWNLIST)

      PROC_listbox(dlg%, "", listboxList%, 82, 40, 64, 48, 0)

      PROC_radiobutton(dlg%, "Radiobutton 1", radiobuttonButton1%, 12, 64, 64, 10, 0)
      PROC_radiobutton(dlg%, "Radiobutton 2", radiobuttonButton2%, 12, 82, 64, 10, 0)

      PROC_checkbox(dlg%, "Checkbox1", checkboxCheckbox1%, 82, 82, 64, 10, 0)
      PROC_checkbox(dlg%, "Checkbox2", checkboxCheckbox2%, 82, 10, 64, 10, 0)

      PROC_pushbutton(dlg%, "OK", pushbuttonOK%, 12, 108, 56, 14, WS_GROUP OR BS_DEFPUSHBUTTON)

      PROC_pushbutton(dlg%, "Cancel", pushbuttonCancel%, 92, 108, 56, 14, 0)

      PROC_showdialog(dlg%)

      ON CLOSE PROC_closedialog(dlg%):QUIT
      ON ERROR PROC_closedialog(dlg%):PRINT'REPORT$:END

      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 1"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 2"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 3"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 4"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 5"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 6"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 7"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 8"

      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_SETCURSEL, 3, 0

      SYS "SendDlgItemMessage", !dlg%, listboxList%, LB_ADDSTRING, 0, "Listbox item 0"
      SYS "SendDlgItemMessage", !dlg%, listboxList%, LB_ADDSTRING, 0, "Listbox item 1"
      SYS "SendDlgItemMessage", !dlg%, listboxList%, LB_ADDSTRING, 0, "Listbox item 2"
      SYS "SendDlgItemMessage", !dlg%, listboxList%, LB_ADDSTRING, 0, "Listbox item 3"

      SYS "CheckRadioButton", !dlg%, radiobuttonButton1%, radiobuttonButton2%, radiobuttonButton2%

      SYS "SendDlgItemMessage", !dlg%, dlgctrlNumberBox%, UDM_SETRANGE, 0, 15


      REM --------------------- START OF THE INTERESTING BIT --------------


      INSTALL @lib$+"EVENTLIB"

      PROC_eventinit

      PROC_eventregister(WM_COMMAND, PROCgetControlID())

      REPEAT
        PROC_eventpoll
        WAIT 100
      UNTIL FALSE

      END

      DEF PROCgetControlID(M%, W%, L%)

      ControlNo% = W% AND &FFFF

      CASE TRUE OF
        WHEN (ControlNo% > 899) AND (ControlNo% < 909) :
          ControlID$ = STR$(ControlNo%)
    
        OTHERWISE ControlID$ = "Unknown " + STR$(ControlNo%)
    
      ENDCASE

      SYS "MessageBox", @hwnd%, "M%= " + STR$(M%) + "  Control ID= " + ControlID$, "",0


      ENDPROC


 






Re: Identifying changes to controls
Post by rtr on Jun 6th, 2014, 10:15pm

on Jun 6th, 2014, 8:45pm, g3nrw wrote:
Ideas?

I don't see anything obviously wrong when I run it, but the program's design does make analysis of the results difficult.

Firstly, reporting the events with a message box is not ideal, because if multiple events need to be reported you can only see them sequentially in isolation. I would far rather list the events in the 'main window' so you can see them together as a group.

Secondly, you don't report what the event actually is, only the control with which it is associated! For example suppose you click on a button; typically that may result in three events: a focus lost event from the control which previously had the input focus, a focus gained event from the control you clicked on, and a button clicked event. As the program stands all you would see is an event from one control followed by two events from another control, but no context.

Thirdly, the WAIT 100 in the event-polling loop is ridiculously long - that's a whole second! A WAIT 1 is more than sufficient.

If you report the events in a list, and include information on what kind of event it was, I suspect you will find that everything is working exactly as you would expect.

Edit: Listed below a program with the suggested changes. I can see nothing untoward in the results.

Richard.

Code:
      REM. Program to demonstrate a Dialogue Box
      INSTALL @lib$+"WINLIB2"

      REM!WC
      BN_CLICKED = 0
      BS_DEFPUSHBUTTON = 1
      CB_ADDSTRING = 323
      CB_SETCURSEL = 334
      CBN_CLOSEUP = 8
      CBN_DROPDOWN = 7
      CBN_KILLFOCUS = 4
      CBN_SELCHANGE = 1
      CBN_SELENDCANCEL = &A
      CBN_SELENDOK = 9
      CBN_SETFOCUS = 3
      CBS_DROPDOWNLIST = 3
      EN_CHANGE = 768
      EN_KILLFOCUS = 512
      EN_SETFOCUS = 256
      EN_UPDATE = &400
      ES_AUTOHSCROLL = &80
      ES_NUMBER = 8192
      LB_ADDSTRING = 384
      LBN_KILLFOCUS = 5
      LBN_SELCHANGE = 1
      LBN_SETFOCUS = 4
      UDM_SETRANGE = &465
      UDN_DELTAPOS = -722
      UDS_ALIGNRIGHT = 4
      UDS_AUTOBUDDY = 16
      UDS_SETBUDDYINT = 2
      WM_COMMAND = 273
      WS_CHILD = &40000000
      WS_GROUP = &20000
      WS_VISIBLE = &10000000

      editboxTextBox% = 900

      editboxNumber% = 901

      dlgctrlNumberBox% = 902

      comboboxDropDown% = 903

      listboxList% = 904

      radiobuttonButton1% = 905
      radiobuttonButton2% = 906

      checkboxCheckbox1% = 907
      checkboxCheckbox2% = 908

      pushbuttonOK% = 1
      pushbuttonCancel% = 2


      dlg%=FN_newdialog("Dialogue box", 360, 20, 160, 128, 8, 1024)
      PROC_groupbox(dlg%, "Group box", 0, 4, 4, 152, 96, WS_GROUP)

      PROC_editbox(dlg%, "Text box", editboxTextBox%, 12, 20, 64, 12, ES_AUTOHSCROLL)

      PROC_editbox(dlg%, "123456", editboxNumber%, 82, 20, 64, 12, ES_NUMBER)
      PROC_dlgctrl(dlg%, "", dlgctrlNumberBox%, 0, 0, 12, 12, WS_VISIBLE OR WS_CHILD OR \
      \ UDS_AUTOBUDDY OR UDS_ALIGNRIGHT OR UDS_SETBUDDYINT, "msctls_updown32")

      PROC_combobox(dlg%, "", comboboxDropDown%, 12, 40, 64, 60, CBS_DROPDOWNLIST)

      PROC_listbox(dlg%, "", listboxList%, 82, 40, 64, 48, 0)

      PROC_radiobutton(dlg%, "Radiobutton 1", radiobuttonButton1%, 12, 64, 64, 10, 0)
      PROC_radiobutton(dlg%, "Radiobutton 2", radiobuttonButton2%, 12, 82, 64, 10, 0)

      PROC_checkbox(dlg%, "Checkbox1", checkboxCheckbox1%, 82, 82, 64, 10, 0)
      PROC_checkbox(dlg%, "Checkbox2", checkboxCheckbox2%, 82, 10, 64, 10, 0)

      PROC_pushbutton(dlg%, "OK", pushbuttonOK%, 12, 108, 56, 14, WS_GROUP OR BS_DEFPUSHBUTTON)

      PROC_pushbutton(dlg%, "Cancel", pushbuttonCancel%, 92, 108, 56, 14, 0)

      PROC_showdialog(dlg%)

      ON CLOSE PROC_closedialog(dlg%):QUIT
      ON ERROR PROC_closedialog(dlg%):PRINT'REPORT$:END

      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 1"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 2"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 3"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 4"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 5"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 6"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 7"
      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_ADDSTRING, 0, "Combobox 8"

      SYS "SendDlgItemMessage", !dlg%, comboboxDropDown%, CB_SETCURSEL, 3, 0

      SYS "SendDlgItemMessage", !dlg%, listboxList%, LB_ADDSTRING, 0, "Listbox item 0"
      SYS "SendDlgItemMessage", !dlg%, listboxList%, LB_ADDSTRING, 0, "Listbox item 1"
      SYS "SendDlgItemMessage", !dlg%, listboxList%, LB_ADDSTRING, 0, "Listbox item 2"
      SYS "SendDlgItemMessage", !dlg%, listboxList%, LB_ADDSTRING, 0, "Listbox item 3"

      SYS "CheckRadioButton", !dlg%, radiobuttonButton1%, radiobuttonButton2%, radiobuttonButton2%

      SYS "SendDlgItemMessage", !dlg%, dlgctrlNumberBox%, UDM_SETRANGE, 0, 15


      REM --------------------- START OF THE INTERESTING BIT --------------


      INSTALL @lib$+"EVENTLIB"

      PROC_eventinit

      PROC_eventregister(WM_COMMAND, PROCreportevent())

      REPEAT
        PROC_eventpoll
        WAIT 1
      UNTIL FALSE

      END

      DEF PROCreportevent(M%, W%, L%)
      LOCAL controlID%, notificationCode%

      controlID% = W% AND &FFFF
      notificationCode% = W% >> 16

      PRINT TIME$ ": Control "; controlID%; " sent notification ";

      CASE controlID% OF
        WHEN 900,901:
          CASE notificationCode% OF
            WHEN EN_KILLFOCUS:  PRINT "EN_KILLFOCUS"
            WHEN EN_SETFOCUS:   PRINT "EN_SETFOCUS"
            WHEN EN_CHANGE:     PRINT "EN_CHANGE"
            WHEN EN_UPDATE:     PRINT "EN_UPDATE"
            OTHERWISE PRINT "unknown"
          ENDCASE
        WHEN 903:
          CASE notificationCode% OF
            WHEN CBN_KILLFOCUS: PRINT "CBN_KILLFOCUS"
            WHEN CBN_SETFOCUS:  PRINT "CBN_SETFOCUS"
            WHEN CBN_SELCHANGE: PRINT "CBN_SELCHANGE"
            WHEN CBN_DROPDOWN:  PRINT "CBN_DROPDOWN"
            WHEN CBN_CLOSEUP:   PRINT "CBN_CLOSEUP"
            WHEN CBN_SELENDOK:  PRINT "CBN_SELENDOK"
            WHEN CBN_SELENDCANCEL: PRINT "CBN_SELENDCANCEL"
            OTHERWISE PRINT "unknown"
          ENDCASE
        WHEN 904:
          CASE notificationCode% OF
            WHEN LBN_KILLFOCUS: PRINT "LBN_KILLFOCUS"
            WHEN LBN_SETFOCUS:  PRINT "LBN_SETFOCUS"
            WHEN LBN_SELCHANGE: PRINT "LBN_SELCHANGE"
            OTHERWISE PRINT "unknown"
          ENDCASE
        WHEN 1,2,905,906,907,908:
          CASE notificationCode% OF
            WHEN BN_CLICKED:    PRINT "BN_CLICKED"
            OTHERWISE PRINT "unknown"
          ENDCASE
        OTHERWISE PRINT "unknown"
      ENDCASE

      ENDPROC