OML for the complete beginner, Lesson 12

Dialog Boxes

Lesson 12 is quite long in comparison to previous lessons. You may wish to try it in smaller doses.

Now that you've had the opportunity to use the InputBox command on occasion, have you ever looked at the screen display of an InputBox and wished you could change the size of the window, the location of the window, the location of the buttons inside the window, the size and number of the data entry fields, and so forth? Or just wished you could design an input window so that users could type in information and the macro could then use and play with what was typed in? There is a way to do this using dialog boxes--but be warned, the concepts are easy but the actual implementation can be extremely intimidating and aggravating.

Connexion comes with a dialog box editor, so you have the ability to create dialog boxes, add controls, and change the size and contents of a dialog box by using the mouse and menus, and the computer then takes care of figuring out the programming commands needed to achieve the look you want. You will usually find it easier to use that rather than manually create dialog boxes by hand, but you still need to know how the commands work in order to get data from the dialog box, and it can be helpful to know how to make some changes manually, so that you do not have to constantly open and close the dialog box editor. (It can be kind of like a refrigerator door in that regard.) Additionally, when you use the dialog box editor to make changes to existing dialog boxes, there may be some things it does not handle well, so it may accidentally wreck a dialog box that you've worked and worked on to get working just the way you want it to.

Here is the program code for a sample dialog box along the lines of what is used by the InputBox command. Note that this is completely non-functional as is, in order to better explain the various parts. Elements in angle brackets represent strings that can be included as a string or as plain text in quotation marks; square brackets designate optional elements.

  Begin Dialog <name1> [x, y,] dx, dy, [<caption>]
    Text x, y, dx, dy, <text>
    TextBox x, y, dx, dy, .func1
    OKButton x, y, dx, dy
    CancelButton x, y, dx, dy
  End Dialog
  Dim <name2> As <name1>
  z = Dialog(<name2>)

As you can see by comparing the first line to the second to last line, the <name> of the dialog is used later on to define the way the elements in the dialog box are referenced by the rest of the macro.

The <caption> is the title (if any) you want to appear in the blue bar at the top of the window; if this is left out, the default is "Softbridge Basic Language", as you've probably seen on message boxes.

Note that you generally must have at least one button showing on your dialog box, so that users have a way to exit from the dialog box. It does not have to be an OKButton or a CancelButton, but most dialog boxes will have one or the other or both of those two.

X = across, y = down. X = 1 is 1/4 the average width of a letter; since the font used does not have uniform-width letters, x = 2 is roughly the width of the letter "i", and x = 6 is roughly the width of the letter "m". Y = 1 is 1/8 of the height of a normal capital letter; y = 12 will give enough room to display the entirety of any capital letter or a letter with a tail. Dx and dy are the total width and height of the box/window being defined. In the Begin Dialog statement, x and y are optional; they define where on the screen to place the box. If they are left out, the default is a central location.

<Name2> is defined to be the results of dialog <name1>; because of this, <name2> is used by the rest of the macro to refer to the various elements of the dialog box rather than <name1>. That is, <name2>.<identifier> (for example, SampleDialog.MyTextBox) is a variable containing whatever was typed in the MyTextBox textbox of the SampleDialog dialog window.

The Dialog statement at the end is what actually displays the dialog box and waits for the user to do something; it closes the dialog box and the macro continues as soon as the user clicks any button. Z then reflects which button was pressed; -1 for an OKButton, 0 for a CancelButton, and 1 and higher for any user-defined buttons, in the order that the user-defined Button commands appear in the macro.


As was briefly explained above, all dialog box commands can optionally include an identifier. For illustrative purposes, I've used the form .Identifier or DialogName.Identifier in all of the following examples. However, in your own macros, you do not actually have to use the words "DialogName" or ".Identifier." "DialogName" should be whatever the name of your dialog is, as given as the first half of the relevant Dim statement following End Dialog. (Thus, Dim GetNewText As Dialog1 means you would use GetNewText instead of DialogName.) "Identifier" can be any word or combination of letters and numbers you can think of, as long as it is preceded by a period and is not the same as any other identifier in the same dialog box.

A dialog box with some plain text and an "OK" button is the equivalent of a MsgBox. A dialog box with a box for typing data, an "OK" button and a "Cancel" button is the equivalent of an InputBox. For fancier applications, there are several commands that can be included between the Begin Dialog and End Dialog statements in order to get various "controls" (like the control knobs and buttons on a radio): boxes, buttons, text, and the like.

Button x, y, dx, dy, "Text", .Identifier
PushButton x, y, dx, dy, "Text", .Identifier
Button and PushButton are synonymous. X, y are numbers that indicate coordinates relative to the dialog window (0,0 is the upper left corner of the dialog window); dx, dy are numbers that indicate the width and height of the button. Otherwise, the four sizing controls work the same as they do for the Begin Dialog statement. "Text" is the word(s) that appear on the button, and .Identifier is an optional identifier you can use later on in the macro to reference whether this button was pushed or not by using DialogName.Identifier. Clicking on a button, any button, automatically closes the dialog window and sends any results to the macro. This was stated earlier, but it bears repeating: Every dialog box must contain at least one button, be it an OKButton, a CancelButton, or a user-defined Button or PushButton; otherwise there is no way for the user to exit the dialog box and continue on to the rest of the macro!

ButtonGroup .Identifier
ButtonGroup defines a set of buttons for use by the dialog. Later on the macro, DialogName.Identifier will identify with a number which button in the group was pushed. The first button in the group is identified as "1", the second as "2", and so forth.

CancelButton x, y, dx, dy
This creates a "Cancel" button. x, y, dx, and dy work the same as for Button (and, for that matter, all commands that use such location and sizing controls inside of a Begin Dialog...End Dialog block.) As mentioned in the discussion of the Dialog statement above, clicking the Cancel button either returns a -1 or an error, depending on which format of the Dialog command is used.

Caption "text"
Caption text$
If you didn't specify one in the Begin Dialog statement, Caption allows you to set the text in the blue bar at the very top of your dialog box. As with most instances of strings in commands, you can use plain text in quotes or use a string which was given a value earlier in the macro. Thus, the two above forms of the command are equivalent.

CheckBox x, y, dx, dy, "text", .Identifier
This command creates a box which can be checked and un-checked. Unlike OptionButtons, checking one CheckBox has no effect on any other checkboxes in the dialog window. DialogName.Identifier will equal 0 if the box is unchecked and 1 if it is checked.
Apples

ComboBox x, y, dx, dy, text$, .Identifier
DropComboBox x, y, dx, dy, text$, .Identifier
These two commands are synonymous. A ComboBox combines a TextBox with a DropListBox to create a list of choices from which the user can choose or type in their own; text$ must be defined earlier in the macro, exactly the way a ListBox works. If the user clicks in the box, a cursor appears and the user can type anything, just as for a TextBox. [Note: Due to the limitations of HTML, it is not possible to type anything in the following box.]

If the user clicks the down arrow, the box drops down. Selecting an item closes the box back down to normal, with the newly selected item appearing in the box. The user may then click in the box and edit the selection as desired. After the dialog window has been closed, DialogName.Identifier will be a string containing the selection or whatever the user typed.

DropListBox x, y, dx, dy, text$, .Identifier
This is virtually identical to a normal ListBox, except that, unless the user is active in selecting something from the box, only the selected item is shown (the first item is the default selection). Note that text$ must be defined earlier, exactly as for a ListBox.

If the user clicks anywhere in the box or on the down arrow, the box drops down. Selecting a different item or clicking on the arrow box closes the box back down to normal, with whichever item was highlighted appearing in the box. Also, if the box is "active", pressing the first letter of an item brings that item directly into the box. After the dialog window has been closed, DialogName.Identifier will reflect the choice made--choosing the first returns a "0", choosing the second returns a "1", and so forth.

GroupBox x, y, dx, dy, text$
This command allows you to draw a line around a section of your dialog window. If text$ is null (""), then it is a solid line all the way around; otherwise, the contents of text$ are displayed as part of the top border of the box formed by the line.

ListBox x, y, dx, dy, text$, .Identifier
A ListBox gives the user a selection of choices, which looks something like this:

In this case, "apples", being the first item in the list, is pre-selected. If the user clicks on another selection or uses the down arrow on the keyboard to highlight a different one, then the selection box highlights the new selection. Also, if the box is "active", pressing the first letter of an item highlights that item.

The text$ element must be defined earlier in the program, and is usually made up of each element you wish to list, separated by a tab--that is, Chr(9)--or in an array explicitly made up of strings. For the above example, a line would be needed before the ListBox command along the lines of either of the following sets of statements.

  text$ = "apples" & Chr(9) & "oranges" & Chr(9) & "pears"

  text$(0) = "apples"
  text$(1) = "oranges"
  text$(2) = "pears"

After the dialog box has been closed, DialogName.Identifier will reflect the choice made--DialogName.Identifier equals 0 if the first is chosen, it equals 1 if the second is chosen, and so forth.

OKButton x, y, dx, dy
This command creates an OK Button. Otherwise, it is functionally identical to the CancelButton command, except that it does not automatically generate an error.

OptionButton x, y, dx, dy, text$, .Identifier
Both ListBoxes and OptionButtons allow users to select between a limited number of choices. Where ListBox does so via a single command, in which the selected choice is highlighted, OptionButtons are "radio" buttons, which fill in when they are selected, making all other OptionButtons blank. OptionButton can only be used after the OptionGroup command. Each choice requires its own OptionButton command, and if you are using OptionButtons, at least two must be used. If you want a user to be able to select an option by typing a letter, put an ampersand before that letter in text$. For example, this code fragment
  OptionGroup .Identifier
    OptionButton 16, 12, 46, 12, "&Grapes"
    OptionButton 16, 28, 67, 8, "Grape&fruit"

will display something roughly like this

Grapes
Grapefruit

In this case, when the macro is running, pressing "f" will change the selection to "Grapefruit". [Note: Due to the limitations of HTML, this ability is not possible on this web page.]

OptionGroup .Identifier
OptionGroup defines a group of OptionButton statements; it tells the computer which radio buttons are linked together, so that it is possible to have multiple sets of radio buttons in the same window. DialogName.Identifier will equal 0 if the selection defined by the first OptionButton statement is selected, 1 if the second is selected, and so forth.

StaticComboBox x, y, dx, dy, text$, .Identifier
This command is identical to a DropComboBox, except that the list of choices is always visible.

Text x, y, dx, dy, "text"
The indicated text is printed in the dialog box, beginning at the point indicated by x & y. Dx and dy are the width and height of the text to be inserted, and work the same as other dialog statements do.

TextBox x, y, dx, dy, .Identifier
Creates a box in which users can type in whatever they want. Later statements in the macro can reference the entered text by using DialogName.Identifier. There is no way to use the TextBox command itself to limit the number of characters typed in, or the type of letters (such as letters versus numbers), but applying Left$, Right$, and the like to the inputted text may achieve this effect. The inputted text is always a string, even if numbers are typed, so the Val command may be required to change an inputted number from a string value to a numerical value.


Since it may be easier to understand all of this by seeing these commands in their proper context, here is a macro that creates and handles a sample dialog box.

  Sub Main
  StartDialog:
    Begin Dialog GetInfo 130, 60, "Name Request"
      Text 4, 4, 84, 12, "Please enter a name:"
      TextBox 4, 20, 45, 12, .UserName
      OKButton 4, 34, 40, 20
      CancelButton 45, 34, 40, 20
      PushButton 86, 34, 40, 20, "Reset"
      OptionGroup .NameOrder
        OptionButton 86, 4, 42, 12, "First Last"
        OptionButton 86, 16, 42, 12, "Last, First"
    End Dialog
    Dim NameInfo As GetInfo
    z = Dialog(NameInfo)

    If z = -1 Then
      Goto Done
    ElseIf z = 1 Then
      Goto StartDialog
    Else
      If NameInfo.UserName = "" Then
        MsgBox "'Name' is a required field."
        Goto StartDialog
      End If
    End If

    If NameInfo.NameOrder = 0 Then
      MsgBox "The name you typed was:" & NameInfo.NameOrder
    Else
      LastName$ = Trim(GetField(a$, 1, ","))
      FirstName$ = Trim(GetField, a$, 2, ","))
      MsgBox "The name you typed was:" & FirstName$ & " " & LastName$
    End If

  Done:
  End Sub

As you can see, right away the total size of the window is established, as is the title of the window. Since there are only two numbers included, the window will be automatically centered on the screen. Then comes a Text command, which simply writes the indicated text in the window you've created (in this case, instructions for what to type in the box), and a TextBox command, in which the user can type some data. After that are three button commands: an OK button, a Cancel button, and a custom button called "Reset". The last statements before the "End Dialog" are an OptionGroup that creates two radio buttons that will dictate how the macro handles the data the user enters.

The command "z = Dialog(NameInfo)" displays the dialog window on the screen, and then waits for one of the three buttons to be clicked. Once that happens, an If...Then statement block routes the program flow appropriately, depending on which button was clicked. Assuming the user typed in data and clicked the OK button, a second If...Then statement block manipulates the entered name--if necessary, as determined by the radio buttons--so that it is in the order "first-name last-name", and displays the name in a MsgBox.


Users of a dialog box which utilizes several of the above commands will be happy to note that it is possible to jump from any control to the next one by using the Tab key, and from any control to the previous one by using the Shift-Tab key combination. This can aid users who get confused when using a mouse or who often accidentally miss a control, as repeatedly pressing Tab or Shift-Tab will cycle through all of the controls, making each "active" in turn.

And that's that. The end...?


Return to Lesson #11.
Return to Main page.

Copyright 2003, Joel A. Hahn
Sponsored and endorsed by OCLC Online Computer Library Center, Inc.