Classic Computer Magazine Archive A.N.A.L.O.G. ISSUE 78 / NOVEMBER 1989 / PAGE 114



    You've all seen dialog boxes in programs; they are GEM'S "window on the world." The purpose of dialog boxes is to obtain information from the user. The file-selector box is one example. There are, of course, other ways to do this, but none so elegant as using a dialog box. They can contain buttons, text, editable fields, pictures, sliders and other elements to provide both information and ornamentation.
    Unfortunately, it has been difficult for the average programmer to include dialog boxes in his or her program. It's not because dialog boxes are hard to build. There are a number of easy-to-use RCSs (Resource Construction Sets) that make building dialog boxes a matter of point-and-click. It's also not because it's hard to actually put the dialog box up on the screen. Just a few simple commands will load and draw the box. No, the problem has not been in getting a dialog box on the screen, but in getting the user-entered information back once he exits the box. How does the program get at that information?
    The release of GFA BASIC 3.0 has considerably simplified the task of working with dialog boxes by providing a variety of commands that make it easier to retrieve the information. It's still not a trivial matter, but it's now much more straightforward. The purpose of this article (and the one to follow next issue) is to teach you what you need to know to build a dialog box and retrieve the information the user provides. When we get done, you should be able to build and use your own dialog boxes, making your GFA BASIC programs look more professional.

    The first thing to understand is that there are many types of objects that can be used in dialog boxes. This should come as no surprise if you've seen some of the complex boxes that accompany commercial programs. The main types of objects that can be used in a dialog box are:
    1. G_BOX: This is a rectangular box with adjustable parameters. Among these are its size, color, border thickness and fill pattern.
    2. G_IBOX: This is a rectangular box identical to G_BOX, except that it can't have a fill pattern. The inside of the box is "Invisible.
    3. G_BOXCHAR: This rectangular box is identical to G_BOX except that it can contain a single character. The character can have its color and size adjusted.
    4. G_BUTTON: This is a box containing text that is always centered. The size of the box is adjustable.
    5. G_STRING: A character string.
    6. G_TEXT: Graphic text. The font size and text color can be varied, as can the writing mode (replace, transparent, etc.).
    7. G_BOXTEXT: This is graphic text with a box around the text. In addition to the G_TEXT variations, you can set the border width and color, fill pattern and color and the alignment of the text in the box.
    8. G_FTEXT: This is the type of field used for editable text. It has three components. The first is the template field. Anything you enter here will be duplicated in the dialog box. For example, you could enter "Name: " in this field, and it will appear at the left side of this field in the dialog box. You could also enter something like "Date:__/__/__." When the user actually goes to enter the date using the dialog box, the slashes would be automatically skipped as he or she types in the numbers.
    The RCS that comes with GFA BASIC 3.0 seems to need placeholders to reserve the number of spaces you want to use for data entry. The symbol for the placeholder is the tilde (~). Everywhere you enter this symbol, an underline (_) will appear in the dialog box. Thus, the date example would actually have to be entered as "Date:~/~ /~."
    The next field is the validation field. Here you specify what characters are acceptable. You must enter one character for each placeholder. The validation characters are:
    9 - accept only numeric characters 0-9.
    A - accept only uppercase alphabetical characters.
    a - accept only upper or lowercase alphabetical characters.
    N - accept uppercase alphabetical characters or numbers.
    n - accept upper/lowercase alphabetical characters or numbers.
    F - accept any character that can be part of a valid GEMDOS filename.
    P - accept any character that can be part of a valid GEMDOS pathname.
    p - same as P, except that wildcard characters (*,?) will not be accepted.
    X - accept any character.
    The last of the three components is the initial text field. Here you enter any string you want (usually a default) in the text field when it appears on the screen. You may enter blanks if you like, but you must enter as many characters as there are placeholders in the Template string. The color, size and writing mode of the text can be set.
    9. G_FBOXTEXT: This is identical to G_FTEXT, except it has a border around it. The thickness and color of the border can be set. A fill pattern can be selected as well (along with its color), but the fill pattern will be visible only in the portion of the box not fillable by text. That is, if the border of the box is sized to fit exactly around the maximum-size string it can contain, then the fill pattern will never be visible.
    10. G_ICON: This is a graphic. A variety of icon editors is available for designing your own icons. If you make the icon selectable (see States) and you want it to change color when you do select it with your mouse, you must design a mask when using the icon editor. Icons can be selectable, just like buttons, and thus can serve as fancy graphic buttons.

    One of the things that makes working with dialog boxes easier is the addition of new commands to Version 3 of GFA BASIC. Previously, when you wanted to use the AES commands that accessed dialog box fields, you needed to construct a code that POKEd in values, make a call to AES, and then jump through a series of memory addresses to get to where the data was actually stored. Commands to modify the dialog box were nearly as complicated.
    With GFA BASIC 3.0, however, these complex lines of code have, in large part, been replaced with a single command. While it is outside the scope of this article to detail each command and its parameters (that's what you have the manual for, though heaven knows its the very worst manual I've ever seen ... ), a brief summary of the more useful commands is in order so that you can follow along more easily:
    1. RSRC_LOAD(filename) attempts to load your resource file (given by filename) from disk. The resource file can contain many types of resources, such as menus, alert boxes and dialog boxes. In this article, however, we are going to concentrate on dialog boxes. If the resource load is successful, this function returns a nonzero value. If it fails for any reason (i.e. the resource file is not available), it returns a zero.
    2. ~RSRC_ GADDR(0,treenumber,adr%) returns the address of a tree in memory. All resource structures, such as our dialog box, are identified by their tree. The address of the tree is important, as this number will be used in almost every call to a dialog-box function. The address is stored in the third parameter, adr%. The second parameter determines which tree to return the address of. If you have only one tree, treenumber would be zero. The first parameter can have other values besides zero, but again, explaining all the parameters is beyond the scope of this article.
    3. ~FORM_ CENTER(adr%,,x%,y%,w%, h %) calculates the x, y, width and height coordinates of the dialog box with address adr% when it is located in the center of the screen, and places these values in the other parameters. While you don't have to put your dialog box in the center of the screen, that is where you most often want it located.
    4. ~FORM_DIAL (flag, minx, miny,minw, minh,maxx,maxy,maxw,maxh) has a variety of functions, depending on the value of the parameter flag. However, the two most common are to create an expanding rectangle (used before drawing the dialog box, flag = 1) or a shrinking rectangle (used after you are through working with the dialog box and are ready to remove it from the screen, flag = 2). While these two effects are strictly cosmetic, they do give that "professional" look. Parameters 2-5 specify the minimum x, y, width and height of the expanding or shrinking rectangle, while the rest of the parameters specify the maximum values. Typically, the minimum value is zero, while the maximum values would correspond to the values returned by FORM_CENTER.
    5. ~OBJC_DRAW(adr%,start,end,x % , y%,w%,h%) actually draws the dialog box given by adr% on the screen. Start specifies the starting level at which to begin drawing (0 if you are drawing the whole dialog box), while end specifies how many levels should be drawn (do not specify more than seven). The concept of levels is not hard to understand graphically. The dialog box itself is at level 0. Any object contained in the dialog box is at level 1. Any object contained by a level-1 object is a level-2 object, and so on. It is important to note that this command does not activate the box for user input. This command can also be used to redraw only parts of the dialog box.
    6. ~FORM_DO(adr%,fieldnumber) turns control of the dialog box specified by adr% over to GEM so the user may interact with it: click on buttons, type in text, etc. This function returns the value of the object the user clicked on to exit the dialog box. GEM relinquishes control of the dialog box when you click on an "exit" button (see the next section). An example of an exit button is the button labeled "OK" in the file-selector box. It's important to note that, although GEM releases control of the dialog box, it does not erase it from the screen. It is up to the programmer to restore whatever was behind the dialog box. The parameter fieldnumber specifies which field the cursor should start in and is usually set to zero.
    7. ~OBJC_ CHANGE(adr%,objnum,0, x%,y%,w%,h%,state,flag) changes the state of the object given by objnum in the dialog box specified by adr%, usually an exit button. We'll talk more about "states" in the next section; however, an example of this would be when you click on the OK button, and it turns dark just prior to the dialog box disappearing from the screen. When the OK button turns dark, it is in its "selected" state. If you didn't use the OBJC_CHANGE command to return it to its "unselected" state, the OK button would still be dark the next time you activated the dialog box.
    The parameter state gives the state that the object is to be changed to, and flag determines whether the object should be redrawn right away (1) or not (0). If the dialog box has been removed from the screen, there is no need to immediately redraw the object, because it will be redrawn the next time the dialog box is drawn on the screen with ~OBJC_DRAW. However, if you are immediately reentering FORM_DO to reuse the dialog box without using *OBJC_DRAW, then you should specify flag to be 1 to redraw the changed object.
    8. OB_ STATE(adr%, obj) returns the state of the object given by obj. States are described in the next section.
    9. OB_SPEC(adr %,obj) returns the address of information about the object specified by obj. This is primarily of interest with buttons, text and editable fields, where this function is used to get the address of the stored text.
    10. OB_X(adr%,obj) sets or returns the x position of the object specified by obj relative to its parent object. The concept of parent and child needs some explaining. Let's say you create an object that is completely contained within another object. A good example is a large box with several buttons within it. The large box is the "parent," while the buttons are the "children." Thus, this function would tell you the x coordinate of the specified button relative to the outer box.
    To get the x coordinate: X&=OB_X (adr%,object&) where the adr% is the address of the dialog box (returned by *RSRC_GADDR), and object& is the number of the object you want to know the x coordinate of (this number is set by the Resource Construction Set when you build the dialog box). To set the x coordinate: OB_X (adr %,object&) =x&.
    11. OB_Y(adr%,obj) sets or returns the y position of the object specified by obj relative to its parent object.
    12. OB_W(adr%,obj) returns the width of the object in pixels.
    13. OB_H(adr%,obj) returns the height of the object in pixels.
    14. CHAR{address} returns or sets the null-terminated string at the address specified. This function is extremely useful in finding out what text is in buttons, text fields and editable text fields, since these types of objects store their text as null-terminated strings. If we wanted to find out what text was in a G_String- or G_Button-type object, we would use the following: X$=CHAR{OB_SPEC(adr%,object&) } because OB_SPEC returns the address of the text in a G_String- or G_Button-type object. To set the text in a G_String- or G _Button-type object, we would use CHAR {OB_ SPEC(adr%,object&)}=X$. Note that the length of X$ must not be longer than the field length set when designing the dialog box, or you may crash your machine.
    Finding out what text is in text-type objects (G_TEXT or G_BOXTEXT) or formatted (editable) text-type objects (G_FTEXT or G_FBOXTEXT) is a little more complicated: X$=CHAR{{OB_SPEC(adr%,object&)} } . Note the extra set of curly braces. O_BSPEC returns an address that points to another address, which in turn contains the address of the string. In GFA BASIC, the curly braces are placed around any term that will be handled as an address. Thus, this statement takes the address returned by OB_ SPEC, retrieves the address contained there (inner set of curly braces) and then reads the string contained at that address (CHAR{}).
    Finally, to set the text in a G_TEXT-, G _BOXTEXT-, G _FTEXT- or G_FBOXTEXT-type object, use CHAR{ {OB_ SPEC(adr %,object&) } } = X$. The same caveat about string length applies here as well.

    The "state" of an object refers to a graphic condition of that object. Each of the following conditions corresponds to one bit in the variable that sets the state of the object:
    1. SELECTED (Bit 0, 00 0001): This state indicates that the object was selected and is thus shown in inverse text. Typically, this state occurs for the exit button of a dialog box after the user clicks on it with the mouse. As noted above, you should use OBJC_CHANGE to set the object back to a state of NONE (0), otherwise the exit button will still be selected the next time the dialog box is drawn on the screen.
    2. CROSSED (Bit 1, 00 0010): This state places a cross inside the object. It is only meaningful with box-type objects.
    3. CHECKED (Bit 2, 00 0100): A check mark is drawn in the upper-left corner of the object.
    4. DISABLED (Bit 3, 00 1000): The object is grayed out and cannot be selected. This is helpful in preventing the user from making selections in the dialog box that don't make sense at the current time (for example, a NEXT button when there is no next piece of data to look at).
    5. OUTLINED (Bit 4, 01 0000): The object is drawn with a border. If it already had a border (a box-type object), then a second one is added.
    6. SHADOWED (Bit 5, 10 0000): The object is supplied with a drop shadow.

    The attributes of the elements in a dialog box are set by their "flags." As with the state of an object, each flag detailed below corresponds to a bit set in the variable, which sets the object's attributes. There is even a command (OB__FLAGS) that returns the status of the flags for an object, but it is rarely used because the programmer already knows the attributes of each object; he or she designed the object with the Resource Construction Set, where these flags are set automatically. The common flags that can be set for an object are:
    l. SELECTABLE (Bit 0, 0 0000 0001): This object may be selected by the user. Most button objects must be selectable.
    2. DEFAULT (Bit 1, 0 0000 0010): Setting this flag causes two things to happen. The first is that pressing the return key selects this object automatically. Second, the object is drawn with a bold border to inform the user which object is the default. A dialog box should have only a single DEFAULT object.
    3. EXIT (Bit 2, 0 0000 0100): Selecting this object ends the FORM_DO command, returning control to the program. To select an object with an EXIT flag, the user must position the mouse pointer over the object, then press and release the left button (See TOUCHEXIT).
    4. EDITABLE (Bit 3, 0 0000 1000): This object can be edited. It only makes sense for text fields to be EDITABLE.
    5. RBUTTON (Bit 4, 0 0001 0000): This object is a radio button. It belongs to a group of radio buttons that are contained within a parent object. Radio buttons are special because only one of the group can be selected at any time. If you select one radio button of a group, the inside is darkened to show that it is selected. If you then select a different button, the new radio button is shown as selected, and the previously selected one is set back to the non-selected condition.
    6. TOUCHEXIT (Bit 6, 0 0100 0000): Selecting this object ends the FORM_DO command and returns command to the program. However, unlike the EXIT flag, to select a TOUCHEXIT object the user needs merely to place the mouse pointer inside the object and press the left button; it is not necessary to release it. This object is handy with certain types of buttons, as we shall soon see.

    This is all the room we have this issue. Next time, we'll pick up our discussion where we left off, as well as take a look at the source code for a dialog box written in GFA BASIC 3.0. See you then.

    David Plotkin has been pounding the keys on Atari computers for almost ten years now. In that time he has written many memorable programs and articles, which have been published in a variety of magazines. He holds an M.S. in chemical engineering and is a data analyst for Chevron Corporation.