Point and click in Microsoft Basic; a Macintosh tutorial. John J. Anderson.
Ever since you took your Macintosh out of the box, you've loved those pull-down menus, windows, and push-button operations. They make using a computer about as easy and enjoyable as it is likely to become in the foreseeable future. But even as you have grown accustomed to the point-and-click way of life, one peevish disappointment may have nagged at you. Sure, all that magic is addictive. But how to get those wonderful things working in your own programs?
After the initial issue of a rather disappointing Macintosh version of Basic over a year ago, Microsoft Corporation truly has made amends with Mac Microsoft Basic 2.0. This version of the language is at long last deserving of its target machine and is nearly bug-free. It is totally structure, and though line numbers remain an option, there is no need for them. Procedures and sub-procedures can be nested to your heart's desire. And, because this version of Basic offers countless hooks to the Mac Toolbox, pull-down menus, custom windows, dialog boxes, and point-and-click operations can make your Basic programs indistinguishable from professional software products in terms of the user interface.
In this tutorial we'll take a look at how you can harness these features, albeit in a very simple manner. Once you understand the basics unveiled here, you can incorporate these powerful capabilities to make your programs look and act the way they should on a machine of the caliber of the Apple Mac-intosh: namely, polished.
I should also mention at the outset that for those of you not inclined to type in listings, all the programs that follow are available for download in the Apple Cart section of Creative Computing Online (Compuserve PCS-22).
One more thing before we get to the meat and potatoes. Here are a few guidelines for Basic programming: always skip a line before beginning print in your listings. This will avoid scrunched lines in hard copy due to a bug in the Mac printer driver. Don't ignore the strong editing features of your Mac-intosh.
Cut and paste can save you lots of time when entering repetitive lines of code. Finally, notice that colons are optional between separate commands on a single line. I tend toward including them out of long-term habit, but you can leave them out if you so desire.
Creating a Custom Menu
As I mentioned long ago in my initial review of the Mac, point-and-click is not just a gimmick; it is a powerful approach to computer use. However, without its slick user interface, the Macintosh is just another computer. Unfortunately, some programming languages for the Mac manage to reduce it to that lackluster category, by making it quite difficult for all but the most expert programmer to get the Macintosh Toolbox working. Microsoft Basic 2.0 has changed that. Listing 1 throws a customized menu up onto the ruler in a mere 22 lines.
As you can see, the command MENU is used to get things going. The MENU argument is structured as follows: MENU <menu item id, [state, name]>...where menu id = the menu header number (range 1 -10); you cannot reassingn the desk accessor header item id = the menu item number (range 0-20); you cannot have more than 20 items on an individual header state = condition flag (range 0-2); 0 (disable); 1 (enable); 2 (enable with checkmark) name = title of the header or item At the top of Listing 1, we first shut off menu columns 1 and 2 entirely. Note that even hen there is no title, the quote marks must still appear. We then assign to menu bar slots 3,4, and 5 the names of continents and countries. Notice that the lead item for each slot is the header, which is then directly followed by its item list set. The item id progresses from 0 to 4 in each case.
From there we move to a procedure called "Idle." Certainly we could have left this bit of code unlabeled, and it would still run--but up ahead we shall see why it merits a name. Within this procedure there are some very recognizable Basic commands. We do some printing, then freeze the action by prompting for keyboard input. When the program is run, you can nose around these menus for as long as you like, until you are convinced that they have been created with lots of help from the Toolbox. Notice that each menu box is perfectly sized to conform with the header and item names. When you click off them, they flash. They await your further instructions. By gaining access to the Toolbox, you can make the 64K of ROM inside the Macintosh work for you.
When you press RETURN, the program calls back the Microsoft Basic menus with the command MENU RESET, and then STOPS. It is imperative that you avoid painting yourself into corners when redefining menus. Once you modify the menu bar, you must provide a way out. Failure to do so results in loops that can be broken only with a flip of the power switch.
Menu-Based Escape Hatch
Listing 2 makes escape from a customized menu an actual selection of tht menu. For our purposes that is appropriate, and we will carry that method through in all the programs here, so you can easily move from the actual program to a listing of that program, to see how things work (or don't work). Listing 2 also gives us a first taste of branching from a pulldown menu. The command ON MENU GOSUB launches our simple search. The command MENU ON traps for the ON MENU GOSUB command.
Think of the procedure Idle as a car sitting in neutral, idling. In this case all we want the procedure to do is keep the motor running--hence the procedure loops in an endless GOTO itself. Most programs ultimately hinge off a loop of some kind; if you call such a loop Idle in all your programs it will make them easier to understand.
To follow through with the metaphor, the "transmission" of this program is the procedure Menucheck. We define the variable Itemchoice as the value of MENU(1). Because there is only one header in this chunk of code, we need not count headers at all; we need to count only items of that single header. If MENU(1) returns a value of 1, the selection "Exit to Basic" has been chosen, so we'll GOSUB procedure Breaker. If it returns a value of 2, we'll GOSUB procedure Exitter.
The line MENU Menuchoice, 0,1 removes highlighting from the header when it is deselected. Otherwise the highlighting gets stuck in the "on" position. The variable Menuchoice can remain undefined in this listing as it will always be 0; there are no other choices to be had. Further ahead that will no longer be the case.
The procedures Breaker and Exitter are quite straight-forward. The former reverts to MS-Basic just as it did in Listing 1. The latter is included for purposes of example, to show how the command SYSTEM closes all open files and returns control to the Finder program. In functional programs, this is a more appropriate escape than that provided by a simple STOP.
Both RETURN statements in these subroutines could be deleted, as the program will never reach them. Still, it is a good idea to get in the habit of returning from all your GOSUBS--a habit that may save you debugging time when writing much more complex code.
Checking Things Out
So far we have branched from menu selections directly to unique subroutines. However, many times a menu selection serves not as a specific branch but rather to modify other menu selections, which is one thing we're out to do here. An indispensible Toolbox tool for this purpose is the check mark. Listing 3 gives us a succinct example of how to get one going.
First we get Breaker installed into menu slot 1. Then we create a menu as we did in the previous example, with one alteration: we put a check mark next to the selection "Rail." Recall that you can do this simply by giving an item a menu state with the value 2. We will default to the item "Rail," while affording the user the opportunity to move the check mark with a point-and-click. First we'll turn off all the other menus and move through Menucheck and Idle in the now-usual manner.
Note that this time around we define variable Menuchoice as well as Itemchoice. These will allow us to keep track of what items have been pulled down, even with multiple headers. Menuchoice will keep track of headers; Itemchoice will keep track of items.
Depending upon whether the user pulls down "Stop" or "Rail/road," we'll branch to Breaker or Infotype, respectively, by counting through the values of Menuchoice. If "Rail/road" is chosen, we'll branch to procedure Rail or procedure Road, depending on the count through values of Itemchoice. This approach is the foundation of menu-branching. It is quite easy, once you understand it.
Those procedures in our petrie dish example here only move the check mark back and forth. But that check mark moves firm-footedly, doesn't it? It is a simple matter of changing MENU states.
Trains of Thought
Listing 4 is the longest of the programs presented here, as it attempts to show menu control and branching in a meaningful way, along with a few new bells and whistles. Rest assured, however, that it is easy to understand after a few minutes of stud. Also, substantial chunks of it make use of modules you have already typed. Use the cut and paste function to grab the menu list from Listing 1. You can also pilfer some of Listing 3, though alterations are needed for a couple of procedures. (Downloaders need only capture the file.)
This may seem like a strange moment for me to tell you a little something about myself, but you should be forewarned: I am a devotee of railroads of the world. So it seemed natural that our example should deal with that topic. If you are into trains too, so much the better. If you are not, let me underscore that the objective here is to show you how to access the Toolbox through MS-Basic. I'm sure you can easily substitute your own interests for mine.
The top of Listing 4 should look quite familiar to you now. Nothing up the sleeves there. Your first question ought to come in at the WINDOW command. Rather than sending the output to the default window, we use the command to create our own. Format for the WINDOW command is as follows: WINDOW <window id[,[title][,[dimensions[[,tupel]]]>...where window id = identifies window (range 1 - 4); maximum of 4 windows title = an optional text string argument for use with document window dimensions = screen bounderies of created window; consists of x,y coordinates corresponding to upper left- and lower righthand corners type = Indicates type of window (range 1-4); 1 (document window); 2 (two-line frame border); 3 (simple one-line border); 4 (window with shadow)
Note that even when a title is omitted, the quote marks must be included, as is the case with MENU. Note also the format for the dimensions of the window, which utilize standard MS-Basic form (parenthesized coordinates separated by a hyphen).
When you are finished with a window, you may or may not need to close it, using a WINDOW CLOSE command. We'll learn more about this up ahead.
As for sizing windows, well, you'll probably need a few trial and error sessions before you get a feel for them. Expect to do some tailoring once you have laid one down. Always make sure any window is big enough to handle the largest of your inputs to it.
Next we encounter the command TEXTFACE. This is very simply a means of calling up character style. Format for the command is: TEXTFACE *attribue>...where attribute = 0 (plain text); 1 (bold); 2 (italic); 4 (underlined); 8 (outlined); 16 (shadow); 32 (condensed); 64 (extended)
A caveat: the documentation is wrong when it shows a format of CALL TEXTFACE <attribute>. The CALL command means something else entirely, and using it as suggested in the documentation results in a syntax error. This erratum is being redressed by Microsoft.
Anyway. We get a better look to the text in our text window by making it boldface. Then we head into our old friend ON MENU GOSUB.
The MENU method then more or less repeats itself. However, in this case there are five possible values for Menuchoice and four Itemchoice possibilities per header. Things get a little crowded, but the technique is no different from what we saw in the preceding modules.
You'll notice an extra statement in the procedures Rail-names and Trackage. Here we set up a new variable, rail, to act as a flag. In the following procedures, the value of variable rail determines which text strings are printed. Remember that these are the two menu items that share a checkmark. The user can ask for two type of information from each item on the menu. Though the approach is somewhat primitive, this is an example of how a checked menu selection can modify other selections. We could use it to control many more than two information states.
The tail end of Listing 4 consists of procedures that print out the information for each country on the menu. As stated, when rail=0, railway names are printed. When rail=1, trackage statistics are printed in the window. It's that simple.
When you run the program, notice that you can size, move, or close all the windows on the screen except for the active program window at any time during execution of the program. That's a function of the Toolbox. It is a nice idea here to close them all so that the screen is as neat as possible.
On the Button
Our final program, Listing 5, introduces a new window with pushbuttons in it to help us differentiate between East and West Germany (thught you had me on that, didn't you?). Everything prior to procedure Germany itself should now be clear to you, if you have spent a little time with the previous listings.
Within procedure Germany, we create a new text window in the same manner as before, but lower down on the screen in this case so as not to obscure the original text window. There is a way to recover obscured windows, but that is best left to a future article.
We print a message in the window, then place three buttons there, using the BUTTON command. Format for the command is as follows: BUTTON button id, state[,title, dimensions[,type]...where button id = identifies button (range 1 to memory limitations) state = 0 (button dimmed and inactive); 1 (button active, but not selected); 2 (button active and currently selected) title = text string description of button function dimensions = Screen boundaries of created window, consists of x,y coordinates corresponding to upper left- and righthand corners type = Indicates type of button (range 1-3); 1 (frame push button); 2 (check box); 3 (radio button)
Our use of the button command in Listing 5 is pretty straightforward. Once they have been established, we hold up everything but button-pressing with a WHILE ... WEND command. The facility of this statement is that it exeecutes a loop as long as a given condition is true. Here we loop until a button is pressed. When one is, we branch to the appropriate subroutine.
In this instance we must close WINDOW 2, to return to normal operation of the program. Hence the statement WINDOW CLOSE 2 appears in all three subroutines--Shut, East, and West.
To add this improvement to Listing 4, copy procedure Germany with its ancillary subroutines, Shut, East, and West, and paste it into Listing 4. Don't forget to then delete the old procedure Germany. (Again, downloaders can capture a complete version of the program from Creative Computing Online.) You will then have a functional Basic program utilizing pull-down menus, windows, and pushbuttons.
That is more than enough for this time around to get you thinking about your own pull-down applications. In a follow-up piece, we'll take a look at reading the mouse and mouse button, pulling up MacPaint files, and the creation of simple graphics and sound in MS-Basic 2.0. Until then, keep on clicking!