This chapter introduces the concept of using wizards and provides guidance on why and when to use wizards. You'll be guided through planning an example application by using the wizard paradigm. Then you'll be taken step-by-step through building the application and, along the way, you'll learn how to build an intuitive process flow and how to avoid design pitfalls in your own wizard applications.
When you examine the workflow of many user interfaces, you'll often find that the user is processing the same series of tasks over and over again. There are instances where the application asks the user a series of questions and builds a response set or a finished product. This may be an appropriate place to design a wizard interface for your application. Later in this chapter, you'll learn how to design and build a wizard, but first, some application tasks that are suitable for a wizard will be discussed.
If you've ever used Microsoft Access, then you probably are already familiar with using wizards. The Access Report Wizard is one of the best examples of a successful implementation of the wizard paradigm. The Report Wizard prompts the user for information about which tables or queries to use, which fields to use in the report, and in which order to use them. The Report Wizard then asks if the user wants totals and subtotals, and how to group and sort the report. When the Report Wizard has collected all the essential information from the user, it asks the user to select a presentation format for the report. Then the Report Wizard assembles all this information and presents the user with a complete, finished product: a professional-looking report.
Now examine what happens in the process of using the Report Wizard. The program asks a series of questions. The Report Wizard gathers essential information from the user in the form of answers to questions and then presents a finished product to the user. Keep in mind that, to a user, a wizard appears only to ask a series of questions. Each question usually has a finite number of answer choices. After the wizard has gathered all the necessary information, it processes the information behind the scenes--that is, the processing is transparent to the user--before presenting the finished product.
Many applications lend themselves to this sort of querying process interface, such as the following:
When designing a wizard, it is necessary to break the essential pieces of information into logical units first. Then these logical units must be placed in an appropriate order. For example, a report-building wizard would not ask about sorting fields before asking the user to select fields. First the user would be asked what information to include and then would be asked how to present that information. Similarly, a loan calculator wizard would not ask a user to select interest rates--this information would come from a database. Instead, the program would ask about the principal of the loan, frequency of payments, duration of the loan, and so forth. Lastly, the user can be presented with a choice about the presentation or routing of the finished information.
The Wizard Manager simplifies the daunting task of building a wizard with Visual Basic 5.0. If you wanted to create a wizard in earlier versions of Visual Basic, you had to build your own wizard from scratch. The process was not complex, but it was certainly cumbersome. At the time, the accepted method was to create a single form with individual frames, which contained the controls for each step of the wizard. Then the frames were either shown or hidden to present individual screens to the user. A few enterprising developers built reusable classes from these models, but it was still slow and cumbersome work. With Visual Basic 5.0, this approach has been incorporated as the Wizard Manager, which is now included as an Add-In tool.
A Note from the Author
There is very little documentation about the Wizard Manager on the Visual Basic disks. In fact, you cannot find "Wizard Manager" when searching the help index, but you will find a very brief overview under "Wizard Wizard."
The Wizard Manager automates much of the tedious work involved in building a wizard application. The Wizard Manager builds the necessary frames and essential controls, and creates the code to control the behavior of the interface elements (for example, navigation buttons). When you use the Wizard Manager to create a skeleton wizard, you can be assured that the design of your wizards will be consistent.
While the Wizard Manager greatly speeds up your wizard development, it doesn't do all the work for you. Remember that the Wizard Manager only builds a template, a skeleton wizard. You still have to add the controls and the code specific to your interface needs, and you have to write the code to process the information that your wizard gathers from the user. Although the Wizard Manager provides some rudimentary error handling, if you want more sophisticated error handling or conditional branching, you have to provide that code yourself.
First, you need to install the Wizard Manager Add-In. From the Visual Basic toolbar, select Add-Ins; then click the Add-In Manager. You will see the available add-ins. Check the box next to VB Wizard Manager, as illustrated in Figure 44.1.
FIG. 44.1
Here is the Visual Basic Add-In Manager, which shows the screen when the new VB
Wizard Manager is selected.
Next, return to the Visual Basic menu bar and select the Add-Ins option. Note that the Wizard Manager has been added to the submenu. Select this option and you will see the Wizard Manager form, as shown in Figure 44.2.
FIG. 44.2
You can create a template wizard by following the prompts from the Wizard Manager
Add-In.
You are almost ready to begin building your wizard, but first you must complete the most important step: planning.
Obviously, it is important to plan every application, but all too often, developers simply sit down at the keyboard with a rough idea of what they want and begin to code. While this is undeniably bad practice, the result can be even worse with a highly specialized interface, such as a wizard. So, before you begin to design or code anything, stop and think about the design. How will the design be most intuitive to the user? Careful design now will not only make your program more usable, but it will also make it easier to develop--and you certainly will reduce the chances that you will have to go back and redesign the application.
Most wizards today are extensions of existing larger applications. But a wizard can be the entire application, as is the case in the example you'll be building in this chapter.
The application you will design is a user interface for ordering a pizza, in which the user is asked a series of questions, and the wizard then builds the order and asks the user if the order is correct. If the user answers affirmatively, the order is built and e-mailed to the appropriate pizza kitchen. You'll see from this relatively simple demonstration application that you can easily build powerful intranet applications.
To start, you need to determine what information your application must obtain from the user. First, you need to identify the user. Presuming that there is a database with previous orders on file, you will ask the user to enter a telephone number.
NOTE: If you want to build a truly powerful intranet application from this example, add an interface to a telephone database and match the users' telephone numbers with their addresses.
Now you need to ask the users what kind of pizza they would like. You should build the pizza logically, from size, to crust, to sauce, to toppings. Finally, ask the users whether they want to order add-on items, such as garlic bread and soft drinks.
Now pause a minute and re-read the preceding paragraph. These descriptions are very logical, discrete units. In essence, then, you are defining the steps of the pizza-order process. From looking at these units, you should begin to understand how to build the wizard screens.
The wizard needs a splash or welcome screen and a summary screen at the end. You can design the entity diagrams, or logical units, for these screens. As you go through them, there may be quite a few toppings you want to include. Thus, you should subdivide toppings into two types--meat and cheese, and vegetables. Perhaps you can combine the crust and sauce type screens. If you block these screens out into an entity diagram, you'll have the high levels of your wizard screens defined, as in Figure 44.3.
Now that the entities, or logical units, have been clearly delineated, you are ready to begin designing the screen frames for the application.
A wizard should always start with an introductory, or splash, screen. The splash screen should identify the application wizard and tell the user some basic information about what to expect--for example, that the wizard will ask questions and present a series of options to make the process as simple as possible. The Wizard Manager will create a basic introductory screen--you'll add appropriate text and graphics to it later on.
FIG. 44.3
After the order process is broken into eight logical units, eight screens are
defined for the Pizza Wizard.
To begin, start a new project and name it "Pizza Wizard." Now select Add-Ins from the menu bar and select the Wizard Manager. Immediately, you see the template forms for a generic wizard in the Wizard menu frame. If you don't see the pre-built steps--Introduction, Steps 1, 2, 3, 4, and Finished!--right-click the Wizard Manager and select New Wizard. The Wizard Manger creates two forms automatically (Wizard.frm and Confirm.frm) and opens the Wizard template screens, as shown in Figure 44.4.
FIG. 44.4
The Wizard Manager pre-builds the wizard template forms, which you can modify
for your own wizard application.
NOTE: You must name the main form in your wizard application frmWizard!
You're now ready to get into the meat, as it were, of building your Wizard application.
Now you are ready to begin modifying the template Wizard to build your own Wizard. By default, the Wizard Manager creates four Step x template screens. Because you will need six screens, click the Add A Step button and add two more. You'll be asked for names, but for now, just name them Step 5 and Step 6.
Next, double-click each of the Step x captions and change them, as set forth in Table 44.1 and shown in Figure 44.5.
Original Caption | New Caption |
Introduction | (no change) |
Step 1 | Step 1: Your Telephone Number? |
Step 2 | Step 2: What Size Pizza? |
Step 3 | Step 3: Crust & Sauce |
Step 4 | Step 4: Meat and Cheese Toppings |
Step 5 | Step 5: Vegetable Toppings |
Step 6 | Step 6: Accompaniments |
Finished! | (no change) |
If you mix up the screen order, you can always rearrange the order by clicking the Move Up and Move Down buttons on the Wizard Manager.
FIG. 44.5
After you have set all the captions, you will have eight screens in the Pizza
Wizard.
TIP: You don't have to rename the items in the Wizard Manager, but you'll find it easier to maintain your wizards if you give the frames meaningful names instead of something overly generic, such as Step 3.
Now change the project startup form to frmWizard and run the application. You'll see that the Wizard Manager has inserted the appropriate navigation buttons into the form for you. Now just add graphics and appropriate text to create the visual portion of the interface.
Now close the application and return to Visual Basic. Examine the Wizard form and note how you can navigate among the various frames by clicking the appropriate screen title in the Wizard Manager, as explained earlier.
The various Wizard screens are saved on frame controls. Start by selecting the first frame in the array. This form has only three controls on it: a picture box, a label, and a check box. Usually, the check box should be left as it is, which enables users to select the Skip this screen in the future option. The Wizard Manager creates the code to activate this check box option, too. The Step frames, however, have only two controls each: the picture box and a single label. These controls are all control arrays; thus, it is simple to correlate them with the frame names as you work.
Create your own version of the Pizza Wizard by using the following figures and control name tables as a guide. Figures 44.6 through 44.12 illustrate the remaining screen modifications. Begin by modifying Frame(0), the Introduction screen, as in Figure 44.6.
FIG. 44.6
Add an appropriate graphic to the PictureBox control.
Add the controls listed in Table 44.2 to the frame Step 2: "What Size Pizza?"
FIG. 44.7
Add a graphic, as you did for Figure 44.6, to the second screen, and add a text
box for a telephone number.
FIG. 44.8
Add option buttons for the "Step 2: What Size Pizza?" choice.
Control Type | Name | Caption or Text |
OptionButton | optSizeSmall | Small (8") |
OptionButton | optSizeMedium | Medium (12") |
OptionButton | optSizeLarge | Large (16") |
OptionButton | optSizeParty | Party Size (24") |
Control Type | Name | Caption |
Frame | fraCrust | Crust Type |
OptionButton | optCrustRegular | Regular |
OptionButton | optCrustWholeWheat | Whole Wheat |
OptionButton | optCrustGarlic | Garlic Sourdough |
Frame | fraSauce | Sauce |
OptionButton | optSauceRegular | Regular Tomato |
OptionButton | optSauceSpicy | Spicy Tomato |
OptionButton | optSaucePesto | Pesto |
FIG. 44.9
On the third screen, as depicted in this figure, you have two frames, one for
crust type and one for sauce (see Table 44.3).
FIG. 44.10
The Step 4 frame has multiple check boxes so that the user can select multiple
toppings (see Table 44.4).
Control Type | Control Name | Caption or Text |
CheckBox | chkMozzarella | Mozzarella Cheese |
CheckBox | chkRomano | Pecarino Romano Cheese |
CheckBox | chkGorgonzola | Gorgonzola Cheese |
CheckBox | chkPepperoni | Pepperoni |
CheckBox | chkSausage | Italian Sausage |
CheckBox | chkCanadianBacon | Canadian Bacon |
CheckBox | chkAnchovies | Anchovies |
FIG. 44.11
As with the meat and cheese topping screen, the Step 5, "Vegetable Toppings,"
frame has a number of check boxes so that the user can select multiple toppings (see
Table 44.5).
Control Type | Control Name | Caption or Text |
CheckBox | chkOnion | Onion |
CheckBox | chkRedOnion | Red Onion |
CheckBox | chkGarlic | Roasted Garlic |
CheckBox | chkOlive | Olives |
CheckBox | chkPineapple | Pineapples |
CheckBox | chkMushroom | Mushrooms |
CheckBox | chkHotPepper | Hot Peppers |
CheckBox | chkBellPepper | Bell Peppers |
Control Type | Control Name | Caption |
CheckBox | chkGarlicBread | Garlic Bread (Serves 6) |
CheckBox | chkBuffaloWingsSpicy | Spicy Buffalo Wings (1 dozen) |
CheckBox | chkBuffaloWingsMild | Mild Buffalo Wings (1 dozen) |
CheckBox | chkColaRegular | Regular Cola (6-pack) |
CheckBox | chkColaDiet | Diet Cola (6-pack) |
FIG. 44.12
The final step in collecting information from the user is the Accompaniments frame,
where you have two option groups.
Because they contain check boxes, the frames are optional (see Table 44.6). The wizard now should be able to gather all the information necessary to process the customer's order. But good wizard design dictates that the program process the information and present it to the user so that the user can go back and change it if necessary. For a typical wizard application, the Finish button is active only on the final frame. The Wizard Manager cre-ates the "Finished!" frame for you; in most cases, there is no need to change this frame. For this particular application, the text on the command button could be changed to "Place Order." The chkSaveSettings control can be used to enable the customer to make the same order next time.
The Confirm dialog box, illustrated in Figure 44.13, appears last. It is a separate form that serves to confirm that the order has been sent. In the background, the program assembles the information and e-mails it to the proper pizzeria.
FIG. 44.13
The Confirm dialog box is a separate form that appears after the user has clicked
the Finish button on the last frame of the wizard.
You have created an interface with the help of the Wizard Manager, but as noted earlier in this chapter, the Wizard Manager doesn't make your wizard do anything. You still have to write most of the functional code.
In this section, you learn how to modify the code the Wizard Manager created. You also look at some error-handling techniques for the wizard paradigm. Finally, you learn how to use resource files to create wizard libraries that you can quickly modify for easy maintenance.
Now that you have built the interface, you can run the wizard, and even compile it, but it is still just a series of screens. In fact, notice that the form caption doesn't change properly, and the Finish button appears prematurely. It's time to look at the code built by the Wizard Manager and make the essential changes. The declarations section code generated by the Wizard Manager is provided in Listing 44.1.
Option Explicit Const NUM_STEPS = 8 Const RES_ERROR_MSG = 30000 `BASE VALUE FOR HELP FILE FOR THIS WIZARD: Const HELP_BASE = 1000 Const HELP_FILE = "MYWIZARD.HLP" Const BTN_HELP = 0 Const BTN_CANCEL = 1 Const BTN_BACK = 2 Const BTN_NEXT = 3 Const BTN_FINISH = 4 Const STEP_INTRO = 0 Const STEP_1 = 1 Const STEP_2 = 2 Const STEP_3 = 3 Const STEP_4 = 4 Const STEP_FINISH = 5 Const DIR_NONE = 0 Const DIR_BACK = 1 Const DIR_NEXT = 2 Const FRM_TITLE = "Blank Wizard" Const INTRO_KEY = "IntroductionScreen" Const SHOW_INTRO = "ShowIntro" Const TOPIC_TEXT = "<TOPIC_TEXT>" `module level vars Dim mnCurStep As Integer Dim mbHelpStarted As Boolean Public VBInst As VBIDE.VBE
Several values in the Declarations section need to be changed; the necessary changes for the sample are noted in Listing 44.2.
Option Explicit Const NUM_STEPS = 8 Const RES_ERROR_MSG = 30000 `BASE VALUE FOR HELP FILE FOR THIS WIZARD: Const HELP_BASE = 1000 Const HELP_FILE = "PIZZAWZD.HLP" ` Help file name Const BTN_HELP = 0 Const BTN_CANCEL = 1 Const BTN_BACK = 2 Const BTN_NEXT = 3 Const BTN_FINISH = 4 Const STEP_INTRO = 0 Const STEP_1 = 1 Const STEP_2 = 2 Const STEP_3 = 3 Const STEP_4 = 4 Const STEP_5 = 5 ` Constant added Const STEP_6 = 6 ` Constant added Const STEP_FINISH = 7 ` Constant changed Const DIR_NONE = 0 Const DIR_BACK = 1 Const DIR_NEXT = 2 Const FRM_TITLE = "Pizza Wizard" ` Form caption changed Const INTRO_KEY = "IntroductionScreen" Const SHOW_INTRO = "ShowIntro" Const TOPIC_TEXT = "<TOPIC_TEXT>" `module level vars Dim mnCurStep As Integer Dim mbHelpStarted As Boolean Public VBInst As VBIDE.VBE
Now that changes have been made in the Declarations, it is necessary to change the SetStep() subroutine accordingly, as noted in Listing 44.3.
Select Case nStep Case STEP_INTRO Case STEP_1 Case STEP_2 Case STEP_3 Case STEP_4 Case STEP_5 Case STEP_6 mbFinishOK = False Case STEP_FINISH mbFinishOK = True
The purpose of the code in Listing 44.3 is to change the mbFinishOK variable to be called on the sixth, or last step, rather than the fourth, or default frame. Otherwise, the user sees the finish button enabled prematurely in the fourth screen frame.
If you want to use conditional branching, that is, present different options on subsequent wizard screens, you can insert it into the code in Listing 44.3.
An essential feature of any wizard is error handling. The wizard must check, for instance, that the user has entered the necessary data in the required fields.
For the purposes of this example, you have enabled the essential error handling on only one screen. But, from the techniques in the example, you will be able to see how to insert more sophisticated error handling, and even conditional branching routines, into your own wizard interfaces.
The Wizard Manager creates a subroutine called IncompleteData, which displays error messages. First, however, the Wizard needs criteria to detect errors or omissions. You must pass this information to the IncompleteData subroutine. This error checking is the purpose of the CheckForIncompleteData subroutine. The subroutine in Listing 44.4 is not created by the Wizard Manager; you must add it.
Sub CheckForIncompleteData(nStep As Integer) Select Case nStep Case STEP_INTRO Case STEP_1 If txtTelephoneNumber.Text = "" Then IncompleteData (mnCurStep) End If Case STEP_2 Case STEP_3 Case STEP_4 Case STEP_5 Case STEP_6 Case STEP_FINISH End Select
To call the subroutine from the next button, simply call the function with a simple If...Then statement, as in Listing 44.5.
Private Sub cmdNav_Click(Index As Integer) Dim nAltStep As Integer Dim lHelpTopic As Long Dim rc As Long CheckForIncompleteData (mnCurStep) Select Case Index Case BTN_HELP mbHelpStarted = True lHelpTopic = HELP_BASE + 10 * (1 + mnCurStep) rc = WinHelp(Me.hwnd, HELP_FILE, HELP_CONTEXT, lHelpTopic) Case BTN_CANCEL Unload Me Case BTN_BACK `place special cases here to jump `to alternate steps AltStep = mnCurStep - 1 SetStep nAltStep, DIR_BACK Case BTN_NEXT `place special cases here to jump `to alternate steps AltStep = mnCurStep + 1 SetStep nAltStep, DIR_NEXT Case BTN_FINISH `wizard creation code goes here Unload Me If GetSetting(APP_CATEGORY, WIZARD_NAME, CONFIRM_KEY, vbNullString) = vbNullString Then frmConfirm.Show vbModal End If End Select
If you want to include more sophisticated branching or error handling, the cmdNav_Click procedure is the appropriate place to insert this code.
The Wizard Manager creates an easily maintainable program skeleton, which requires the minimal code manipulation listed in the previous sections. Much of what the user sees in the interface, however, is customized and controlled from a resource file.
A resource file can be added and removed from the Visual Basic project just as any other object can, except that you can't work with the file directly from Visual Basic. First, you need to create the source file, then compile it into a resource .res file.
The Wizard Manager creates a template resource file that holds strings for the captions of the various buttons and labels in the wizard application. The source code created by the Wizard Manager for the template resource file is contained in Listing 44.6.
STRINGTABLE DISCARDABLE BEGIN //Wizard Caption 10 "Wizard Template" 15 "Wizard Template..." //Button Captions for Navigation Control: 100 "Help" 101 "Cancel" 102 "< &Back" 103 "&Next >" 104 "&Finish" //Intro Info: 1000 "Introduction" 1001 "The ??? Wizard will help you ..." 1002 "&Skip this screen in the future." //Other Step Control Captions: 2000 "Step 1" 2001 "Instructions for this step." 2002 "Step 2" 2003 "Instructions for this step." 2004 "Step 3" 2005 "Instructions for this step." 2006 "Step 4" 2007 "Instructions for this step." //Finish Step: 3000 "Finished!" 3001 "The ??? Wizard is finished collecting information.\r\n\r\n_" 3002 "To build your ???, press Finish!" 3003 "Save current settings as default" //Confirmation dialog 10000 "??? Created" 10001 "The ??? has been created." 10002 "Don't show this dialog in the future." 10003 "OK" //Misc strings: 20000 "(None)" //Error messages: 30000 "Incomplete Data." 30001 "You must ... before you can continue." END
You can modify each of the strings in the preceding source code to match what you want your wizard to say to the user. The numbers to the left of each string refer to the Tag property of the controls on the wizard. Note that the /r/n characters in the resource file signal the compiler to insert a carriage return and new line into your text.
NOTE: If you are interested in seeing how the code refers to the Tag property, examine the code in the Wizard.bas module on the companion CD.
To modify your own resource file, use a text editor and open the file wizard.rc in your working directory. Make the changes listed in Listing 44.7 to the source code.
STRINGTABLE DISCARDABLE BEGIN //Wizard Caption 10 "Pizza Wizard" 15 "Pizza Wizard..." //Button Captions for Navigation Control: 100 "Help" 101 "Cancel" 102 "< &Back" 103 "&Next >" 104 "&Finish" //Intro Info: 1000 "Introduction" 1001 "The Pizza Wizard will take you step-by-step through the order process.\r\n\r\n The Wizard will ask a series of questions about how you like your pizza, and then your order will be prepared!" 1002 "&Skip this screen in the future." //Other Step Control Captions: 2000 "Step 1" 2001 "Enter your telephone number below:" 2002 "Step 2" 2003 "What size pizza would you like?" 2004 "Step 3" 2005 "Select a sauce and crust type." 2006 "Step 4" 2007 "Select your favorite meat and cheese toppings." 2008 "Step 5" 2009 "Select your favorite vegetable toppings." 2010 "Step 6" 2011 "Don't forget beverages and side orders to go with your pizza!" //Finish Step: 3000 "Finished!" 3001 "The Pizza Wizard is finished collecting information.\r\n\r\n To send your pizza order, press Finish!" 3003 "Save current settings as default" //Confirmation dialog 10000 "Order Created" 10001 "Your pizza order has been created." 10002 "Don't show this dialog in the future." 10003 "OK" //Misc strings: 20000 "(None)" //Error messages: 30000 "Incomplete Data." 30001 "You must enter required information before you can continue."
Note that most of the modifications in the code in Listing 44.7 are simply changes to the text strings. But as you have added screens, you need to go back to the interface and check the Tag properties on the controls for the screens that you added. If you neglect this step, your controls will not display the label text you entered in Listing 44.7.
TIP: If you want to customize your wizard further, you can change the &Finish string to &Send Order.
Now you're ready to compile your resource file. But first you need to make sure that the Resource Compiler is installed on your system.
NOTE: The modified code does not include any bitmaps. In the example on the CD-ROM, the bitmaps are imbedded directly into the controls. However, you may want to refer to your own wizards in the resource file. If you do, make sure that they are in the application directory, where the wizard is installed.
If the Resource Compiler is not already installed on your system, you need to copy it from the Visual Basic CD. You'll find it in the Tools\Resource\ directory. There is no install process; simply copy the rc.exe and rcdll.dll files to your hard drive. You will find it helpful to copy the Resource Compiler directly into the directory where you are working with your wizard.
The Resource Compiler is discussed extensively in the VB Books Online on your Visual Basic CD and in the readme file in the Resource Compiler tool directory, but you only need to know the basics to compile your resource file. To compile the file, run the following in the working directory:
RC /v /r wizard.rc
The RC runs the Resource Compiler, the /v parameter turns on messages (so that you can see what the compiler is doing), the /r parameter tells the compiler to create the .res file, and the wizard.rc specifies the file name.
If you run the Resource Compiler and receive an error message, the /v parameter tells you which line(s) you need to correct. When you have successfully compiled the resource .res file, return to Visual Basic, open the Pizza Wizard project, and run it. You will now see your changes in the resource file reflected in the program, as illustrated in Figure 44.14.
FIG. 44.14
The control tags are associated with the appropriate strings in the compiled resource
file.
Now that you have received the essential order information from the user and have verified it, the Pizza Wizard is ready to assemble the pizza order. Depending on the nature of the environment, the order can be e-mailed to the appropriate pizza deli, or simply printed in the kitchen.
In this chapter, you learned how to build a simple wizard, collect the necessary information from the user, and check for errors or omissions. When you are ready to build more complex wizards or explore the possibilities of Internet-enabled Wizard interfaces, explore these sources:
© Copyright, Macmillan Computer Publishing. All rights reserved.