This section discusses a simple data-entry application that demonstrates many of the topics discussed here, as well as a few techniques for designing easy-to-use forms. Figure 5.4 shows a data-entry form for maintaining contact information, and I’m sure you will add your own fields to make this application more useful.
You can navigate through the contacts by clicking the buttons with the arrows, as well as add new contacts or delete existing ones by clicking the appropriate buttons. When you’re entering a new contact, the buttons shown in Figure 5.4 are replaced by the usual OK and Cancel buttons. The action of adding a new contact, or editing an existing one, must end by clicking one of these two buttons. After committing a new contact or canceling the action, the usual navigation buttons appear again.
Place the controls you see in Figure 5.4 on the form and align them appropriately. After the controls are on the form, the next step is to set their tab order. You must specify a TabOrder using the TabIndex property even for controls that never receive focus, such as the Label controls. In addition to the tab order of the controls, we’ll also use shortcut keys to give the user quick access to the most common fields. The shortcut keys are displayed as underlined characters on the corresponding labels.
Notice that the Label controls have shortcut keys, even though they don’t receive the focus. When you press the shortcut key of a Label, the focus is moved to the following control in the tab order, which is the TextBox control next to it.
Figure 5.4 – An example fro using the Form to maintain contact details
If you run the application now, you’ll see that the focus moves from one TextBox to the next and that the labels are skipped. After the last TextBox control, the focus is moved to the buttons and then back to the first TextBox control. To add a shortcut key for the most common fields, determine which fields will have shortcut keys and then which keys will be used for that purpose. Being the Internet buffs that we all are, let’s assign shortcut keys to the Company, EMail, and URL fields. Locate each label’s Text property in the Properties window and insert the & symbol in front of the character you want to act as a shortcut for each Label. The Text properties of the three controls should be &Company, &EMail, and &URL.
Shortcut keys are activated at runtime by pressing the shortcut character while holding down the Alt key. The shortcut key will move the focus to the corresponding Label control, but because labels can’t receive the focus, the focus is moved immediately to the next control in the tab order, which is the adjacent TextBox control.
The contacts are stored in an ArrayList object, which is similar to an array but a little more convenient. We’ll discuss ArrayLists in Chapter, “Storing Data in Collections in VB.NET”; for now, you can ignore the parts of the application that manipulate the contacts and focus on the design issues. Start by loading the sample data included with the application. Open the File menu and choose Load. You won’t be prompted for a filename; the application always opens the same file in its root folder. After reading about the OpenFileDialog and SaveFileDialog controls, you can modify the code so that it prompts the user about the file to read from or write to. Then enter a new contact by clicking the Add button or edit an existing contact by clicking the Edit button. Both actions must end with the OK or Cancel button. In other words, we require users to explicitly end the operation, and we won’t allow them to switch to another contact while adding or editing one.
The code behind the various buttons is straightforward. The Add button hides all the navigational buttons at the bottom of the form and clears the TextBoxes. The OK button saves the new contact to an ArrayList structure and redisplays the navigational buttons. The Cancel button ignores the data entered by the user and likewise displays the navigational buttons. In all cases, when the user switches back to the view mode, the TextBoxes are also locked, by setting their ReadOnly properties to True.
Although the Tab key is the Windows method of moving to the next control on the form, most users will find it more convenient to use the Enter key. The Enter key is the most important one on the keyboard, and applications should handle it intelligently. When the user presses Enter in a single-line TextBox, for example, the obvious action is to move the focus to the following control. I included a few statements in the KeyDown event handlers of the TextBox controls to move the focus to the following one:
Code language: PHP (php)
Private Sub txtAddress1_KeyDown(...) Handles txtAddress1.KeyDown If e.KeyData = Keys.Enter Then e.SuppressKeyPress = True txtAddress2.Focus() End If End Sub
If you use the KeyUp event handler instead, the result won’t be any different, but an annoying beeping sound will be emitted with each keystroke. The beep occurs when the button is depressed, so we must intercept the Enter key as soon as it happens, and not after the control receives the notification for the KeyDown event. The control will still catch the KeyUp event and it will beep because it’s a single-line TextBox control (an audible warning that the specific key shouldn’t be used in a single-line TextBox control). To avoid the beep sound, the code “kills” the keystroke by setting the SuppressKeystroke property to True.
Processing Keys from within Your Code
The code shown in the preceding KeyDown event handler will work, but you must repeat it for every TextBox control on the form. A more convenient approach is to capture the Enter keystroke in the form’s KeyDown event handler and process it for all TextBox controls. First, we must figure out whether the control with the focus is a TextBox control. The property Me.ActiveControl returns a reference to the control with the focus. To find out the type of the active control and compare it to the TextBox control’s type, use the following If statement:
If Me.ActiveControl.GetType Is GetType(TextBox) Then ' process the Enter key End If
An interesting method of the Form object is the ProcessTabKey method, which imitates the Tab keystroke. Calling the ProcessTabKey method is equivalent to pressing the Tab key from within your code. The method accepts a True/False value as an argument, which indicates whether it will move the focus to the next control in the tab order (if True), or to the previous control in the tab order. Once you can figure out the active control’s type and you have a method of simulating the Tab keystroke from within your code, you don’t have to code every TextBox control’s KeyDown event.
Start by setting the form’s KeyPreview property to True and then insert the following statements in the form’s KeyDown event handler:
If e.KeyCode = Keys.Enter Then If Me.ActiveControl.GetType Is GetType(TextBox) Then e.SuppressKeyPress = True If e.Shift Then Me.ProcessTabKey(False) Else Me.ProcessTabKey(True) End If End If End If
The last topic demonstrated in this example is how to capture certain keystrokes, regardless of the control that has the focus. We’ll use the F10 keystroke to display the total number of contacts entered so far. Assuming that you have already set the form’s KeyPreview property to True, enter the following code in the form’s KeyDown event:
Code language: PHP (php)
If e.Keycode = keys.F10 Then MsgBox("There are " & Contacts.Count.ToString & _ " contacts in the database") e.Handled = True End If
Listing 5.1 shows the complete handler for the form’s KeyDown event, which also allows you to move to the next or previous contact by using the Alt+Plus or Alt+Minus keys, respectively.
Listing 5.1: Handling Keystrokes in the Form’s KeyDown Event Handler
Code language: PHP (php)
Public Sub Form1_KeyDown(ByVal sender As Object, _ ByVal e As System.WinForms.KeyEventArgs) _ Handles Form1.KeyUp If e.Keycode = Keys.F10 Then MsgBox("There are " & Contacts.Count.ToString & _ " contacts in the database") e.Handled = True End If If e.KeyCode = Keys.Subtract And e.Modifiers = Keys.Alt Then bttnPrevious.PerformClick End If If e.KeyCode = Keys.Add And e.Modifiers = Keys.Alt Then bttnNext.PerformClick End If End Sub
The KeyCode property of the e argument returns the code of the key that was pressed. All key codes are members of the Keys enumeration, so you need not memorize them. The name of the key with the plus symbol is Keys.Add. The Modifiers property of the same argument returns the modifier key(s) that were held down while the key was pressed. Also, all possible values of the Modifiers property are members of the Keys enumeration and will appear as soon as you type the equal sign.