|
Post by klewlis on Jan 12, 2022 19:42:08 GMT -5
Rod's diagram in the "wait and scan in subs and functions" thread and Brandon Parkers comments in another thread, has me questioning some presumptions that I have not been able to verify through the help file. The information may be there, I just have not found it yet. I also do not see a way to do a search on the help file, except a manual one, which can be rather slow, clicking on each link that might provide some of the information I am seeking. When I run a program in the debugger, when my program exits a sub at the "end sub" statement it appears to return to the line immediately below the line that called the sub. Rod's diagram seems to suggest that if an event triggers a sub to be called, while the program is "waiting" at a wait statement, the exit from the sub will return the program to the wait statement, and not to the line immediately following it. Also apparent in Brandon's posted code. I am currently experimenting with this. This will certainly clean up my code and ease the task I have set before myself. Second, if a window is set up and opened in a sub, the window, all it's controls and event handlers are global? Does this mean my "event handler in a sub" for the "window in a sub" can be outside the window sub, or does it have to be inside the window sub? If it has to be inside the window sub how will my program find it while "waiting" in the main program, if it is scoped locally within the window sub. I am also experimenting with this now. I tend to build the different parts of a program as a separate program run them in the debugger both by stepping through them and running them in "animate" mode. Certain pieces I will create a .tkn and run it stand alone to be sure they work as intended. I then add the "tested code" to my main program and implement it as needed. I am by no means a career programmer, just a hobbyist. I code programs that make my 2 lives easier, (my life at home and my life at work ). If a window and the controls placed in it are global, can I set up a sub to create the window and create the controls in another sub that is not contained in the window sub, I am about to experiment with this. The worst I can do is break something, won't be a first or last.
|
|
|
Post by Rod on Jan 13, 2022 3:54:05 GMT -5
I will post more about searching the help file later. When you define windows and controls the handle variables you create are global. I would not usually use a sub to define or create controls I like to create everything at the head of the program. The reasons, if you create inside a sub you need to be sure that sub has been called before accessing anything it creates. Too easy to call something that has not yet been created.
So the windows and controls are global and their handles will work anywhere. But handlers are not. They are either [branch labels] or calls to subs. Obviously calls to subs are available anywhere. But to do that safely ALL handlers need to be subs including trap close and quit. If not there is the danger we are inside a sub when an external event fires and it’s external handler can’t be found.
Subs and functions, think about this. When you call a sub the obvious expectation is that you will return at the end sub point. Put a wait in a sub and you likely NEVER return. If you never return from any sub the stack just builds and builds.
When you call a sub it returns and continues at the line below, in my case a wait statement. I believe if it returns to a wait it continues to wait till another event pulls it elsewhere.
Janet had this to say in the LBPE
“Once a sub has been executed, program execution reverts to the state prior to calling the sub. In most cases, your program will need only one WAIT statement. Since the events are triggered by controls, there is no need for a single GOTO statement. In a recent discussion of Sub Events at the Liberty BASIC Forum, Carl Gundel, author of Liberty BASIC clarified, "WAIT does not use GOTO if your event handlers are all SUBs. The SUB will get executed, and when it is finished you will be left at the same WAIT statement."
|
|
|
Post by Rod on Jan 13, 2022 4:06:40 GMT -5
Stefan produced the best aid for exploring the help file. The help file does take a bit of getting used to. But make no mistake, even with this aid you need lots of reading time. libertybasiccom.proboards.com/post/11040
|
|
|
Post by klewlis on Jan 14, 2022 9:44:39 GMT -5
Janet had this to say in the LBPE “Once a sub has been executed, program execution reverts to the state prior to calling the sub. In most cases, your program will need only one WAIT statement. Since the events are triggered by controls, there is no need for a single GOTO statement. In a recent discussion of Sub Events at the Liberty BASIC Forum, Carl Gundel, author of Liberty BASIC clarified, "WAIT does not use GOTO if your event handlers are all SUBs. The SUB will get executed, and when it is finished you will be left at the same WAIT statement." Ah hah, this clarifies that question. I was previously unaware of this behavior. And until the whole question of why I would put a wait in a sub came up, I had never experimented with this.
|
|
|
Post by klewlis on Jan 14, 2022 10:02:21 GMT -5
Stefan produced the best aid for exploring the help file. The help file does take a bit of getting used to. But make no mistake, even with this aid you need lots of reading time. libertybasiccom.proboards.com/post/11040Yes, no doubt, a lot of reading time. Previously, this is how it has gone. Spend time looking at the contents page. Find a link that looks promising and click. Read everything on that page only to discover the information I seek is not there. About 40% of the time, I do find what I am looking for after several tries.
|
|
|
Post by klewlis on Jan 15, 2022 18:22:45 GMT -5
In an attempt to remove the wait from my subs, I ran into a problem. The second dialog window would open immediately after the first dialog window opened, and therefore would open on top of it. My goal is to keep the second dialog from opening until the first dialog is closed. I tried
While hwnd(#Instruct) > 0 Wend This of course worked great, until I closed the window. At that point #Instruct became an invalid device handle and broke the program. At this point, I declared a global variable, instructFlag, set it to =1 in the sub that opens the window. Then in the sub that closes the window I set it to =0 I used a global because the only thing passed from the button click is the handle of the button.
While working on this, it occurred to me that I could use the same sub to close either window, the button press would pass the buttons handle to the sub. With 20 radio buttons in the main window, I think I can handle all of them in the same sub. I would just have to read the buttons handle...
The while/wend will take up a lot of processor time, but the program is doing nothing else while the dialog is displayed. If anyone knows a better way to do this, I would be glad to have you chime in.
Just know that 80% of the program code has been cut out for this demo, in order to keep the code section of the post fairly short.
'----- Pre-window set up 'nomainwin WindowWidth = 1400 WindowHeight = 722 UpperLeftX = int((DisplayWidth-WindowWidth)/2) UpperLeftY = int((DisplayHeight-WindowHeight)/2)
MWW = 1400 MWH = 722
BackgroundColor$ = "lightgray" ForegroundColor$ = "black" TextboxColor$ = "white"
global BadInfo global instructFlag global MWW global MWH dim BldgInfo(4, 10) dim RftrInfo(4, 1000) dim group(4)
'----- Calculate button moved here to make it the last control in the tabbing order button #main.calc0, "Calculate", [GetInfo], UL, 1120, 602, 245, 60
'----- Open main window open "Rafter Master" for window_nf as #main print #main, "font ms_sans_serif 10" print #main.calc0, "!font ms_sans_serif 20 bold" print #main, "trapclose [quit.main]"
call instruct
'----- inserted While/Wend loop so that second dialog would not open unless first one was closed while instructFlag > 0 scan wend
call numFormat
'----- Wait for "instant" input or calculate button to be clicked '----- The intent is to fall into this branch label so I can return here from [GetInfo] which has been cut out for this demo [main.inputLoop] if BadInfo = 1 then x = 0 y = 0 end if wait
[GetInfo] wait
'----- End the program [quit.main] close #main end
sub instruct '----- Pre-window set up nomainwin WindowWidth = 550 WindowHeight = 445 UpperLeftX = int((MWW - WindowWidth) / 2) UpperLeftY = int((MWH - WindowHeight) / 2)
'----- Information to be displayed button #Instruct.button1,"GOT IT ", quit.dialog, UL, 455, 380, 70, 25 statictext #Instruct.statictext1, "ALL ROOF PITCHES MUST MATCH! ALL WALL HEIGHTS MUST MATCH!", 5, 5, 525, 20 statictext #Instruct.statictext2, "If there is enough interest, these features may be added at a later time", 5, 35, 450, 20 statictext #Instruct.statictext3, "This program will calculate rafter, ridge, hip and valley lengths.", 5, 75, 490, 20 statictext #Instruct.statictext4, "It will also calculate the following jack rafter lengths:", 5, 105, 325, 20 statictext #Instruct.statictext5, "Ridge to Valley, Hip to Wall, Hip to Valley and Ridge to Ridge.", 5, 135, 400, 20
'----- Open "about" window open "About Rafter Master" for dialog_modal as #Instruct print #Instruct, "font times_new_roman 12" print #Instruct, "trapclose quit.dialog" instructFlag = 1
end sub
'----- Explain measurement entry formatting sub numFormat '-----Pre-window set up nomainwin WindowWidth = 675 WindowHeight = 420 UpperLeftX = int((MWW - WindowWidth) / 2) UpperLeftY = int((MWH - WindowHeight) / 2)
'----- Information to display button #Format.button1,"GOT IT ", quit.dialog, UL, 565, 340, 90, 35
statictext #Format.statictext6, "When inputting measurements, the following conventions must be followed:", 5, 5, 600, 30 statictext #Format.statictext7, "Feet and inches must be separated with a dash, (e.g. 19-6).", 5, 55, 670, 30 statictext #Format.statictext8, "Foot, ('), and inch, (" + chr$(34) + "), marks are allowed, (e.g. 19'-6" + chr$(34) + "), but are not required.", 5, 105, 600, 30 statictext #Format.statictext9, "Use of the foot mark, (') does not require use of the inch mark, (e.g. 19'-6).", 5, 155, 620, 20 statictext #Format.statictext10, "Fractional inches must be separated from whole inches with a space, (e.g. 19-6 3/8).", 5, 205, 630, 20 statictext #Format.statictext11, "Decimal inches require a decimal point, (e.g. 19-6.375).", 5, 255, 550, 20 statictext #Format.statictext12, "Ridge Width must be expressed as inches only, (e.g. 1 1/2 or 1.5).", 5, 305, 550, 20 statictext #Format.statictext13, "Roof pitch must be expressed as a fraction, Rise / Run, (e.g. 6/12).", 5, 355, 550, 20
'----- Open format window open "Rafter Master Format Assistant" for dialog_modal as #Format print #Format, "font times_new_roman 14" 'print #Format.button1, "!font times_new_roman 12" print #Format, "trapclose quit.dialog"
end sub
'sub quit.instruct handle$ 'instructFlag = 0 'close #Instruct 'end sub
'sub quit.format handle$ 'close #Format 'end sub
sub quit.dialog handle$ handle$ = upto$(handle$, ".") if handle$ = "#Instruct" then instructFlag = 0 end if close #handle$ end sub
If using the same sub to close multiple windows is a bad idea, let me know and explain why.
|
|
|
Post by Brandon Parker on Jan 15, 2022 21:54:47 GMT -5
Just a note, this is one way that I might accomplish this type of task. If the second window needs to open immediately after the first, open the second window when the first window is closed. Then you have no need for a flag...
'----- Pre-window set up 'nomainwin WindowWidth = 1400 WindowHeight = 722 UpperLeftX = int((DisplayWidth-WindowWidth)/2) UpperLeftY = int((DisplayHeight-WindowHeight)/2)
MWW = 1400 MWH = 722
BackgroundColor$ = "lightgray" ForegroundColor$ = "black" TextboxColor$ = "white"
global BadInfo global instructFlag global MWW global MWH dim BldgInfo(4, 10) dim RftrInfo(4, 1000) dim group(4)
'----- Calculate button moved here to make it the last control in the tabbing order button #main.calc0, "Calculate", [GetInfo], UL, 1120, 602, 245, 60
'----- Open main window open "Rafter Master" for window_nf as #main print #main, "font ms_sans_serif 10" print #main.calc0, "!font ms_sans_serif 20 bold" print #main, "trapclose [quit.main]"
call instruct
'----- Wait for "instant" input or calculate button to be clicked '----- The intent is to fall into this branch label so I can return here from [GetInfo] which has been cut out for this demo [main.inputLoop] if BadInfo = 1 then x = 0 y = 0 end if wait
[GetInfo] wait
'----- End the program [quit.main] close #main end
sub instruct '----- Pre-window set up nomainwin WindowWidth = 550 WindowHeight = 445 UpperLeftX = int((MWW - WindowWidth) / 2) UpperLeftY = int((MWH - WindowHeight) / 2)
'----- Information to be displayed button #Instruct.button1,"GOT IT ", quit.dialog, UL, 455, 380, 70, 25 statictext #Instruct.statictext1, "ALL ROOF PITCHES MUST MATCH! ALL WALL HEIGHTS MUST MATCH!", 5, 5, 525, 20 statictext #Instruct.statictext2, "If there is enough interest, these features may be added at a later time", 5, 35, 450, 20 statictext #Instruct.statictext3, "This program will calculate rafter, ridge, hip and valley lengths.", 5, 75, 490, 20 statictext #Instruct.statictext4, "It will also calculate the following jack rafter lengths:", 5, 105, 325, 20 statictext #Instruct.statictext5, "Ridge to Valley, Hip to Wall, Hip to Valley and Ridge to Ridge.", 5, 135, 400, 20
'----- Open "about" window open "About Rafter Master" for dialog_modal as #Instruct print #Instruct, "font times_new_roman 12" print #Instruct, "trapclose quit.dialog"
end sub
'----- Explain measurement entry formatting sub numFormat '-----Pre-window set up nomainwin WindowWidth = 675 WindowHeight = 420 UpperLeftX = int((MWW - WindowWidth) / 2) UpperLeftY = int((MWH - WindowHeight) / 2)
'----- Information to display button #Format.button1,"GOT IT ", quit.dialog, UL, 565, 340, 90, 35
statictext #Format.statictext6, "When inputting measurements, the following conventions must be followed:", 5, 5, 600, 30 statictext #Format.statictext7, "Feet and inches must be separated with a dash, (e.g. 19-6).", 5, 55, 670, 30 statictext #Format.statictext8, "Foot, ('), and inch, (" + chr$(34) + "), marks are allowed, (e.g. 19'-6" + chr$(34) + "), but are not required.", 5, 105, 600, 30 statictext #Format.statictext9, "Use of the foot mark, (') does not require use of the inch mark, (e.g. 19'-6).", 5, 155, 620, 20 statictext #Format.statictext10, "Fractional inches must be separated from whole inches with a space, (e.g. 19-6 3/8).", 5, 205, 630, 20 statictext #Format.statictext11, "Decimal inches require a decimal point, (e.g. 19-6.375).", 5, 255, 550, 20 statictext #Format.statictext12, "Ridge Width must be expressed as inches only, (e.g. 1 1/2 or 1.5).", 5, 305, 550, 20 statictext #Format.statictext13, "Roof pitch must be expressed as a fraction, Rise / Run, (e.g. 6/12).", 5, 355, 550, 20
'----- Open format window open "Rafter Master Format Assistant" for dialog_modal as #Format print #Format, "font times_new_roman 14" 'print #Format.button1, "!font times_new_roman 12" print #Format, "trapclose quit.dialog"
end sub
'sub quit.instruct handle$ 'instructFlag = 0 'close #Instruct 'end sub
'sub quit.format handle$ 'close #Format 'end sub
sub quit.dialog handle$ handle$ = upto$(handle$, ".") close #handle$ if handle$ = "#Instruct" then call numFormat end sub
{:0)
Brandon Parker
|
|
|
Post by Rod on Jan 16, 2022 5:21:25 GMT -5
Here is my attempt. Not sure what #main is meant to be doing but the two modal windows should be managed like this. EVERYTHING is a Sub and has to be. Why? well because the program is sitting at the wait statement outside of every block of code, so everything is out of scope except Subs. This will help you frame your next question :)
'----- Pre-window set up nomainwin WindowWidth = 1400 WindowHeight = 722 UpperLeftX = int((DisplayWidth-WindowWidth)/2) UpperLeftY = int((DisplayHeight-WindowHeight)/2)
MWW = 1400 MWH = 722
BackgroundColor$ = "lightgray" ForegroundColor$ = "black" TextboxColor$ = "white"
global BadInfo global MWW global MWH dim BldgInfo(4, 10) dim RftrInfo(4, 1000) dim group(4)
button #main.calc0, "Calculate", getInfo, UL, 1120, 602, 245, 60 open "Rafter Master" for window_nf as #main print #main, "font ms_sans_serif 10" print #main.calc0, "!font ms_sans_serif 20 bold" print #main, "trapclose quit"
call instruct wait
sub instruct WindowWidth = 550 WindowHeight = 445 UpperLeftX = int((MWW - WindowWidth) / 2) UpperLeftY = int((MWH - WindowHeight) / 2) statictext #Instruct.statictext1, "ALL ROOF PITCHES MUST MATCH! ALL WALL HEIGHTS MUST MATCH!", 5, 5, 525, 20 statictext #Instruct.statictext2, "If there is enough interest, these features may be added at a later time", 5, 35, 450, 20 statictext #Instruct.statictext3, "This program will calculate rafter, ridge, hip and valley lengths.", 5, 75, 490, 20 statictext #Instruct.statictext4, "It will also calculate the following jack rafter lengths:", 5, 105, 325, 20 statictext #Instruct.statictext5, "Ridge to Valley, Hip to Wall, Hip to Valley and Ridge to Ridge.", 5, 135, 400, 20 open "About Rafter Master" for dialog_modal as #Instruct print #Instruct, "font times_new_roman 12" print #Instruct, "trapclose closeInstruct" end sub
sub closeInstruct h$ close #Instruct call numFormat end sub
sub numFormat WindowWidth = 675 WindowHeight = 420 UpperLeftX = int((MWW - WindowWidth) / 2) UpperLeftY = int((MWH - WindowHeight) / 2) statictext #Format.statictext6, "When inputting measurements, the following conventions must be followed:", 5, 5, 600, 30 statictext #Format.statictext7, "Feet and inches must be separated with a dash, (e.g. 19-6).", 5, 55, 670, 30 statictext #Format.statictext8, "Foot, ('), and inch, (" + chr$(34) + "), marks are allowed, (e.g. 19'-6" + chr$(34) + "), but are not required.", 5, 105, 600, 30 statictext #Format.statictext9, "Use of the foot mark, (') does not require use of the inch mark, (e.g. 19'-6).", 5, 155, 620, 20 statictext #Format.statictext10, "Fractional inches must be separated from whole inches with a space, (e.g. 19-6 3/8).", 5, 205, 630, 20 statictext #Format.statictext11, "Decimal inches require a decimal point, (e.g. 19-6.375).", 5, 255, 550, 20 statictext #Format.statictext12, "Ridge Width must be expressed as inches only, (e.g. 1 1/2 or 1.5).", 5, 305, 550, 20 statictext #Format.statictext13, "Roof pitch must be expressed as a fraction, Rise / Run, (e.g. 6/12).", 5, 355, 550, 20 open "Rafter Master Format Assistant" for dialog_modal as #Format print #Format, "font times_new_roman 14" print #Format, "trapclose closenumFormat" end sub
sub closenumFormat h$ close #Format call Calculate end sub
sub Calculate end sub
sub quit handle$ close #main end sub
|
|
|
Post by klewlis on Jan 16, 2022 9:34:35 GMT -5
Thank you both, the thought of opening the second dialog from the sub to close the first dialog hadn't occurred to me. Once I have the entire program near completion, I will try to post the code. Currently I have a branch label [GetInfo] to gather the information from the textboxes when the "calculate" button is pressed. With the way the wait statement can be used, I believe I can move that to a sub. If I move that to a sub, I can remove the [main.inputLoop]. I have written a short program that proves locally scoped variables do not retain a value when you return to a sub. This will eliminate the need to set x and y to zero in my input loop. Resetting these variables was the main reason for the input loop.
Are there any known problems with using "exit sub" within a for/next loop? If not, I may be able to eliminate the use of "Global BadInfo" variable. On second thought, I should probably "exit for" and then "exit sub" after the "next" statement.
|
|
|
Post by klewlis on Jan 16, 2022 11:01:42 GMT -5
Not sure what #main is meant to be doing #main is a rather large window that is filled with static text, textboxes and radiobuttons. It is used to gather information from the user. radiobuttons and the calculate button move the program to different event handlers. I am currently revising one of the textboxes to a combobox, I want to resize the window to hide the controls that will not be needed based on the combobox selection. I am looking for a way to center, (left to right) the information in the combox and drop down list. Stylebit _ES_CENTER does not seem to work for a combobox. This may be because the combobox is not technically considered and edit control, even tho you can type into it.
|
|