Scripting Solutions with WSH and COM

In "Scripting Solutions with WSH and COM: Extending WSH with ActiveX Controls," July 2002, InstantDoc ID 25288, I introduced you to GooeyScript, an ActiveX control built to extend Windows Script Host (WSH) that lets you quickly create event-driven forms. Let's look at how we can use some of the other great ideas in GooeyScript, such as incorporating multiple buttons, custom backgrounds, progress bars, and various other form elements.

Closing Forms Gracefully
The BasicWorkingForm.vbs script in my July column demonstrated how you can create a simple form with one button. The script displays the form on screen, pauses execution until you click the button, and finishes execution after you click the button. The script included one problem that I didn't have time to address. The form's border contains a close button. When you click the close button, the form disappears and GooeyScript terminates the object instance and the script. Lee Carlson, the author of GooeyScript, has addressed this problem by adding a special event called FormClose that redisplays the form and prevents GooeyScript from terminating the script prematurely.

Listing 1 shows NewBasicWorkingForm.vbs, which adds a new snippet of code to BasicWorkingForm.vbs. The new code snippet, which callout A in Listing 1 shows, is easy to understand: You simply handle the Form::FormClose event in the same way you handle any other event, use the Form::OnTop property to place the form on top of all other windows, and use the Form::Visible property to make the form visible. Of course, if you want to use the close button to close the form gracefully, you must modify the contents of gsForm.FormClose() to do whatever you want to do, then use gsForm.Unload to close the form gracefully.

Creating Multiple GooeyScript Buttons
If we pick up where we left off last time, the next logical step is to expand the single-button form into a multibutton form. After you understand this approach, you can apply the same principles to your own scripts.

Listing 2 shows Multi-ButtonForm.vbs, which uses the script in Listing 1 as a base. To add three additional buttons to the form, you must modify the original line of code that created the Exit the form button to create four new buttons. These buttons will appear on screen as Button 1 through Button 4 and are denoted as Button1 through Button4, respectively, in the script. You load the four buttons to the form by using the Button::Load method. To equally space the buttons on the form, position Button1 100 pixels from the left edge of the form and 50 pixels down from the top, position Button2 350 pixels from the left edge and 50 pixels down from the top, position Button3 100 pixels from the left edge and 150 pixels down from the top, and position Button4 350 pixels from the left edge and 150 pixels down from the top.

If you didn't modify anything else in the script and you clicked any of the buttons, the script would generate an event for the gsForm_ButtonClick event to handle. The event handler would call the Form::UnPause method, close the form, and terminate the script gracefully. However, you typically want each button to trigger a separate action. Because you have only one event-handler subprocedure for all four buttons, you must place all the code that needs to occur for each button action into the event-handler subprocedure. However, unless the code for all the buttons is short, you would typically use a Select Case statement to call a separate subprocedure for each button.

Notice that the Select Case statement at callout A in Listing 2 selects on only three buttons, just to demonstrate that you can create a button that does nothing. If you click a button and nothing happens, remember that you might have forgotten to handle the event in the event handler or you might be calling an empty subprocedure.

Button 1 in this example does nothing, no matter how many times you click it. To show that Button 1 does nothing, Button2 calls the HideButton1 subprocedure, which uses the Button::Visible method to hide Button 1. As a result, when you click Button 2, the script hides Button 1 on the form.

Button3 looks innocuous, calling the SayHi3 subprocedure, which creates a separate message box. However, I discovered a pitfall while playing with GooeyScript. If you use the Form::OnTop method at the beginning of a script to make the form always appear on top of all other windows, you can't use MsgBox or WScript::Echo to display a message on screen: Because the main form is always on top, you can't click the message box that Button 3 generates. To acknowledge the message box, you need to select it from the taskbar or move the form. Alternatively, after you click Button 3 for the first time, subsequent clicks will bring the message box to the front because the script doesn't call the Form::OnTop method between button clicks. A better way to let the user acknowledge the message box is to set the OnTop requirement to FALSE, display the data you need, then reset the form to be on top, assuming that's what you want to do.

Button 4 calls the CloseMyForm subprocedure. When you click this button, the script uses the Form::UnPause method to terminate the script gracefully.

To use Multi-ButtonForm.vbs, just replace the button names (i.e., Button 1, Button 2, Button 3, and Button 4) with sensible names relating to what they do, and replace HideButton1, SayHi3, and CloseMyForm with subprocedures that the script can call from the Select Case statement to perform the actions you require. Because you need a way to close the form, make sure that one of your subprocedures calls the Form::UnPause method so that you can close the form gracefully.

Adding a Custom Image
Let's digress for a moment and get a bit more radical with form design. You can modify the Form::Load method in Listing 1 to include a seventh parameter that adds a path to a JPEG photo, as in the code

gsForm.Load ,,,,"This is a " & _
  "form with a simple button",, _
  "c:\My Scripts\Jenny and " & _

Amazingly, the form will expand to match the size of the JPEG image. This parameter is a simple way to include a corporate brand on your forms. Just be careful when you select an image: Misspelling or specifying a wrong image path will create a form that doesn't display correctly and force you to use taskmgr.exe to close the hidden window.

Inserting Progress Bars
GooeyScript offers a great solution for creating progress bars. ProgressBar.vbs, which Listing 3, page 10, shows, introduces a modified version of Listing 1 that contains a progress bar. Instead of loading a button, you use the ProgressBar::Load method, which callout A in Listing 3 shows, to load a progress bar. Because this method takes the same four size-and-location parameters as the button load statement does, you can use the same parameters that you used for the button in Listing 1 to make the progress bar any size you like. The fifth parameter lets you specify which image to use to fill the progress bar. (GooeyScript includes a progressbar.gif file that you can use as the gradual indicator that fills your progress bar.) If you specify an image that's smaller or larger than the progress bar, the display will scale the image to fill the available area. ProgressBar.vbs loads an image called Jenny and Bill.jpg to fill the progress bar. The complete picture of Jenny and Bill first appears scaled down to a thickness no wider than a line, then expands as the progress bar fills, finally scaling to the fullest possible extent when the progress bar reaches 100 percent. The optional sixth parameter states that the percent value should appear in the middle of the progress bar as it fills. (This parameter defaults to TRUE if you don't include it; changing this parameter to FALSE stops the percent value from appearing.)

The simple For...Next loop at callout B controls the progress bar fill rate and uses the ProgressBar::Value method to set the fill percentage. After the loop finishes, I use the same ProgressBar::Value method to update the fill percentage to 100 percent, but this time I include a second parameter to provide text (i.e. "Done!") that I want to display in the progress bar instead of the "100%" default choice.

Because Listing 3 has no Exit the form button, I need a new way to close the form and gracefully terminate the script. The gsForm_FormClose event handler unpauses the script and handles the close button in the window's top-right corner.

Going Beyond Buttons
GooeyScript includes three additional objects you'll want to master and add to your toolbox. These objects are OptionButton (often called radio buttons), CheckBox, and ComboBox.

ComplexForm.vbs, which Listing 4 shows, uses all three objects to make the form that Figure 1 shows. You use the Form::OptionButton object to display four radio buttons and the OptionButton::Load method to load the associated options. The first parameter specifies the text label that you want to use for the radio button on the form, as well as the name you'll use to identify the radio button. The remaining four parameters specify the size and location of the radio button and are the same parameters used in Listing 1 to place the button. When the form first appears on screen, no radio button is selected. When you select a radio button, the script calls the gsForm_OptionButtonClick event handler and creates a message box that displays the selected button's name, as callout C in Listing 4 shows.

Listing 4 includes two check boxes. To display the check boxes, you must use the Form::CheckBox objects and CheckBox::Load methods at callout A. The first parameter specifies the text label to use for the check box, as well as the name used to identify the check box. The next four parameters specify the location and size of the check boxes. The optional sixth parameter lets you specify a caption for the check box. The seventh parameter in the script sets the starting value for the check boxes to FALSE. When you select either check box, the script calls the gsForm_CheckBoxClick event handler at callout E. This event handler uses the CheckBox::Value method and the VBScript UCase function to display whether the selected check box is set to TRUE or FALSE.

To display a drop-down combo box, you need to use the Form::ComboBox object and the ComboBox::Load method (at callout B) in a similar manner to the other form objects. The first parameter specifies the combo box name (Combo1 in this case). The next three parameters specify how far the combo box appears from the left edge of the form, how far the combo box is from the top edge of the form, and how wide the combo box is, respectively (all three parameter values are in pixels). GooeyScript doesn't include a parameter for specifying the height, because a combo box always has a fixed height. The fifth parameter is a string containing a comma-separated list of items to choose from when you select the combo box on the form. The first value in a combo box typically instructs the user to select an item from the combo box. For example, the first value in Listing 4 is called "—-Pick an item—-". GooeyScript considers the first value an item in the combo box list. Therefore, to display this item on the form, you must select the item, just as if you had clicked it. To select the first item, you use the ComboBox::Value method and specify the combo box to modify and the item to select. When you click the combo box to display its list, the script generates a ComboBoxDropDown event. Although Listing 4 doesn't show an event handler for this action, ComplexForm.vbs does handle the ComboBoxClick event. The handler (at callout D) checks to make sure you select a combo box item other than the first item and displays the name of the selected item.

In all these examples, the script uses VBScript's MsgBox function to display the results. You'll want to customize these scripts to create objects and handle events as your requirements dictate.

Moving Forward
I've touched on GooeyScript's ability to add single buttons, multiple buttons, progress bars, radio buttons, check boxes, and combo boxes. GooeyScript also makes adding text boxes (with or without scroll bars), pictures, and PictureClick events easy. You can also use GooeyScript to easily add labels that support click events to your forms and specify a variety of fonts, colors, and borders for these labels. GooeyScript comes with a demoscript.vbs file that includes good examples of all these features.