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