BBC BASIC for Windows
Programming >> BBC BASIC language >> Another dialogue box question.
http://bb4w.conforums.com/index.cgi?board=language&action=display&num=1438801879

Another dialogue box question.
Post by CharlesB on Aug 5th, 2015, 7:11pm

For months now I have been wondering how I might set up a smarter dialogue box. For example, in my example below, the user has a number of boxes to supply necessary data.

This is for tubing and long radius bends.
If the user indicates the ID (inner diameter) and the OD (outer diameter), he/she does not need to enter the wall thickness.

On the other hand either the ID and wall is enough, or the OD and wall.

The same goes for the radii of the bend. All the program needs is the OD of the bend and either the top, center, or bottom radius to calculate all of the radii.

So, is there a way that I can gray out a box if the user gives enough information.

For example if the user supplies the OD and the wall, the ID box would gray out (or better yet, it would calculate and display the ID?)

Sorry if I'm back with my annoying questions, but I don't know how to go about doing this.
Thanks
Charles

Code:
      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

      rem These are the old values dlg%=FN_newdialog("NON STOCK Bends Quote", 20, 20, 160, 128, 8, 560)

      dlg%=fn_newdialog("NON STOCK Bends Quote", 20, 20, 225, 180, 10, 1200)
      proc_groupbox(dlg%, "Enter Degree   Enter Number", 0, 4, 4, 192, 96, WS_GROUP)
      rem PROC_editbox(dlg%, "Enter Degree", 101, 12, 20, 64, 12, ES_AUTOHSCROLL)
      rem proc_editbox(dlg%, "Enter OD", 101, 12, 20, 64, 12, ES_AUTOHSCROLL)

      rem proc_dlgctrl(dlg%, "", 109, 0, 0, 12, 12, WS_VISIBLE or WS_CHILD or \
      rem \ UDS_AUTOBUDDY or UDS_ALIGNRIGHT or UDS_SETBUDDYINT, "msctls_updown32")
      proc_editbox(dlg%, "ID", 103, 12, 20, 64, 15, ES_AUTOHSCROLL)
      proc_editbox(dlg%, "OD", 101, 12, 40, 64, 12, ES_AUTOHSCROLL)
      proc_editbox(dlg%, "Wall", 102, 82, 20, 64, 12, ES_AUTOHSCROLL)
      proc_editbox(dlg%, "Degree",104,82,40,64,14,ES_AUTOHSCROLL)
      proc_editbox(dlg%, "Center-Line Radius", 110, 82, 65, 64, 12, ES_AUTOHSCROLL)
      proc_editbox(dlg%, "or Bottom-Arc Rad", 111, 150, 85, 64, 12, ES_AUTOHSCROLL)
      proc_editbox(dlg%, "or Top-Arc Rad", 112, 82, 85, 64, 12, ES_AUTOHSCROLL)
      proc_editbox(dlg%, "Left Tangent", 105, 12, 64, 64, 10, ES_AUTOHSCROLL)
      proc_editbox(dlg%, "Right Tangent", 106, 12, 82, 64, 10,ES_AUTOHSCROLL)
      proc_editbox(dlg%, "QTY", 122, 155, 20, 50, 12, ES_AUTOHSCROLL)
      proc_dlgctrl(dlg%, "", 109, 0, 0, 12, 12, WS_VISIBLE or WS_CHILD or \
      \ UDS_AUTOBUDDY or UDS_ALIGNRIGHT or UDS_SETBUDDYINT, "msctls_updown32")

      proc_listbox(dlg%, "Special Chg", 120, 82, 105, 64, 42, -2)

      proc_listbox(dlg%, "Select", 115, 10, 110, 64, 38, -2)
      rem proc_radiobutton(dlg%, "Std Tangents", 105, 12, 64, 64, 10, 0)
      rem proc_radiobutton(dlg%, "Extd Tangents", 106, 12, 82, 64, 10, 0)
      proc_pushbutton(dlg%, "OK", 1, 12, 155, 56, 14, WS_GROUP or BS_DEFPUSHBUTTON)
      proc_pushbutton(dlg%, "Cancel", 2, 92, 155, 56, 14, 0)
      proc_showdialog(dlg%)
 

Re: Another dialogue box question.
Post by Torro on Aug 5th, 2015, 9:48pm

This is why we need a dlg /forms designer

Re: Another dialogue box question.
Post by Zaphod on Aug 5th, 2015, 11:04pm

Well you can control the code with interrupts. If you use *SYS 1 you will get notifications from the edit boxes when you enter, change its contents and by deduction when you exit. So you don't need to grey out anything as you can have it live dependent on which box was changed.
So if the ID is the fixed value then look to see if the wall thickness is being changed and either recalculate OD as the number is put in or wait for that edit box to be exited and then update the OD. Similarly if the entry was the OD then update the wall. Just be careful that you don't get into loops chasing your own tail.
Or you could just detect the first box of the Wall or OD to be changed and then use the EnableWindow API to stop key entry into the other one. Not sure when you reset that, but that is up to you.

Hope this helps.
Re: Another dialogue box question.
Post by Zaphod on Aug 5th, 2015, 11:13pm

Quote:
This is why we need a dlg /forms designer


Not sure if you are aware of the various offering on the Yahoo group files (you need to be a member to access), but there was a community effort that did produce some results.
https://groups.yahoo.com/neo/groups/bb4w/files/Tools/Dialog%20Editor%20Community%20Ed./

Or if you are into interrupt driven code then there was an effort to translate ResEdit files to BB4W which is in here:
https://groups.yahoo.com/neo/groups/bb4w/files/%22Temp%20Folder%22/Event_Programming/
ResEdit has a reasonable GUI creation for Dialogs and Menus.

Those are the best options that exist at the moment and all those authors have vacated the space since.

Re: Another dialogue box question.
Post by Torro on Aug 6th, 2015, 07:00am

From access app

Why do you want to grey it out? Do you want to make it inactive, or just color it?


If you want to make it inactive, you click on the field in design view, go to its properties dialog box, then click the Data tab, and select Enabled = No. This will grey it out.

If you want to make this conditional based on some value (in a record, for example) then you check the condition, and use:

Me.TextBox.Enabled = False

I am pretty sure that last line will work. The code may be slightly different.



For BBC BW specific looks like you need to see howm properties are set Enabled=false
Re: Another dialogue box question.
Post by DDRM on Aug 6th, 2015, 08:13am

To inactivate (grey out) the control, you will need to change the style of the (edit control) window. As Torro suggests, you can do this when you set it up, but as I understand it, you want to do it dynamically, as data is entered. In that case you will need to be checking when data gets entered into controls, and then inactivating the relevant control, using the code listed in the manual, under "Dialogue boxes":

Disabling and enabling dialogue box items
You may wish to disable one or more items in a dialogue box, for example you may want to disable a button if it is not appropriate to click it in the current circumstances. An item which is disabled is shown in grey.
To disable an item you can use the EnableWindow API call:

SYS "GetDlgItem", !dlg%, id% TO h%
SYS "EnableWindow", h%, 0

Here id% is the identifier of the button you want to affect. To re-enable the item change the zero to a one:
SYS "GetDlgItem", !dlg%, id% TO h%
SYS "EnableWindow", h%, 1

Note that, as with initialisation, these routines must be executed after the call to PROC_showdialog.

I haven't tried that on an edit box, but the wording suggests it should work.

On the other hand, do you really want to grey it out? That would mean that the user could never subsequently alter it, except indirectly. Would it be better to change it to the implied dimension, so the user can see if that is OK? You would need to decide an order of priority for what happens if all three are set, then one is changed - for example, you might decide inner and outer diameter had priority, and thickness would be set accordingly - or you could check which one had changed, and adjust one of the others according to some rule.

Best wishes,
D
Re: Another dialogue box question.
Post by Zaphod on Aug 8th, 2015, 02:35am

So here is one approach to having live input boxes.
This demo is just for three boxes but clearly could be extended.
The program is interrupt driven entirely using event library files that are on the Yahoo group temp files folder.
https://groups.yahoo.com/neo/groups/bb4w/files/%22Temp%20Folder%22/
You must get these and either copy into the end of the program or place in your LIB folder along with the other BB4W Library files. That may need Admin rights.
It is in UPPERCASE keywords, so you may need to adjust your options since you seem to like lower case (not recommended).
Sorry the code is quite long and the library files won't fit the space here:-
Code:
 
     REM Event driven demo of live ID-OD-Wall calculation.

      INSTALL @lib$+"VElib" : REM Event queue and polling.
      INSTALL @lib$+"VDlib" : REM Links controls to event procedures.
      INSTALL @lib$+"WINLIB2"

      PROC_trapok(PROCok)       :REM forwards OK button to PROC ok
      PROC_trapcancel(PROCcancel)

      PROCconstants : REM IMPORTANT!  Call the Add Windows Constants Utility before running!

      Dialog1% = FN_newdialog( "Dialog", 0, 0, 210, 89,8,550)
      Dialog1%!16= DS_3DLOOK OR DS_CENTER OR DS_MODALFRAME OR DS_SHELLFONT OR WS_CAPTION OR WS_VISIBLE OR WS_POPUP OR WS_SYSMENU
      IDcancel%=FN_dlgbutton("Cancel", IDCANCEL, 136, 65, 50, 14, 0,Dialog1%)
      IDok%=FN_dlgbutton("OK", IDOK, 69, 65, 50, 14, 0+1,Dialog1%)
      id%=FN_dlgstatic("ID", PROCdummy,  19, 17, 8, 9, SS_LEFT,Dialog1%)
      od%=FN_dlgstatic("OD", PROCdummy,  83, 17, 12, 9, SS_LEFT,Dialog1%)
      wall%=FN_dlgstatic("Wall", PROCdummy, 153, 17, 15, 9, SS_LEFT,Dialog1%)
      IDedittext1%=FN_dlgeditbox("", PROCedittext1(), 17, 29, 40, 14, ES_AUTOHSCROLL,Dialog1%)
      IDedittext2%=FN_dlgeditbox("", PROCedittext2(), 83, 29, 40, 14, ES_AUTOHSCROLL,Dialog1%)
      IDedittext3%=FN_dlgeditbox("", PROCedittext3(), 153, 29, 40, 14, ES_AUTOHSCROLL,Dialog1%)

      REM End of Dialog1 definition

      HDialog1%= FN_showdialog(Dialog1%) :REM this code will probably be relocated to an event procedure.
      ON CLOSE PROCclose
      ON ERROR SYS "MessageBox", @hwnd%, REPORT$, 0, 48 :PROCclose
      REM DO NOT write any ON SYS line or the DoEvent routing will fail!!!

      PROCinit :REM Initialize the dialog in this procedure.

      Wall%=TRUE  :REM set default. It will get overriden but must be declared before it first gets used.

      REM =========== Event processing loop ===============

      REPEAT
        PROC_DoEvents
      UNTIL FALSE OR HDialog1% =0
      QUIT
      END

      DEF PROCclose
      HDialog1%+=0: IF HDialog1% PROC_destroydialog(HDialog1%)
      QUIT
      ENDPROC

      DEF PROCinit
      REM See http://msdn.microsoft.com/en-us/library/windows/desktop/bb773169%28v=vs.85%29.aspx
      REM Not needed here but we can zero things, say.
      SYS"SetDlgItemText",HDialog1%, IDedittext1% , "0"
      SYS"SetDlgItemText",HDialog1%, IDedittext2% , "0"
      SYS"SetDlgItemText",HDialog1%, IDedittext3% , "0"
      ENDPROC

      DEF PROCcancel
      REM cancel click
      PROCclose
      ENDPROC
      :
      DEF PROCok
      REM ok click.
      LOCAL buffer%, id, od, wall
      DIM buffer% LOCAL 255
      SYS"GetDlgItemText", HDialog1%, IDedittext1% , buffer%, 255 : id=VAL($$buffer%)
      SYS"GetDlgItemText", HDialog1%, IDedittext2% , buffer%, 255 : od=VAL($$buffer%)
      SYS"GetDlgItemText", HDialog1%, IDedittext3% , buffer%, 255 : wall=VAL($$buffer%)
      PRINT "ID = ";id, "  Wall = "; wall, "  OD = "; od
      WAIT 500 :REM Just for display
      PROCclose
      ENDPROC
      :
      DEF PROCedittext1(m%,w%,l%)
      REM Edittext1
      REM If this changes reset the calculation. (It could be programmed with a bit of thought to have this interactive too)
      PRIVATE id
      LOCAL new_id, buffer%
      DIM buffer% LOCAL 255
      SYS"GetDlgItemText", HDialog1%, IDedittext1% , buffer%, 255 : new_id=VAL($$buffer%)
      IF new_id <> id THEN
        REM Reset od and wall
        SYS"SetDlgItemText", HDialog1%, IDedittext2%, "0"
        SYS"SetDlgItemText", HDialog1%, IDedittext3%, "0"
      ENDIF
      id=new_id
      ENDPROC
      :
      DEF PROCedittext2(m%,w%,l%)
      REM Edittext2  OD
      REM w% contains the notification code
      CASE w% OF
        WHEN EN_SETFOCUS:  Wall%=FALSE :REM Wall% is Global in scope.
        WHEN EN_KILLFOCUS:
        WHEN EN_CHANGE: PROCupdate
      ENDCASE
      ENDPROC
      :
      DEF PROCedittext3(m%,w%,l%)
      REM Edittext3  Wall
      CASE w% OF
        WHEN EN_SETFOCUS:  Wall%=TRUE
        WHEN EN_KILLFOCUS: Wall%=FALSE
        WHEN EN_CHANGE: PROCupdate
      ENDCASE
      ENDPROC
      :
      DEF PROCdummy
      REM Nothing is going to get here.
      ENDPROC

      DEF PROCconstants
      REM!WC 
      EN_CHANGE = 768
      EN_KILLFOCUS = 512
      EN_SETFOCUS = 256
      DS_3DLOOK = 4
      DS_CENTER = &800
      DS_MODALFRAME = &80
      DS_SHELLFONT = 72
      ES_AUTOHSCROLL = &80
      IDCANCEL = 2
      IDOK = 1
      SS_LEFT = 0
      WS_CAPTION = &C00000
      WS_POPUP = &80000000
      WS_SYSMENU = &80000
      WS_VISIBLE = &10000000
      ENDPROC

      DEF PROCupdate
      REM Calculate OD or Wall depending on Wall% state.
      REM Read the edit box contents
      LOCAL buffer%, old_id, old_wall, od, id, wall :REM od, id and wall could be Global.
      DIM buffer% LOCAL 255
      SYS"GetDlgItemText", HDialog1%, IDedittext1% , buffer%, 255 : id=VAL($$buffer%)
      SYS"GetDlgItemText", HDialog1%, IDedittext2% , buffer%, 255 : old_od=VAL($$buffer%)
      SYS"GetDlgItemText", HDialog1%, IDedittext3% , buffer%, 255 : old_wall=VAL($$buffer%)
      REM Now to make sure we don't keep on running in update loops only change if needed.
      REM Writing to the OD or Wall will cause an EN_CHANGE event and bring us back here
      REM so we have to put in some conditions to allow the update.
      IF Wall% THEN
        od=id+2*old_wall
        IF od=old_od THEN ENDPROC  :REM Exit as fast as we can.
        REM Now we can write back to new data OD.
        SYS"SetDlgItemText", HDialog1%, IDedittext2%, STR$(od)
      ELSE
        wall=(old_od-id)/2
        IF wall=old_wall THEN ENDPROC
        SYS"SetDlgItemText", HDialog1%, IDedittext3%, STR$(wall)
      ENDIF
      ENDPROC

      REM End of demo
REM ======================================
      REM Libraries from Yahoo group files could go here.
 


So I appreciate that this may not mean a lot until you get to grips with event driven programming but it will make life so much easier if you do.
For more details I can be found here:
zaphod dot g dot beeblebrox at gmail dot com

Re: Another dialogue box question.
Post by Zaphod on Aug 8th, 2015, 1:32pm

And finally the answer you were probably looking for, the procedural version. Stripped down and works.
Note that it will not catch quite a few events but in a simple case you probably will not notice. All event notifications from the edit box trigger the same procedure which limits your flexibility but for a beginner I don't think you will be bothered. Later as sophistication grows you might want to separate out the events and catch them all. The previous program does that!

Code:
      INSTALL @lib$+"WINLIB2"

      PROCconstants

      Dialog1% = FN_newdialog( "Dialog", 0, 0, 210, 89,8,550)
      PROC_pushbutton(Dialog1%,"Cancel", IDCANCEL, 136, 65, 50, 14, 0)
      PROC_pushbutton(Dialog1%,"OK", IDOK, 69, 65, 50, 14, 1)
      PROC_static(Dialog1%,"ID",-1,  19, 17, 8, 9, SS_LEFT)
      PROC_static(Dialog1%,"OD", -1,  83, 17, 12, 9, SS_LEFT)
      PROC_static(Dialog1%,"Wall", -1, 153, 17, 15, 9, SS_LEFT)
      PROC_editbox(Dialog1%,"", 101, 17, 29, 40, 14, ES_AUTOHSCROLL)
      PROC_editbox(Dialog1%,"", 102, 83, 29, 40, 14, ES_AUTOHSCROLL)
      PROC_editbox(Dialog1%,"", 103, 153, 29, 40, 14, ES_AUTOHSCROLL)

      PROC_showdialog(Dialog1%)

      ON CLOSE PROCclose
      ON ERROR SYS "MessageBox", @hwnd%, REPORT$, 0, 48 :PROCclose

      PROCinit :REM Initialize the dialog in this procedure.

      Wall%=TRUE  :REM set default. It will get overriden but must be declared before it first gets used.

      ON SYS E%=@wparam%:RETURN

      REM Main polling loop.
      REPEAT
      WAIT 10
        IF E% THEN
          CASE E% AND &FFFF OF
            WHEN 1: PROCok
            WHEN 101: PROCid
            WHEN 102: PROCod
            WHEN 103: PROCwall
            OTHERWISE
          ENDCASE
        ENDIF
      UNTIL FALSE OR !Dialog1%=0

      END

      DEF PROCconstants
      REM!WC
      ES_AUTOHSCROLL = &80
      IDCANCEL = 2
      IDOK = 1
      SS_LEFT = 0
      ENDPROC

      DEF PROCinit
      REM See http://msdn.microsoft.com/en-us/library/windows/desktop/bb773169%28v=vs.85%29.aspx
      REM Not needed here but we can zero things, say.
      SYS"SetDlgItemText",!Dialog1%, 101, "0"
      SYS"SetDlgItemText",!Dialog1%, 102, "0"
      SYS"SetDlgItemText",!Dialog1%, 103, "0"
      ENDPROC

      DEF PROCclose
      Dialog1%+=0: IF Dialog1% PROC_closedialog(Dialog1%)
      QUIT
      ENDPROC

      DEF PROCok
      REM ok click.
      LOCAL buffer%, id, od, wall
      DIM buffer% LOCAL 255
      SYS"GetDlgItemText", !Dialog1%, 101 , buffer%, 255 : id=VAL($$buffer%)
      SYS"GetDlgItemText", !Dialog1%, 102 , buffer%, 255 : od=VAL($$buffer%)
      SYS"GetDlgItemText", !Dialog1%, 103 , buffer%, 255 : wall=VAL($$buffer%)
      PRINT "ID = ";id, "  Wall = "; wall, "  OD = "; od
      PROC_closedialog(Dialog1%)
      WAIT 500 :REM Just for display
      PROCclose
      ENDPROC

      DEF PROCid
      REM If this changes reset the calculation. (It could be programmed with a bit of thought to have this interactive too)
      PRIVATE id
      LOCAL new_id, buffer%
      DIM buffer% LOCAL 255
      SYS"GetDlgItemText", !Dialog1%, 101 , buffer%, 255 : new_id=VAL($$buffer%)
      IF new_id <> id THEN
        REM Reset od and wall
        SYS"SetDlgItemText", !Dialog1%, 102, "0"
        SYS"SetDlgItemText", !Dialog1%, 103, "0"
      ENDIF
      id=new_id
      ENDPROC

      DEF PROCod
      REM Edittext2  OD
      Wall%=FALSE :REM Wall% is Global in scope.
      PROCupdate
      ENDPROC

      DEF PROCwall
      Wall%=TRUE
      PROCupdate
      ENDPROC

      DEF PROCupdate
      REM Calculate OD or Wall depending on Wall% state.
      REM Read the edit box contents
      LOCAL buffer%, old_id, old_wall, od, id, wall :REM od, id and wall could be Global.
      DIM buffer% LOCAL 255
      SYS"GetDlgItemText", !Dialog1%, 101 , buffer%, 255 : id=VAL($$buffer%)
      SYS"GetDlgItemText", !Dialog1%, 102 , buffer%, 255 : old_od=VAL($$buffer%)
      SYS"GetDlgItemText", !Dialog1%, 103, buffer%, 255 : old_wall=VAL($$buffer%)
      REM Now to make sure we don't keep on running in update loops only change if needed.
      REM Writing to the OD or Wall will cause an EN_CHANGE event and bring us back here
      REM so we have to put in some conditions to allow the update.
      IF Wall% THEN
        od=id+2*old_wall
        IF od=old_od THEN ENDPROC  :REM Exit as fast as we can.
        REM Now we can write back to new data OD.
        SYS"SetDlgItemText", !Dialog1%, 102, STR$(od)
      ELSE
        wall=(old_od-id)/2
        IF wall=old_wall THEN ENDPROC
        SYS"SetDlgItemText", !Dialog1%, 103, STR$(wall)
      ENDIF
      ENDPROC
 

Re: Another dialogue box question.
Post by CharlesB on Aug 13th, 2015, 8:58pm

Thanks so much for your help.
I ended up asking the same question today! I thought that I aborted my last attempt at this question.

But, in any event, I have lots to go on now and will get to school on it.

Thank you so much for your help.
Charles
Re: Another dialogue box question.
Post by CharlesB on Aug 13th, 2015, 9:07pm

Again, thank you all for your kindness.
Zaphoid, your examples really helped.

All of the comments were very helpful, but somewhat over my head. But I am getting the gist of some principles now.

Thank you,
Charles