Programming Using NSBasicCE
ARTICLE 5--MSGBOXes, SUB and FUNCTION
All content (c)1999, 2002 Serg Koren.
All rights reserved.
Welcome to the fifth installment of NSBasicCE.
This time we go over the another very common user-interface object you will use: MSGBOX.
Leftovers from Last Time
Last time we talked about CommandButtons and I asked you to write a program:
The program should have:
- Four command buttons.
- Each button should have a different label: Bold, Italic, Underline, and Normal
The program should:
- Start with all captions in the default style (not Bold, Underlined, or Italic)
- When you hit the button that says "Bold" the label style should go bold (stand out)
- When you hit the button that says "Italic" the label style should switch to italics
- When you hit the button that says "Underline" the label style should underline
- When you hit the button that says "Normal" all label styles should go normal (the default) and undo everything else.
- No button should affect any other button except for the "Normal" button which affects all the others.
- Use factoring.
If you're just starting out programming you may be overwhelmed by the amount of stuff you have to worry about all at once...don't worry! You don't have to worry about it all at once. Take one item and get is working. Then take another. And so on. This is the principle of divide-and-conquer. For instance, get just the Bold button working properly. Then copy the code from the Bold button and just change the lines you have to to get the Italic button working. And so on. This is mental factoring (as opposed to code factoring which we discussed earlier.) Never get overwhelmed by programming. It always just comes down to solving a tiny little problem and then adding on to it once its solved.
The hardest part of this assignment is the Normal button. The other three buttons just send a message to themselves; the Normal button sends a message to each of the other three buttons.
Here's my version of the program. First you'll notice that it doesn't look anything like yours. This doesn't mean mine is right and yours is wrong. If your program does what the assignment states, then you did it correctly. The most notable difference is probably the coordinates and size you used for the buttons (the last 4 parameters to the ADDOBJECT command). The other differences are due to something known as coding (programming) style. Religious wars have been fought over this and much blood has been shed. Coding style refers to how your code looks on the page. How pleasing to the eye is it. It also refers to how easy your code is to read and understand. Style amounts to how you space your lines, are your keywords (commands) in uppercase, lowercase, mixed case, do you have comments and how are they aligned, etc.
Of course, my coding style is the correct one.
'---start code here---
'
' A program that demonstrates the Font style capabilities of the CommandButton Object
'
' -- Subroutines to create our buttons ---
' A subroutine to create the Bold button
SUB MakeBoldButton
ADDOBJECT "CommandButton","MyBoldButton",10,10,70,30
MyBoldButton.Caption = "Bold" ' set the caption on the button to read "Bold"
END SUB
' A subroutine to create an Italic button
SUB MakeItalicButton
ADDOBJECT "CommandButton","MyItalicButton",10,50,70,30
MyItalicButton.Caption = "Italic" ' set the caption on the button to read "Italic"
END SUB
' A subroutine to create an Underline button
SUB MakeUnderlineButton
ADDOBJECT "CommandButton","MyUnderlineButton",10,90,70,30
MyUnderlineButton.Caption = "Underline" ' set the caption on the button to read "Underline"
END SUB
' A subroutine to create a Normal button
SUB MakeNormalButton
ADDOBJECT "CommandButton","MyNormalButton",10,130,100,30
MyNormalButton.Caption = "Norlaml" ' set the caption on the button to read "Normal"
END SUB
' --- The Click event handler subroutines for our buttons ---
' The Bold Click Event handler
SUB MyBoldButton_Click
MyBoldButton.FontBold = True ' make the caption bold
END SUB
' The Italic Click Event handler
SUB MyItalicButton_Click
MyItalicButton.FontItalic = True ' make the caption italic
END SUB
' The Underline Click Event handler
SUB MyUnderlineButton_Click
MyUnderlineButton.FontUnderline = True ' underline the caption
END SUB
' The Normal Click Event handler sends a message to the other 3 buttons
SUB MyNormalButton_Click
MyBoldButton.FontBold = False ' turn bold style off
MyItalicButton.FontItalic = False ' turn italics off
MyUnderlineButton.FontUnderline = False ' turn underline style off
END SUB
' --- The UI setup SUBroutine ---
SUB SetupUI
MakeBoldButton
MakeItalicButton
MakeUnderlineButton
MakeNormalButton
END SUB
' --- Our main subroutine ---
SUB Main
SetupUI
END SUB Main ' Our one and only IMMEDIATE command
'---end code here---
Not too bad! Ok, now you have a feel for how to use CommandButtons in your program. Remember, Objects can send messages to themselves, or to other Objects (like other CommandButtons). Now before we delve into our main topic, namely MSGBOXes, I want to talk a bit about something we've used but never really described. SUBroutines and FUNCTIONs.
SUB and FUNCTION
As we've mentioned SUBroutines and FUNCTIONs are ways of breaking up big hunks of code into reusable, easily managed, and understood pieces. We've seen and used SUBs before. They always consist of a matching pair of:
SUB
...hunk of code here...
END SUB
where <name> is a name that you provide, that identifies this "hunk" of code. Whenever you want the subroutine to execute (run), you merely use its name. For instance in the CommandButton assignment we had a subroutine called SetupUI that created all our buttons. We got it to run in the Main subroutine by just using the name SetupUI. Very straightforward. And as the last line in the program shows we can call any subroutine from IMMEDIATE mode. Then why don't we call more from IMMEDIATE mode? It gets confusing and it's difficult to debug a program with lots of subroutine and function calls from IMMEDIATE mode, because you can't tell who calls what when easily.
Subroutines are easy. Functions are a little bit more complex, but they have more flexibility. Whereas subroutines just execute code, FUNCTIONs, not only execute a hunk of code, but they get an answer back to you. Huh? Think of it this way. Say you have a complex calculation to do:
5 x 5 x pi
(the area of a circle having radius 5).
And because you use it over and over and over in your main program, you decide to factor it out into its own subroutine:
SUB Area5
Area = 5 * 5 * 3.14
END SUB
This would work fine, but what if you don't want to save it in the "Area" variable each time? Maybe someplace in your program you want to save it to a variable called "MyPoolSize" instead. You could have two separate subroutines. One called Area5 and one called AreaOfMyPool and store the first result in Area and the second in "MyPoolSize". But this gets cumbersome fast. That's where FUNCTIONs do wonders. FUNCTIONs return the value of a calculation (FUNCTIONs always return a value, SUBs never return a value) in the name of the function itself. For example:
FUNCTION AreaOfACircle
AreaOfACircle = 5 * 5 * 3.14
END FUNCTION
First of all, a FUNCTION is like a SUB. It has a matching END FUNCTION statement. Also, you have to have a line (the very last one in the function usually) that uses the name of the function and assigns a value to it. You can have other code as well, but at least one line has to use the name of the function. (Don't worry NSBasic is smart enough to know that if it sees a value assigned to a name not to call the function again. So how does this help our pool problem? Well remember that a FUNCTON returns a value, and you have to put the value somewhere. So in our program we would have to assign the value (store the number) somewhere (a variable). So to call a FUNCTION you always have to assign its name to a variable like this:
AreaOfMyPool = AreaOfACircle
Of course you can do things like multiply the value by a number, add to it, etc.
AreaOfMyPool = AreaOfACircle * 2
But what happens if your pool doesn't happen to have a radius of 5 feet? That's where Parameters come in. Unless you've dealt with them the terminology can be confusing. Parameters are numbers you can pass into a SUB or FUNCTION that let you alter how the SUB or FUNCTION works. The confusing part is that there are two types of parameters (and I won't bore you with the jargon). The first is the type used as a placeholder in the SUB or FUNCTION itself. Using our circle again, we could define the function as:
FUNCTION AreaOfACircle(Radius)
AreaOfACircle = Radius * Radius * 3.14
END FUNCTION
Radius here is the placeholder parameter. The value we give Radius is passed into the function and replaces every occurrence of the word "Radius". That's the simplest way of thinking about it. So if Radius = 10 we would essentially execute:
10 * 10 * 3.14
So how do we pass a value to Radius? We use an actual parameter in the call to the function like so:
AreaOfMyPool = AreaOfACircle(10)
The number 10 in this statement is the actual parameter that is used for the value of the variable Radius in our Function call. We could get fancy (and often will with parameters) and pass in a variable like this:
RadiusOfMyPool = 10
AreaOfMyPool = AreaOfACircle(RadiusOfMyPool)
This is considered better coding style, since you know what the 10 really stands for--the radius of my pool.
Of course, you can have more than one parameter. Say you have a rectangular pool:
FUNCTION AreaOfARectangle(Height,Width)
AreaOfARectangle = Height * Width
END FUNCTION
HeightOfMyPool = 100
WidthOfMyPool = 10
AreaOfMyPool = AreaOfARectangle(HeightOfMyPool,WidthOfMyPool)
When using more than one parameter, the FUNCTION call itself has to have a place holder for each parameter, and the call to the function has to have a value for each parameter. Just separate them with a comma.
Ok, how would you use parameters with a SUB? The same way, but remember a subroutine doesn't return a value, so whatever you do gets done in the subroutine:
SUB FigureOutTheAreaOfMyPool(Width,Height)
AreaOfMyPool = AreaOfARectangle(Width,Height)
END SUB
Width = 10
Height = 10
FigureOutTheAreaOfMyPool Width,Height
A couple of things to note here. First, parameters themselves can be parameters (Width, Height in the definition of FigureOutTheAreaOfMyPool). Also, the call to the SUB with parameters doesn't use the parentheses around the parameters:
CallASub param1, param2
CallAFunction(param1,param2)
So, what is our ADDOBJECT,"CommandButton",<name>,....? It's a subroutine, and not a function. One that's been written for you and you don't have to worry about what's inside, but still a puny little sub like ours.
There are other types of parameters that a SUB or FUNCTION can use, but we'll discuss those in the future. Now we'll talk about another FUNCTION (built-into NSBasic), namely the MSGBOX.
MSGBOX
The MSGBOX manual page is misleading. It's called a FUNCTION (you can tell by the parameters in parentheses). However it's also a SUB. MSGBOX displays a dialog box with some buttons and lets the user make a decision or just displays a message to the user. It's very flexible and has lots of options (that you set with parameters). We've used a simple one before:
MSGBOX "Hello there!"
You can change the look of the MSGBOX by adding buttons. A list of buttons is shown in the manual. You would use the value for the buttons parameter after the string (called the prompt in the manual):
MSGBOX "Hello there!",5
or
MSGBOX "Hello there!",vbRetryCancel
You can use either the Constant or the Value, it doesn't matter. But using the Constant name reminds you of the buttons. vbRetryCancel is more informative than 5. It's a matter of style.
The final parameter, "title" puts a title, where else but, in the title bar of the dialog:
MSGBOX "Hello there!",vbRetryCancel,"A Silly MSGBOX"
The above are all used as if MSGBOX is a subroutine...no parentheses, and we don't get a value. You can test to see what button the user tapped:
ButtonTapped = MSGBOX("Hello there!",vbRetryCancel,"A Silly MSGBOX")
Note the parens, and we're assigning the value of MSGBOX back to ButtonTapped. It's a function here. MSGBOX is weird because its one of the few (if not only) things in NSBasic that acts like both a function and a subroutine. Try:
MSGBOX("Hello there",vbOkOnly)
and see what error you get. This tells you that you're trying to use MSGBOX like a subroutine (you're not assuaging it to a variable), but you're still using parentheses. So NSBasic says its really a SUB and you can't have the parentheses. Ack! This is one of the most confusing error messages in NSBasic; just remove the parentheses, or assign it to a variable like we did before to get rid of the error.
Ok, now if you followed that we'll try something tricky. This is called a nested call. A nested call is one call right inside another (like a bird's nest). Easy homework for next time!
Explain what the following does:
MSGBOX MSGBOX("My homework!",vbYesNoCancel,"Homework "),vbOKOnly,"My MSGBOX homework"
a) How many functions are there?
b) How many subroutines are there?
c) What gets called/executed first, the subroutine, or the function?
d) When you run this line, what is that number that pops up? Run it again and try something else.
e) How many parameters does this line have?
Next time we'll talk more about variables (and really explain them instead of just talking about them) and go over another Object, the CheckBox! Stay tuned!
If you get stuck or have a question about anything we've gone over, feel free to e-mail me at Serg@VisualNewt.com
Cheers!

