So far, you've learned a good bit about designing programs. You know by now that your programs must not only function properly, they must look good as well. No matter how hard you work to make your program perform its assigned tasks as efficiently as possible, a bland or poorly designed interface can cause your users to have the perception, however unfounded, that your program is junk.
Chapter 20, "Designing User Interfaces," discusses several techniques for enhancing the part of your program that your user sees. You've also seen several different types of controls that you can use in your programs. This chapter takes this knowledge a step further. You will see how to use containers to organize the controls that your application uses. Proper use of containers to group your programs' controls often means the difference between a "functional" program and a really nice one.
Containers are a special type of control that is available in Visual Basic. The primary function of containers is to help you organize other controls on your forms. Containers can help you show or hide controls as a group, respond to changes in the program, or respond to user actions. Containers are also used to create functional groups of option buttons so that you can select more than one button at a time on a form. This extends what you can do with option buttons in your programs.
When you develop a simple program, one form might provide sufficient space for your entire application. But as you develop more complex programs, you will find that the available space on a form is one of the most limiting factors in program design. You can only place so many controls on a single form before you either run out of room or, more often, before your form starts looking very cluttered. A cluttered form looks unprofessional and is hard to use. Figure 13.1 shows a membership information form that tries to handle too much information.
FIG. 13.1
Cluttered forms are a poor design choice.
You could solve the problem by using multiple forms. This way, you can place some of the controls on a second or third form and show the supplemental forms only when necessary. For many applications, this is the best solution to the problem, especially if the data on the different forms is not closely related.
However, many applications (like the membership program shown in Figure 13.1) contain a large amount of related data. For these types of applications, moving between multiple forms to enter data is very inconvenient. Another solution is to go ahead and add all the controls you need to the form, but selectively hide and show certain controls by using their Visible properties. However, this method requires an unwieldy amount of code if you have more than a few controls, and it makes positioning them in design mode almost impossible.
Fortunately, there is an alternative. Several container controls in Visual Basic allow you to show, hide, and position groups of controls. They are known as container controls because you can draw other controls inside of them. For example, you could draw a TextBox on a PictureBox similar to the way you draw it on a form. The PictureBox then "contains" the TextBox.
NOTE: Container controls create a different visual relationship between the form and the controls they contain. The code events and scope of variables on the form remain unaffected.
Containers enable you to place all the controls on one form but display only the ones that you need to work with at the moment. You can use command buttons, toolbar buttons, or the container's own tabs to switch back and forth between groups of controls. Three container controls come with Visual Basic:
NOTE: The Tabbed Dialog is one of the Custom Controls in Visual Basic. To use it, you must first add it to the Toolbox from the Components dialog box (choose Project, Components).
CAUTION: Even when using containers, you should still limit the number of controls that you place on a single form. Remember, they are still on the form even if they are not currently visible. Too many controls use a lot of memory and make your forms load much slower. A good limit is 200 controls on a single form.
In addition to using containers to place more controls on a single form, you will find that containers are useful for creating groups of option buttons. In Chapter 9, "Using the Windows Standard Controls," you saw that you could select only a single option button on a form. Let's now revise that rule to read "you can select only a single option button within a container." Placing container controls on the form allows you to create multiple groups of option buttons. This lets you create applications with groups of multiple choice questions, such as the survey form shown in Figure 13.2.
The Frame control is the simplest of all the container controls. The only function of the Frame control is to hold other controls. In contrast, the PictureBox control can display graphics in addition to holding other controls, and the Tabbed Dialog control has built-in page navigation features.
FIG. 13.2
Survey forms use containers to create multiple button groups.
The Frame control is quite simple and performs its job very well. In fact, it has one key advantage over the other container controls: It uses fewer of your system's resources than the other controls. Therefore, if you do not need to display pictures in the background of your container and do not need the built-in navigation features, the Frame control is the best choice for the job. You will almost always use the frame for creating button groups.
As with all other controls, the first step in setting up the Frame control is to draw it on your form in the size that you want. Then, of course, you need to set the Name property to a unique ame. At this point, there are several properties you can set that control the appearance of the frame: Caption, Appearance, and BorderStyle. Figure 13.3 shows a variety of frames that display different effects of these properties.
See "Exploring Properties," Chapter 4
FIG. 13.3
You control the frame's appearance through the Appearance, BorderStyle,
and Caption properties.
The first property of note is the Caption property. If you enter a value in the Caption property, the text you enter appears in the upper-left corner of the frame. This caption can be used to identify the contents of the frame or provide other descriptive information. If you don't want a caption and simply want an unbroken border around the frame, delete the text in the Caption property.
TIP: To avoid having the lines of the border touch the text of the caption, insert a space before and after the text when you set the Caption property.
The second property is the Appearance property. This property controls whether the border of the frame is shown as a single-line, single-color border, which gives the control a flat look, or is shown using lines, which give the control a 3-D effect.
The final property is the BorderStyle property. This property determines whether the border around the frame is displayed. If the BorderStyle property is set to None (using a value of 0), no border is displayed, and the caption is not displayed because it is also part of the border.
TIP: If you want the frame to appear without a border, leave the border turned on while you are in design mode, but then set the BorderStyle property to 0 when your form loads. Having the border displayed in the design environment makes it easier to see the boundaries of the frame.
After you have set the properties of the frame, you are ready to start placing controls in the frame. You can place any controls you like in the frame (or any other container). You can even place containers within containers.
To place controls in a frame, first highlight the frame with a single click (it's important that the frame is selected before drawing the control). Then draw controls in the frame just like you would draw them on the form. You need to make sure that the cursor is inside the frame when you start drawing the control. Otherwise, the control will not be contained by the frame. Figure 13.4 shows several controls for a personnel application drawn in a frame.
See "Adding Controls to the Form," Chapter 4
FIG. 13.4
Make sure that your cursor is inside the frame before you start to draw a
control.
Here are a couple of points about controls and frames. First, any controls already on the form will not be contained by the frame, even if you draw the frame over the control. Second, unlike moving controls around on the form, you cannot move a control into or out of a frame by dragging and dropping the control. You can drag a control over the frame and the control will look like it is contained within the frame, but it really isn't. The only way to move a control from other parts of the form into the frame is to use cut and paste. You first cut the control from the form by selecting the control and then pressing Ctrl+X or choosing Edit, Cut. The next step is to paste the control into the frame by selecting the frame and then pressing Ctrl+V or choosing Edit, Paste. The control is initially placed in the upper-left corner of the frame, but after the control is in the frame, you can use drag and drop to move the control. You can use the same technique to move a control out of the frame. You can, of course, move multiple controls at the same time.
TIP: If you want to make sure that a control is in the frame, try moving the frame. If the control moves with it, the control is part of the frame. If the control does not move with the frame, you can use cut and paste to move it into the frame.
In Chapter 4, "Working with Forms and Controls," you saw how you could select multiple controls on a form to work with their common properties or to handle alignment and sizing tasks. You can do the same thing with controls inside a frame. The only difference is in the way you select the controls. To select a group of controls, you first need to click the form so that no controls are selected. Then hold down the Shift or Ctrl key while you click and drag the mouse around the controls in the frame. This selects the group of controls, as shown in Figure 13.5. You can still select or deselect other controls by holding down the Ctrl key while you click the controls.
FIG. 13.5
You can work with multiple controls inside a container.
NOTE: When selecting a group of controls, the selected controls must either be all inside or all outside a container. Also, control selection cannot span containers.
After the multiple controls are selected, you can work with their common properties or use the Format menu's commands to position and size the controls.
CAUTION: The Format menu's Center in Form command centers the selected controls in the form, not within the frame or other container control that they might reside in. This, in effect, renders the Center in Form command useless for controls placed inside a container.
In the section "Creating Multiple Pages on a Form" earlier in this chapter, you read that one of the uses of frames and other containers is to create multiple "pages" on a form. This technique refers to alternately showing different controls in the same location, much like turning the pages in a book. Now you get to see how this is done. The first step of the process is to determine what data will be placed in each frame to create the pages of the form. After you have determined what data will fit into each frame, you can start creating the frames themselves. You create the first frame in the manner that was discussed in the last two sections--that is, draw the frame on the form and then add the controls to the frame. Figure 13.6 shows the frame used to create the first page of a personnel application.
FIG. 13.6
The first page of a sample personnel application contains general information.
TIP: If you're going to use a series of "pages" on a form, including several frames, frames within frames, and so forth, it's a good idea to create a "storyboard" to help stay organized. This involves sketching out each frame and the controls it will contain, as well as tracking the navigation order between the various frames, much like a story editor might sketch out the various scenes of a cartoon to keep track of how it flows.
Creating the second page of the form is only slightly trickier than the first page. The key thing that you have to watch is that you start drawing the second frame outside the bounds of the first frame. If you don't do this, the second frame will be contained within the first frame, which defeats the purpose of multiple frames. The easiest way to handle this is to start the second frame below and to the right of the bottom right corner of the first frame. After you draw the second frame, you can add the control of the "page" to the frame. Figure 13.7 shows the second page of the personnel application.
You will probably want to have both frames sized the same. The easiest way to do this is to set the Height and Width properties of the frames to the same value. You might notice in Figure 13.7 that the first frame is hidden by the second frame. If you need to work with the first frame again, select it and press Ctrl+J to bring it to the front of the form. (Ctrl+K moves it to the back of the display order.)
FIG. 13.7
The second page of the sample application contains education information.
TIP: Use code at the beginning of your program to align and size frames. This makes them easier to select in the design environment, and it means you don't have to realign them before running the program.
Now that the frames are set up, you need a way to switch back and forth between them in your program. You switch between the frames by setting the Visible property of one to True while setting the Visible property of the other to False. When the Visible property of a container is set to False, the container and all its associated controls disappear from view. When the Visible property is set to True, the container and controls reappear.
The actual switch takes place in code that you write for the program. You can place the code in any event you want. However, the most typical location is in the Click event of command buttons. The code in Listing 13.1 shows how the second frame would be hidden and the first frame displayed.
fraEducation.Visible = False fraGeneral.Visible = True fraGeneral.Top = 240
Similar code would be used to display the second form and hide the first form. You would also want to place the code from Listing 13.1 in the Load event of the form to set up the initial page of the application. Figure 13.8 shows how the form would look with the first frame displayed.
FIG. 13.8
You can use one command button for each page of the application.
Another approach to handling two pages is to use the same command button for both pages and to change the Caption property of the command button to identify which frame it will display. Listing 13.2 shows how to accomplish this.
If fraGeneral.Visible Then fraGeneral.Visible = False fraEducation.Visible = True fraEducation.Top = 240 fraEducation.Left = 240 cmdGeneral.Caption = "General Information" Else fraEducation.Visible = False fraGeneral.Visible = True fraGeneral.Top = 240 fraGeneral.Left = 240 cmdGeneral.Caption = "Education Information"
You can obviously extend this discussion of using two frames to handle more frames or other containers. In fact, you'll do this when you look at creating a wizard in the section "Creating Your Own Wizard" later in this chapter.
Like the Frame control, the PictureBox control can also be used as a container for other controls. When used as a container, the picture box holds other controls and allows you to hide and display the controls as a group. Setting up the picture box is very similar to setting up a frame. Simply draw the picture box on your form and then add the controls that you want the picture box to contain.
The PictureBox control has two key advantages over the Frame control: The picture box can display a picture as the background for the other controls, and you can use the Print method and graphics methods to display information directly in the picture box. The only drawback to using the picture box is that it requires more resources than the frame does. Figure 13.9 shows a children's software sign-in screen in which a picture box with a background is used as a container for other controls.
FIG. 13.9
Use the picture box if you want a background behind your other controls.
Picture boxes are extremely versatile and can greatly enhance your application's interface. You can, for example, use one or more picture boxes within other containers to precisely place graphic images or to have multiple graphics within one frame. You can also print text to picture boxes instead of a printer, in effect creating a "print preview" for your reports.
See "Outputting Reports to Familiar Controls," Chapter 15
See "Using the PictureBox Control," found in "Doing Graphics" on this book's CD-ROM, for more information about setting up a picture box.
Another way to display large amounts of information on a single form is to use a tabbed dialog, also known as an SSTab control. Tabbed dialogs are used in many of the programs with which you are already familiar. For example, the Options dialog box of Visual Basic (shown in Figure 13.10) and the Options dialog box of Word both use tabbed dialogs to organize and present the various program options.
FIG. 13.10
Tabs enable you to place a lot of information on a form and allow your users
easy access to the information.
The tabbed dialog can best be compared to the use of file tabs or index tabs in a notebook. Each tab can have a label on it to indicate its contents. Each of the tab pages functions like a Frame control to separate the controls on the current page from the controls on other pages. The tabbed dialog is one of the custom controls that comes with Visual Basic. To be able to use it, you must first select Microsoft Tabbed Dialog Control 5.0 from the Components dialog box (choose Project, Components). After you have selected it, the SSTab control is added to the Toolbox.
NOTE: There are two minor differences between the functionality of a tab in the tabbed dialog and a frame. First, you cannot create groups of option buttons directly on a tab. (If you need to place separate groups of option buttons on a tab, you need to place them within a frame on the tab.) Second, tabs have hiding, showing, and alignment built in, while frames must be controlled more with code.
Setting up the tabbed dialog begins like the setup of any other control--you draw it on the form. When you first draw the control, it is displayed with three tabs in a single row as shown in Figure 13.11. You can change the total number of tabs and the number of tabs on each row by setting the Tabs and TabsPerRow properties. Changing the setting of the Tabs property increases or decreases the number of tabs from the initial value of three. The TabsPerRow property tells the control how many tabs to display on each row of the SSTab control. If the number of tabs is greater than the number per row, additional rows are added to accommodate all the requested tabs.
FIG. 13.11
The tabbed dialog is initially drawn with three tabs.
After you have created the tabbed dialog on your form, you can begin adding controls to the tabs. To do this, select the tab where you want the controls to be, and begin drawing controls directly on the tab. To work with another tab, simply select it by clicking the tab with the mouse. As with the frame or picture box, you can place any controls you want on each tab of the tabbed dialog. (See the note earlier in this section about grouping option buttons.) Figure 13.12 shows a completed tabbed dialog.
NOTE: Unless you set the Tab property in your startup code, the initial tab displayed will be the last one selected in the design environment.
In addition to controlling the number of tabs in the tabbed dialog, you can control its overall appearance by using a number of properties. Two properties are also available for each tab that allow you to customize the individual tabs.
FIG. 13.12
Place controls on each page of the tabbed dialog to create multiple pages
of an application.
Changing the Appearance of the Dialog Five key properties of the tabbed dialog control its overall appearance: Style, TabHeight, TabMaxWidth, TabOrientation, and WordWrap. The Style property controls whether the tabs look like those in Microsoft Office for Windows 3.1 or the property page tabs of Windows 95 applications. The Office-style tabs are the default setting of the property. With the Office-style tabs, each tab is the same width, and the width is set by the TabMaxWidth property. If you choose Windows 95-style tabs, the TabMaxWidth property is ignored, and the tabs are sized to fit the caption of the tab. Figure 13.13 shows both styles of tabs.
FIG. 13.13
The two styles of SSTab controls illustrate how different-length tab captions
are treated.
The TabHeight property controls the height (in twips) of the tab portion of each page. The TabMaxWidth property sets the maximum width (in twips) of each tab. Setting this property to 0 causes the tabs to be sized to fit all the way across the control. Remember, the TabMaxWidth property has no effect on Windows 95-style tabs.
The TabOrientation property controls the placement of the tabs in relation to the body of the control. You can choose to have the tabs placed at the top of the control (the default setting), the bottom of the control, or on the right or left side of the control. Figure 13.14 shows the placement of tabs at the top and right of the control.
FIG. 13.14
You can choose where to position the tabs on the control.
TIP: If you are placing the tabs at the side of the control, be sure to use a TrueType font that can be rotated to be displayed vertically.
The final property to look at is the WordWrap property. This property controls whether multiple lines of text will be printed in the tab. If WordWrap is set to True, the text of the Caption property will be placed on multiple lines, if necessary. If there are more lines than will fit within the height of the tab, some of the caption will be lost. If the WordWrap property is set to False, only one line will be shown in the tab. If the Caption is larger than the tab can accommodate, only the center portion of the caption will be visible.
Customizing the Individual Tabs While the previous section dealt with the appearance of the tabbed dialog as a whole, you can also customize the individual tabs of the control. There are two properties for customizing each tab: the TabCaption property and the TabPicture property. These properties allow you to specify a custom caption and a picture for each tab in the control. While you are working with the tabbed dialog in the design mode, you do not see these properties listed in the Properties window. Instead, you see the Caption and Picture properties. As you work with each tab, the TabCaption and TabPicture properties for that tab are displayed in the Caption and Picture properties. Setting the Caption property has the same effect on a tab as it does on a label or command button. The contents of the Caption property are displayed on the tab. Unless you are using long captions, each caption will probably appear as a single line of text on the tab. If the caption is long, its appearance will be controlled by the setting of the WordWrap property.
If you want to include a picture on the tab, you simply set the Picture property of the tab to the image that you want displayed. If a picture is used, the SSTab control places as much of the picture on the tab as possible. The picture is centered vertically and horizontally on the tab. If the picture is taller than the tab height, both the top and bottom of the picture are cropped. From side to side, the picture and the caption are centered together. This means that the caption text appears to the right of the picture, and the total width of of the picture and the caption are centered. The picture is not cropped on the sides unless it is wider than the width of the tab. For pictures smaller than the width of the tab, the full width of the picture is shown and the caption is given the remaining space. Figure 13.15 shows a SSTab control with pictures and captions set for each tab.
FIG. 13.15
Pictures on the tabs can indicate the information they contain.
Using the Property Pages Although you can set all the properties of the Tabbed Dialog control from the Properties window, you might find it easier to use the Property Pages. You access the Property Pages by clicking the ellipsis (...) button next to the Custom property in the Properties window. The Property Pages give you access to all the properties of the tabbed dialog and make it easy for you to set the caption and picture of the individual tabs. Figure 13.16 shows the Property Pages for the tabbed dialog.
FIG. 13.16
Access all properties of the tabbed dialog by using the Property Pages.
You can set up all the pages of the tabbed dialog from design mode, but sometimes you might want to change some parts of the dialog while your program is running. The most common thing to do in code is to disable or hide particular tabs in the control. You might do this for a personnel application where you would want only managers to have access to information about employee compensation or evaluations. Most of the properties of the tabbed dialog are handled through the use of simple assignment statements. However, changing the properties of individual tabs requires special treatment.
Previously, you saw that the caption and picture displayed on each tab were contained in the TabCaption and TabPicture properties, respectively. These properties are actually property arrays, with one element for each tab in the control. The index of the array runs from 0 to one less than the total number of tabs in the control. For example, if you want to change the caption of the first tab in the tabbed dialog, you would use the following code:
tbdPersonnel.TabCaption(0) = "Employee"
In a similar manner, you could change the picture displayed on the tab by setting the TabPicture property. In this case, you would use the LoadPicture statement to get a picture from a file, or you could use a picture contained in the Picture property of another control.
To handle the personnel application, you would want to either disable or hide any tabs that contained confidential information. To disable a tab, you would set its TabEnabled property to False. When the tab is disabled, its caption is grayed to indicate that the tab cannot be accessed. This is shown in Figure 13.17. If you want to hide the tab altogether, you can set the TabVisible property to False keep to the user from even knowing that the tab exists.
Disabled tabs cannot be accessed by the user.
One other thing that you might want to do in your application is to show a specific tab in response to a user action. You might want to have a data validation routine that checks the value of all entered data before saving it to a database. If the user failed to enter a value or entered an improper value, you will want to display the tab that contains the control with the invalid data. To show a specific tab, you simply set the Tab property of the tabbed dialog. For example, the following code displays the second tab of a dialog:
tbdPersonnel.Tab = 1
Now that you have seen how to create the various types of containers for your programs, look at how you might use a few of these in real-life situations. Look at several relatively simple situations and then move on to creating a wizard that you could use in your applications.
You saw that one use of frames was to create multiple pages of information on a single form. However, you can also use frames to provide the user with only the command buttons that are appropriate to a specific task. I have used several variations of this method in my own programs.
The first use of this technique is in data-entry applications. In a typical application, you have buttons that allow you to move from record to record within a table. This lets the user display data and search for a particular record. Figure 13.18 shows a typical set of buttons.
FIG. 13.18
One set of buttons shown is for record navigation.
However, as soon as users start editing the record, you would want to display buttons that allow them to either save the changes or cancel the changes and return the original values to the display. Also, it is a good idea to avoid any problems that might be associated with moving to other records while editing is in progress. How can you handle this? Frames to the rescue!
By placing the record navigation buttons in one frame and the Save and Cancel buttons in another frame, you can easily switch between the two buttons sets. To make the switch, you simply set the Visible property of one frame to True and set the other one to False. This is handled by code similar to that shown in Listing 13.3. The code also changes the ForeColor property of the controls to give a visual indication to users that they're in edit mode. You can call this code from the Change event of your text boxes so that it is invoked whenever users make a change. Figure 13.19 shows the same form after the button switch.
FIG. 13.19
A second set of buttons is used to handle Save and Cancel functions.
Dim I As Integer ' For the sake of this example, we have an array of 8 text boxes For I = 0 To 8 txtOrg(I).ForeColor = vbRed Next I 'Here we hide one frame and then show another fraRecNav.Visible = False
A second use of frames for containing buttons is to display only the functions that a user is allowed to see. In one of my applications, different sets of command buttons were available to users with different security levels. By grouping the buttons in frames, it was easy to show only those buttons that corresponded to the user's security level.
One use of the two-page form is to create a browse and detail page for information in a database. The browse page would use a grid control to display selected information from a number of records. The detail page would then display all the information for the record currently selected in the grid. A single command button could be used to make the switch between the two pages. Figures 13.20 and 13.21 show the two views of the data.
FIG. 13.20
Browse multiple records to get an overall view of data.
FIG. 13.21
Switch to detail view to get more information or to edit the data.
You have probably come across wizards in several of the applications that you use. Wizards are actually miniature programs that help you perform a specific task step by step. For example, Word has a wizard that helps you perform a mail merge, and Visual Basic has a wizard that helps you set up a data access form. You can create your own wizard by using a series of frame controls. To make the wizard that you create really flexible, you will use control arrays for the frames and the command buttons. This makes the wizard easier to set up and easier to program.
The first step in creating a wizard is to set up a frame template. To do this, start with a clean form and draw a frame that is the size you need for all the pages of your wizard. Next, check the Height and Width properties of the form and place code in the Load event of the form to set these properties to their initial values. You will see why this is necessary in a moment. After drawing the frame, set its Name property to a unique name. Next, delete the text in the Caption property so that you have an unbroken border on the frame. Finally, create the first element of the frame array by setting the Index property to 0.
After you have set up the frame, you need to set up three command button arrays. Within each frame we will place command buttons with captions set to Exit, Previous, and Next. To create a command button array, draw a command button on the frame and set its Name and Caption properties. Then set its Index property to 0. As with the frame array, this creates the first element of each button array. After you have added the command buttons, your form should look like Figure 13.22.
FIG. 13.22
Start the wizard by creating a template frame as the first element of a control
array.
The reason for using control arrays will now become obvious. Before you place any other control on the frame, make a copy on the form. You do this by clicking the frame, pressing Ctrl+C to make a copy, and then pressing Ctrl+V to paste the copy on the form. As you make the copy of the frame, you also create copies of all the controls in the frame. This makes it easy to create multiple pages that have the same basic look. Also, by using command button arrays, you have to enter code in only one place to handle the navigation between pages. Listing 13.4 shows the code that would be used to move to the next page in the wizard. This code also sets the Top and Left properties of the next frame to assure that it is in the same position as the previous frame. Similar code would be used to move to the previous page. Also, if you had processing that needed to occur between pages, you could use a Select statement and check the Index argument to determine which page you are on.
Private Sub cmdNext_Click(Index As Integer) fraWizard(Index).Visible = False fraWizard(Index + 1).Visible = True fraWizard(Index + 1).Top = 240 fraWizard(Index + 1).Left = 240 Select Case Index + 1 Case 1 `Code to process first page goes here Case 2 `Code to process second page goes here End Select
After you have created all the pages you need, you need to place a Finish button on the last page. Also, on the last page, you need to disable or hide the Next button because there is no next page. Similarly, you should disable the Previous button on the first page of the wizard. At this point, the shell of your wizard has been created and you can begin setting up the other controls for the individual pages.
Containers provide a number of useful functions in your programs. They allow you to place more information on your forms, create groups of options, and even create your own wizards. To learn more about some of the other topics mentioned in this chapter, take a look at the following chapters:
© Copyright, Macmillan Computer Publishing. All rights reserved.