View Sidebar

A Million Little Pieces Of My Mind

Working with Controls

By: Paul S. Cilwa Viewed: 5/18/2024
Page Views: 686
Topics: #VisualBasic6.0 #ProgrammingforMicrosoftWindows
Chapter 6 of this free online course in Visual Basic 6.0.

Among the toolbars and dockable views that usually appear when you start up Visual Basic, one is called the Toolbox. This toolbar contains buttons for each kind of control you can place on a form. It comes with a set of standard items, but you can add more controls to the list.

The Toolbox is sizable, dockable (by default), and will automatically adjust the buttons within to the available space—except, if you make the Toolbox too short to display all the buttons, there is no scrollbar and no visual indication that all the buttons can't be seen. So I usually make it three buttons wide.

You can also create multiple "categories" (the starting category is "General") and move various controls into whatever categories you like. This is handy if you are working with a great many different controls in the same project, but I have never found it necessary.

There are a couple of ways you can get a control onto a form, using the Toolbox. One is, simply double-click the desired control, and one of them will appear, in an arbitrary place and at an arbitrary size, on the form. You can then resize and re-position it.

But, if you have to do that anyway, why not place it where you want it to start with? So my preferred method is to click once on the control, then "rubber-band" on the form where and how big I want the control to be.

After you've placed a control on a form, it is selected until you click somewhere else on the form. So, if you want to work with the control further—and this is common—you just remember to click on it again to re-select it, then do what you want to do.

Frequently Used Properties

Now that you've had a taste of putting a control on a form, let's look at some properties you will find pretty much all controls share. Since they work similarly for each kind of control, learning them will bring you a long way.

(Name)

The Name property is displayed in parentheses so that it will sort to the top of the property list. Its real name is Name, however; and it can be read at run-time that way. (It cannot be changed at run-time.)

This property is required—in fact, it is so required that when the control is first placed on the form, a name is made up for it, like "Picture1" or "Text2". These are not generally useful names, however; and you are encouraged to change them to something more specific.

Microsoft recommends you use a prefix for the name that indicates the kind of control—like, "lblFirstName" for a label that will display someone's first name, or "txtFirstName" for a text box that will allow an end user to type one in. In general, I do find prefixes for controls to come in handy; but to make them easier to read, I recommend adding an underscore after the prefix:

  • lbl_FirstName
  • txt_FirstName

It doesn't really matter what prefix you use, since the purpose is to keep the controls of the same type sorted together in a dropdown list.

Now, some controls—most labels, for example—will never be accessed programmatically. In that case, I see no reason to waste time on them; and leave them called Label1, Label2, Label3, etc.

The name of a control must be unique per formexcept in the case of a control array. This is where you have several controls of the same type, that share the same code. They then have the same name, as well; but their Index property will be different.

Index

The Index property is unique, because it is optional—it may have a value, or it may not. If it has a value, the value must be numeric and greater than or equal to zero.

If a control's Index property is supplied with a value, that control is a member of a control array—even if it is the only member. Also, while the values must be zero or more, they need not be contiguous. You can use any values that make sense for your application; when the shared code is invoked, the Index value will be passed to it so it will know which element of the array it is working on.

Top, Left, Height, Width

These four properties specify the location and size of a control. Top and Left are relative to the upper left-hand corner of the form or parent control on which the control rests. All four values are in twips, or whatever units are specified by the ScaleMode property.

Font

Since we're talking about printers, twips, points, and so on, we may as well look at the Font property. This is the first property we've examined that is, itself, an object. (Worry about what that means, later; for now, just remember that it is.) All objects can (and are likely to) have properties, just as forms and controls have properties. And so the Font property does. Among its more significant properties are

  • Name
  • Bold
  • Italic
  • Size

At design time, you select a font via the usual font selection dialog box. At run time, you can alter specific properties, thus:

MyForm.Font.Name = "Times New Roman" MyForm.Font.Size = 12 MyForm.Font.Bold = True

Or, if another component holds the font you want, you can copy the whole thing at once. Note the use of the Set statement:

Set MyForm.Font = MyForm.MyLabel.Font

Why did we use Set in the last statement, but not in the first set? Because Name, Size and Bold are not objects. Font is, and when you are assigning another object as the new value of an object property or variable, you have to use Set. Relax; we'll cover this in more detail later, including why. For now, I just wanted you to see it.

Caption / Text

These properties are generally the reason why a specific control exists. For example, a Label control: The only reason you bother to put one on a form is for its caption. The only reason you put a Text control on a form is for the text the user will enter. Caption and Text properties are basically the same thing; and I've never known one control to have both—it's one or the other, or neither.

These are text properties. We've already seen the Picture property, in the last chapter; you'll find that on controls that display images. There's also a Value property you find on controls that provide on/off or numerical values.

Enabled

There are times when a given control must not respond to clicks from the end user. For example: If the data is not correct or complete on a dialog box, the user should not be able to click the OK button. How to prevent that? Simply set the OK button's Enabled property to False.

You can disable a control at design time by setting the Enabled property to False in the Property Window. At run-time, simply make the assignment:

MyForm.cmd_OK.Enabled = False

Visible

Similar to the Enabled property, the Visible property can be set at design or runtime. If Visible is False, the control cannot be seen or used at run-time. It is real, it is there; its properties can be changed at run-time but the end user cannot see or interact with it.

Remember that the effect only occurs at run-time; the control or form looks perfectly normal at design-time.

Toolbox Contents

Pointer

This is the only thing in the Toolbox that does not place a control on a form—it is used to select a control that's already on a form (or elsewhere). It is also used to select the form itself, by clicking on the form at a location where there are no controls.

You can also select several controls on a form in either of two ways.

  1. You can "rubber-band" the controls by holding down the left mouse button while dragging diagonally, creating a dotted rectangle that includes the controls you want to select. When you let go of the button, the controls will be selected.

  2. You can click on the first control you want to select, then hold down the shift or control keys and click the rest.

Once a control is selected, you can place the mouse in the middle of the control and drag to reposition it; or you can drag one of the little rectangular handles that outline the control to resize it.

By the way, when a control or group of controls are selected, you can use the usual editing commands on them: You can delete them, or copy or cut them into the Clipboard; if there are controls in the Clipboard, you can paste them onto the currently active form.

Picture Box, Image

Default property: Picture

You might wonder why there are two controls for displaying pictures. Well, the Picture Control was the first one to come along. Originally, it was intended to display graphics. However, it was used for other purposes, as well; specifically, to contain or group other controls. Now, you might wonder why someone would want to put controls in a control. But picture this: suppose you have a map of the United States and you would like to label cities on it and allow the end user to select a specific city for some purpose. All you have to do is put a Picture control on the form, put a United States map graphic in the control, and then add Option buttons on top of the map where the cities are located. The Picture control is perfect for this.

However, with time, the Picture control developed so many extra capabilities (such as OLE drag-and-drop) that it used too many system resources for so simple a job as simply displaying a graphic. And so the Image control was introduced.

The Image control does nothing but display a picture. It is considered a low resource or "lightweight" control. In technical terms, it does not require an underlying Windows window, which saves a fair amount of memory.

So, use an Image control to display a graphic, and a Picture control to group other controls with or without a graphic.

There is another difference between an Image control and a Picture control. The Image control has the ability to stretch a bitmap larger or smaller than its natural size. To do this, set its Stretch property to True. The Picture control does not have that ability, but it is able to adjust itself to the size of the bitmap in it. That feature is controlled by the Picture control's Autosize property.

As stated in the chapter on colors and graphics, you can place a graphic into a Picture control or an Image control, either by using the Load Picture dialog (available through the Property Window), or by simply pasting a graphic from the clipboard when the control is selected.

Label

Default property: Caption

The Label control is used to display text to the end user. This text is usually specified at design time, but it can be altered by the program whenever necessary.

The Label control supports left, center, or right justification; it does not support left-right justification. However, it does support word wrap. To take advantage of this feature, simply make the Label control as tall as need be to display all the desired text.

On the other hand, many times a Label control is used to display only a small amount of text. If the Autofit property is set to True, the label control will grow shorter or longer, as needed, to hold the required text, and no more.

Text

Default Property: Text

Most dialog boxes require the end user to enter textual information … sometimes, a great deal of it. The Text control (commonly called "Text box") is the primary control used for this purpose. When a dialog box first appears, it can be empty, or it can already contain default text. The default text can be set at design time or at run time.

The Text box, like the Label control, can display its contents left, center, or right-justified,. The Multiline property will allow more than one line of text to be entered. To allow for this, make the Text box tall enough for several lines of text, and set its Multiline property to True.

The Password property, if set to True, causes the text to appear as a line of asterisks.

You can write code to enforce data entry requirements or data validation; but, in many cases, it is easier to use the Masked Edit control bundled with Visual Basic.

Frame

Default property: Caption

The Frame control is used specifically to group other controls. Now, above, we learned that the Picture control also groups controls. So, why are there two controls to do this?

Actually, there are any number of controls that can group other controls—you can write them yourself. But the answer is that the Picture control is primarily intended to group controls on top of a graphic. The Frame control groups controls in a familiar way, without displaying an underlying graphic.

Please note that Option buttons, which we will encounter next, must be grouped, in order to work properly. Consequently, we almost always put Option buttons in a frame control. However, we often use the Frame control simply to provide a visual distinction between one group of controls and another.

In other Windows programming environments, there is a control called a "Group box" that looks visually like the Frame control. However, the Group box is only a visual effect. Controls that lie within it are not a part of it. Controls placed on a Frame control become part of that control. If the Frame control is deleted, the controls in that are deleted, too. If the Frame control is moved, the controls in that retain their positions relative to the upper left hand corner of the Frame control.

Consequently, if you have one or more controls in the Clipboard, and you would like to paste them into a Frame control, you must first select the Frame control, then use the Edit..Paste command.

If you accidentally put a control inside a Frame control, the only way to move it onto the form is to select it, use the Edit..Cut command, deselect the Frame by clicking on the form, and using the Edit..Paste command.

Option Button

Default property: Value

Before Visual Basic was introduced, this control was called the "Radio button". These controls are always found in groups. They offer mutually exclusive choices, allowing the end user to select one choice.

If you only have one set of options on a form, the Option buttons can be placed directly on the form. However, if you have more than one set of choices—for example, the user can select one of several colors and also one of several sizes—each set of option buttons must be placed in a separate group control; and the most common type to use is the Frame control.

Please note that sometimes, one or more of the choices may not currently be appropriate. In that case, set the enabled property of the unavailable Option button to False. If you disable an Option button that was previously selected, don't forget to deselect that button by selecting the most likely of the remaining, enabled choices. If you do not, even though disabled, the button will continue to appear as if it were selected; and the end user will not be able to change it.

Checkbox

Default property: Value

The Checkbox control allows the end user to select individual choices which are not mutually exclusive. There may be one choice or several. A variation is the three-state form, which allows for true, false, and neither true nor false. For example, if a word were selected, and one of the letters in the word was italicized but the rest were not, a check box labeled "italics" would be in the third state, because all of the letters of the word are not italicized; on the other hand, neither are they all not.

As with Option buttons, you should disable any choices that are not currently appropriate. Usually you will uncheck disabled checkboxes, but that is up to you and the situation.

Command Button

Command buttons are usually used on modal dialog boxes. They are seldom used on a form that has a menu. They indicate an immediate action, rather than a modification of the current document.

On every form, there may be one default Command button. This is the button that is pressed automatically if the user hits the enter key. It is usually the OK button. However, if the gist of the dialog box is, "Do you want to delete your entire data base?" perhaps the OK button should not be the default.

Similarly, one Command button on the form can be the cancel button. This is the button that is pressed automatically if the user hits the Escape key on the keyboard. It is usually the button with the caption "Cancel" or "Close".

It is important that you use the cancel button correctly. The word "Cancel" means cancel! It should not appear on a dialog box whose action cannot be undone. It is fairly common for a dialog to appear with a Cancel button whose caption changes to "Close" after an unretractable action has occurred, so as not to imply to the end user that the action can be canceled.

As the end user is filling out the fields on a dialog box, he or she may inadvertently enter incorrect data or omit a required field. At such times, the OK button should be disabled. It is not considered user friendly to allow the user to make a mistake, and then chide them for it. If the user might not know why the OK button is disabled, you should provide a label near the bottom of the dialog box that will explain what the problem is. I call this label the "Hint bar".

Listbox

Default property: Text (read-only)

The Listbox control is used to display a list of items from which the user can select one or more. If the user can select only one—that is, the choices are mutually exclusive—it is called a single-selection Listbox. If the user can make several selections, it is called a multiple-selection Listbox. To create a multiple-selection Listbox, set its MultiSelect property to Extended.

You can populate the Listbox at design time or at run time. At design time, you use the property window to locate the List property. This property is accessed through a drop down list. To make several entries into the list, hold the shift key down while pressing the Enter key to go to the next item. At run time, you use the AddItem method:

MyList.AddItem "Fred"

The List property is also used to access items in the list at run time. It is an array property, which means you must provide the index of the specific item you want (the numbering starts at zero). The ListIndex property will tell you which item is currently selected. However, there is a shortcut to retrieve the currently selected item: the Text property (which in this control is a read-only property).

lbl_Selection.Caption = MyList.List(MyList.ListIndex)

or

lbl_Selection.Caption = MyList.Text

In a multiple selection Listbox, the ListIndex property indicates the last item to be clicked; that item may or may not be currently selected. In a multiple selection Listbox, one click on an item selects it; the next click deselects it.

If you need to know which items are currently selected, you can use the Selected array property. This property also works in a single selection Listbox; but in a single selection Listbox the ListIndex property is easier to use.

Both the ListIndex property for a single selection Listbox, and the Selected property for either type, can be used programmatically to select or deselect items. To deselect all items in a single selection Listbox, set the ListIndex property to -1.

ComboBox

Default property: Text

The ComboBox appears to be a combination of a Text box and a ListBox, and that's exactly what it is. As a ListBox, it is limited to single selections.

The ComboBox has a Style property with three possible values. The Simple Style displays the ListBox and the Text control just above it. The Dropdown Style only displays the Text box and a button with a down arrow. When the button is pressed, the ListBox appears. The third Style is the Dropdown List. It is like Dropdown, except that the Text box part cannot be typed into.

Why use a ComboBox when the ListBox and the Text box already exist? Well, the ComboBox does provide a couple of features that the separate controls do not. For one thing, when the end user clicks on an item in the list, that item is automatically copied into the Text box part. Also, the Dropdown and Dropdown List styles take up much less space on the dialog box, yet would be annoying to have to program over and over.

Like the ListBox, the ComboBox has a List array property and a ListIndex property. However, since multiple selection is not supported in the ComboBox, there is no Selected property. And the Text property can be written to as well as read.

Timer

The timer control is the first control that we've come to that the end user cannot see. It is what is called an invisible-at-runtime control. Such controls were invented before ActiveX. At that time, the only way to encapsulate behavior into an object, was to design it as an invisible-at-runtime control.

You place the timer control in any convenient place on form. In the Property Window, you set the interval property to the number of milliseconds you wish to pass between Timer ticks. When you double-click on the timer control, a code window will open to the Timer event. This is where you put the code that is to execute each time the timer ticks. To stop the timer from ticking, set its enabled property to false.

Control Arrays

You'll recall from our earlier discussion of variables that it is possible to have an array of variables; that is, one name describing a whole set of variables of the same type. Well, we can also have an array of controls.

Now, what does it mean to have to an array in an object-oriented environment? To figure this out let's first consider how arrays are used in the traditional, linear environment. Usually, when you have an array, once the individual values have been assigned or calculated, you run through the elements of the array in some kind of loop, making use of each of them in the same block of repetitive code.

From an object-oriented perspective, this is inside out. Since an individual object holds its own instructions within it, it makes sense that an array of objects would also contain their own instructions. Put another way, the objects in an array share the same code. And since all controls in Visual Basic are objects, that rule applies to them as well.

The usual way to create an array of controls is to first place a control of the desired type on a form. In the Property Window, set the Index property to zero or some other numeric value. Then, place another control of the same type on the form, giving it the same name. The Index property of the new control will automatically fill in with the next number.

Alternatively, after the first controls placed on the form and its properties are set, you can use the Edit..Copy command, followed by an Edit..Paste. You will be prompted as to whether you would like to create a control array. If you answer yes, the Index property of the first control will be set to 0, and the Index property of the new control will be set to 1. Additional pastes will not prompt you; Visual Basic understands that you know you are creating a control array.

Remember that, when its Index property has a value, a control is a member of a control array even as it is the only member. The combination of control Name and Index must be unique per form.

Dynamic Controls

Most of the time, control arrays created at design time are adequate. However, sometimes, you want to create additional elements of a control array at run time. For example, if you are designing a calendar and you would like to use a command button for each day of the month, you could create an array of twenty-eight command buttons at design time, and add however many additional buttons are needed, at run time.

In order to make use of dynamically created controls, you must have at least one element of the control array on the form at design time. It does not need to be visible, but it needs to be there. At run time, when you want to create the additional control, you use the Load statement to create additional elements. The newly-created control will be invisible, which gives you a chance to modify its other properties before you set its Visible property to True::

Load MyLabel(10) MyLabel(10).Top = 200 MyLabel(10).Left = 200 MyLabel(10).Visible = True

To remove a dynamically created control, you use the Unload statement. Please note that you cannot remove a control that was placed on the form at design time.

Unload MyLabel(10)

If you try to create an element whose Index already exists for that array, it will trigger a Visual Basic exception. Likewise, if you try to remove a control that does not exist, or that was placed there at design time, that will also trigger a Visual Basic exception. We have not yet discussed Visual Basic errors and exceptions, but they can be caught in code and dealt with.

When Your Form Is Complete

Once you have finished placing controls on your form, and they are positioned and sized the way you want, it is very annoying to click on them later and accidentally nudge them away from where they are supposed to be. You can prevent this happening by using the Format..Lock Controls command. This command is applied on a form by a form basis.

Even when controls are locked, you can reposition them by changing the Top, Left, Height, or Width properties in the Property Window. You can also reposition them when they are selected, by using the CTRL+arrow key combination.

TabIndex

Amazingly, not everyone likes to use a mouse. You might even be one of them. If you are not, however, be sure not to forget to test your forms and make sure they work with the keyboard in the way a keyboarder will expect.

Particularly, people expect that when they hit the tab key, the focus will move to the next control to the right; if no controls remain on that line, then the leftmost control on the line below that should get the focus.

This isn't a problem if you design your forms on paper first, and then create them on a computer. However, the computer makes an excellent design tool for forms; and when you're done, you can continue working with what you've created. That usually means, however, that your controls were not placed on the form in the right-to-left, top-to-bottom order a keyboard user would expect. That's why, after laying the controls down, you need to reset the TabIndex properties of those controls.

Unfortunately, there is no easy way to reset the TabIndex properties on a form in Visual Basic. There are some third party tools that do make it easy, for example the program VB Assist. However, we cannot discuss third party tools here. So, we have to look at the only method Visual Basic provides us for setting the TabIndex property.

To reset the TabIndex properties, click on the control that is closest to the upper left hand corner of the form. Go to the Property Window. You should be able to find the TabIndex property. (Only lightweight and invisible-at-runtime controls do not have a TabIndex property. )

For the uppermost left-hand control, set the TabIndex property to 0.

Now, click on the control that would come next in order. It doesn't matter if it is not an input control. It still has to be ordered. Set its TabIndex property to 1. Then continue with each subsequent control, giving each TabIndex property the next consecutive number.

Yes, it's a tedious operation; but it is part of creating any efficient, intuitive user interface for all your users.

The reason you must set the TabIndex property for Label and Picture controls as well as Text and Listbox controls, is that the hot key specified in the Captions are also part of the keyboard interface. When a user taps a hot key, the focus is supposed to go to the control immediately following it. If the labels do not have a TabIndex one less than the control that follows them, the user will receive very puzzling results.

When you're done, you have the following controls on your form:

TypeNameCaption
Labellbl_TitleApplication
Labellbl_VersionVersion
Labellbl_authorWritten by
Labellbl_CopyrightLegal Copyright
Commandcmd_OKOK
Imageimg_Icon

The cmd_OK command button should also have the Default and Cancel properties set to True, and the img_Icon control may have an icon placed into its Picture property (to make it easier to see) but it doesn't need to, since we'll be assigning one programmatically in the next chapter.