System.IO

Directives

15.1 Ensure thorough keyboard navigation and interaction.

Depending on the type of program you're creating, it might not be possible to provide keyboard accessibility for all functions that are accessible with the mouse. However, a user should be able to navigate your program without a mouse. This means that your menus should support shortcut keys and access keys. For more information on these methods of keyboard access, refer to Chapter 14, "Interface Design."

In addition to making your menus keyboard-friendly, you must also make it possible for users to use the keyboard to easily navigate the controls of every form and dialog box. Furthermore, it should be possible for a user to accept or reject changes in a dialog box via the keyboard. Enabling full keyboard access can be quite tedious, and chances are you won't account for all situations prior to releasing your product, but you can rest assured that your customers will be more than enthusiastic about letting you know the situations you forgot!

Practical Applications
15.1.1 Thoughtfully set the tab order of all of your forms.

Even if a user loves using the mouse, it's inevitable that sooner or later he is going to want to progress forward or backward through the controls on a form by using the Tab key. The Tab key is the Microsoft Windows standard key for moving the focus forward (and backward using Shift+Tab) through the controls on a form. Every one of your forms should allow complete forward and backward navigation by way of Tab and Shift+Tab. There is simply no good excuse for not providing this.

The order in which the Tab key progresses through the controls on a form is known as the tab order. The tab order is determined by the TabIndex and TabStop properties of the controls on the form. All controls that can receive the focus have a TabIndex property, but not all controls have a TabStop property. Controls that have a TabIndex property but not a TabStop property are treated as though they have a TabStop property always set to True. When a user presses the Tab key, the focus is moved from the control that currently has the focus to the control that has the next highest TabIndex property value. If the control with the next highest TabIndex value isn't visible or has its TabStop property set to False, the search continues until a visible control is found that has its TabStop property set to True. If the tab order isn't set correctly for a form, pressing Tab will cause the focus to jump from control to control in no apparent order. This really isn't a way to impress users.

As you add controls to a form, Visual Basic assigns values incrementally to the TabIndex properties. For instance, the first control placed on a form has a TabIndex of 0, the next control a TabIndex of 1, and so on. This is rarely the order you want by the time you finish designing a form. As you develop the form, you usually add new controls, delete existing controls, and shuffle controls around so as to create that killer interface. As you perform these actions, the system-assigned TabIndex values become arbitrary. Thus, verifying the tab order of a form should be one of the last tasks you perform before a form is put into production (that is, compiled into a usable component). This isn't to say you shouldn't adjust your tab order as you work on a form, because you really should. However, regardless of how many times you've tweaked a form's tab order, when you're done working with a form and are ready to move onto another, verify the tab order.

To define a tab order in previous additions of Visual Basic, you had to assign the first control to receive the focus a TabIndex of 0, the next control a TabIndex of 1, and so on. This was a tedious process, to say the least. In the previous edition of this book, I wrote, "Setting the tab order of the controls on a form should be a simple point-and-click process; after all, you have to do this with every form you create." I now wish I had said, "I want a million dollars," because my wish was granted.

Setting the tab order for a form is now a relatively simple process. First display the form whose tab order you want to edit in the designer, choose Tab Order from the View menu, and then click the controls on the form in the order in which you want the tab order defined. Note that it might be easier to manually assign tab index values when you're changing only one or two values. When you use the visual interface, you have to assign a tab index value for every control on the form. To take the form out of tab-order edit mode, choose Tab Order from the View menu once more.

Tip

When using a container control, such as the frame control, assign the container control a TabIndex value one less than that of the first control to receive the focus in the container.


 

Incorrect:
Figure 15-1. An incorrect tab order confuses and slows down the user. Often, the user has to reach for the mouse to get where he or she wants to go.

graphics/f15ln01.jpg

Correct:
Figure 15-2. Notice that the tab order is set the way the user would expect it to be.

graphics/f15ln02.jpg

15.1.2 Create an accept button and a cancel button in dialog boxes when feasible.

Most applications display modal dialog boxes. These dialog boxes are used to gather information from the user and are then discarded. Generally, such dialog boxes include at least two command buttons: OK and Cancel. Clicking the OK button commits the user's settings and closes the dialog box; clicking the Cancel button closes the dialog box and discards the user's settings. You might have noticed that in most programs pressing the Esc key (Escape) has the same effect as clicking the Cancel button. You can (and should) duplicate this behavior in your applications.

To assign the Esc key to a button, set the form's CancelButton property to the name of the button. Once you do this, pressing Esc while any control on the form has the focus triggers that button's Click event. To assign the Enter key to a button, you set the form's AcceptButton property to the name of the button. As with the cancel button, when you designate a button as the accept button, the button's Click event can be triggered at any time all the user has to do is press Enter.

Although the CancelButton property of every dialog box should be set to a valid button, you'll have to determine whether to assign an accept button based on the nature of the dialog box. The main issue to consider when assigning an accept button is whether the dialog box includes any multiline text boxes. In a multiline text box, pressing Enter causes a new line of text to be created (such as when creating a new paragraph). Unfortunately, Visual Basic doesn't recognize this special situation and interprets the user pressing Enter as a clicking of the accept button. This is extremely aggravating to a user. If you're including a multiline text box in a dialog box, you're better off not designating a button as the accept button for the form.

Note

This practical application doesn't include correct/incorrect examples.


 

15.1.3 Assign access keys to commonly used buttons.

Almost everyone is familiar with menu access keys. When a letter in the name of a top-level menu is underlined (such as the F in File), pressing the Alt key in conjunction with the underlined letter opens the menu. What many developers are unaware of, however, is that you can assign access keys to buttons.

How to go about assigning access keys to buttons isn't obvious because of the lack of a dedicated access key property. You designate an access key by prefixing a character in the button's Text property with an ampersand (&). When Visual Basic displays a button's Text property, it looks for an ampersand. If one is found, the ampersand isn't displayed. Instead, the character immediately following the ampersand is shown with an underscore, and that character becomes the access key for the button. Pressing Alt in conjunction with a button's access key triggers the button's Click event just as though the user clicked the button with a mouse.

Tip

To display an ampersand within the text of a button, use two ampersands. For instance, to display the caption Print & Exit, set the Text property to Print && Exit.


 

Access keys are great because they give keyboard users an efficient means to trigger buttons without clicking them you should assign access keys to all commonly used buttons on your forms. When assigning access keys, be aware of the following points:

  • Don't assign an access key to a button that is set as the form's AcceptButton or CancelButton. When a button is assigned to one of these properties, it can be "clicked" by pressing Enter or Esc, respectively; there is simply no need to assign access keys in these situations.

  • Don't assign access keys that conflict with the access keys of menu items. For instance, if a form has a File menu, the F in File should be designated as the access key for the menu to be consistent with other programs. Don't assign the letter F as a button access key on a form that already has F as the access key of a menu; the menu always wins. Refer to Chapter 14 for more information on menus.

Incorrect:
Figure 15-3. Without access keys, a user is forced to tab to the desired button or reach for the mouse.

graphics/f15ln03.jpg

Correct:
Figure 15-4. Notice the use of logical access keys. The Close button doesn't have an access key because it is the accept button of the form.

graphics/f15ln04.jpg

Tip

You can assign access keys to label controls in the same way you do for buttons. When the user presses the Alt in conjunction with a label's access key, the focus moves to the control that has the next highest TabIndex value above the label control. That is why the label controls were taken into consideration in the tab order shown in Figure 15-2.


 

15.1.4 Set the MaxLength property of controls bound to data fields.

When creating data forms, make the forms as easy to use as possible. This includes making functions and menus accessible via the keyboard, assigning access keys to buttons, and creating accept and cancel buttons when appropriate. Another helpful practice you can follow with data entry forms actually involves stopping the user from typing too much at the keyboard.

Most fields in a database table have a maximum number of characters that they can store. Attempting to store more characters in a field than allowed results in the error shown in Figure 15-5. When a user encounters this error, she's forced to stop working, determine which field on the screen is the culprit, and reduce the number of characters in her entry. Often, she'll shorten the entry and then try to save it again, only to find that the entry is still too long. This process is repeated until the user finally enters a string small enough to fit in the data field. But there's no good reason for making the user go through this.

Figure 15-5. This is most certainly not a friendly way to treat a user.

graphics/f15ln05.jpg

Text box controls, as well as a few others such as the combo box, include a MaxLength property. When a text box's MaxLength property is set to 0 (the default), the only constraint on the number of characters the text box can contain is the amount of memory on the user's computer. Any value greater than 0 for MaxLength causes the text box to limit the number of characters it accepts. If the user attempts to enter more characters than the amount allowed by MaxLength, Visual Basic stops the characters from being entered in the text box and alerts the user with a beep. This situation is definitely preferable to being allowed to enter anything you like and then being shown an error when you attempt to save a record.

If you bind your text boxes to a data source, you might be under the assumption that Visual Basic automatically sets the MaxLength property when the control is bound. This is a great idea, but it doesn't actually work that way. Binding a text box control has no effect on the control's MaxLength property; the text box continues to have the same value in its MaxLength property as it had before it was bound to the data source. Therefore, to prevent the user from entering more data in a text box than can be saved in the underlying record source, you have to set the MaxLength property manually for each text box.

You can take two approaches to setting the MaxLength property: set the MaxLength property of a text box at design time, or retrieve the maximum number of characters allowed by a column in the data source and set the MaxLength property of the corresponding text box at run time. The latter method gives you more flexibility in that if you change a column size you don't have to worry about making the change manually to all text boxes that access the field. Setting the properties at run time is a bit slower than having the properties set at design time, but the performance difference is probably negligible. Still, it's a consideration. Choose whichever method you think is best just be sure to set the MaxLength properties.

15.2 Provide consistent and intuitive mouse interaction.

For most users, the mouse is the primary device for interacting with the computer. Although keyboard users are often neglected, sometimes developers neglect mouse users as well.

Practical Applications
15.2.1 Provide context menus whenever possible.

A context menu (also called a pop-up menu or shortcut menu) is a menu that appears when the user right-clicks an object that supports context menus. (See Figure 15-6.) This section's focus is not on the organization of context menus but rather on the proper ways to invoke context menus. Windows 95 started the era of context menus, and now most users can't live without them.

Figure 15-6. Context menus let users quickly access context-sensitive functions by right-clicking an object.

graphics/f15ln06.jpg

Right-clicking an object is an easy way to explore an application. For instance, if you're not sure what you can do with a message item in Microsoft Outlook, you need only right-click an item to see a context menu of commands related to the item. You should create context menus for as many items as possible in your program. Windows displays standard context menus for certain controls such as the text box, so don't go crazy and think you have to add a context menu to every control on a form. Use your head, and try to put yourself in the user's place. In general, lists of items, whether in a list box, a tree view, or a list view control, are good candidates for context menus.

When you display a context menu for an item, the context menu should contain items specifically related to the item that was right-clicked. For instance, when displaying a context menu for a person's name in a contact list, it would be perfectly logical to show items such as Add New, Delete, Send Fax, and Dial Phone. However, items that aren't directly related to the object being clicked such as Mark As Read or Save As in this example shouldn't appear on the menu. Remember, these are context menus. Just as pressing F1 displays context-sensitive help, right-clicking an object should display a context-sensitive menu.

You used to have to write code to create a context menu, but in Visual Basic .NET all you have to do is set a property: a control's ContextMenu property. You can assign only menus created using the ContextMenu control, not the MainMenu control. If you need to execute code before the menu is displayed, such as testing a condition and disabling menu items accordingly, use the MouseDown event of the control because this event fires before the menu is displayed. If you use the MouseUp event, changes made to the menu won't be displayed to the user.

Incorrect:
Private Sub lstContacts_MouseUp(ByVal sender As Object, _             ByVal As System.Windows.Forms.MouseEventArgs) _             Handles lstContacts.MouseUp    ' If no contact is selected, disable the Edit and Delete     ' buttons on the context menu.     If lstContacts.SelectedItem Is Nothing Then       mnuDeleteContact.Enabled = False       mnuEditContact.Enabled = False    End If End Sub 
Correct:
Private Sub lstContacts_MouseDown(ByVal sender As Object, _             ByVal As System.Windows.Forms.MouseEventArgs) _             Handles lstContacts.MouseUp    ' If no contact is selected, disable the Edit and Delete     ' buttons on the context menu.     If lstContacts.SelectedItem Is Nothing Then       mnuDeleteContact.Enabled = False       mnuEditContact.Enabled = False    End If End Sub  
15.2.2 Use the Cursor property of a form to give the user feedback.

Most of the time, the mouse behaves like a one-way street. The user manipulates it to provide information to a program, and the program takes the information generated by the mouse and performs some sort of action. However, the mouse is also capable of sending information to the user by way of its cursor.

You change the cursor of the mouse pointer by changing the Cursor property of an object. In Design view, you get a drop-down list for the cursor property as shown in Figure 15-7.

Figure 15-7. Visual Basic displays the cursors in a list, making it easy to select the proper cursor.

graphics/f15ln07.jpg

Most of the time, you'll be changing the Cursor property at design time. However, you can change the Cursor property at run time. For example, to change the mouse pointer of a form to an hourglass, use this statement:

' Set the cursor of the current form to an hourglass. Me.Cursor = Cursors.WaitCursor 

Table 15-1 lists the members of the Cursors enumeration you can use for the Cursor property. For some reason, you won't get a drop down list of these values when writing code until you type the word Cursors and a period.

 

Table 15-1. Members of the Cursors Enumeration 

Member

Cursor

Description

Default

graphics/g15ln01.jpg

Shape determined by the object (default)

Arrow

graphics/g15ln02.jpg

Used for most pointing

AppStarting

graphics/g15ln03.jpg

Indicates that an application is starting

Cross

graphics/g15ln04.jpg

Often used for precision pointing

IBeam

graphics/g15ln05.jpg

Often used for positioning within text

SizeAll

graphics/g15ln06.jpg

Often indicates that an item can be moved in any direction

SizeNESW

graphics/g15ln07.jpg

Often indicates that the upper right or lower left corner of an item can be moved in any direction

SizeNS

graphics/g15ln08.jpg

Often indicates that an item can be moved vertically

SizeNWSE

graphics/g15ln09.jpg

Often indicates that the upper left or lower right corner of an item can be moved in any direction

SizeWE

graphics/g15ln10.jpg

Often indicates that an item can be moved horizontally

UpArrow

graphics/g15ln11.jpg

Often used as an insertion point

WaitCursor

graphics/g15ln12.jpg

Indicates that the system is busy

Help

graphics/g15ln13.jpg

Often indicates that clicking on an item displays context-sensitive help

Hsplit

graphics/g15ln14.jpg

Indicates that a horizontal divider (splitter bar) can be moved vertically

Vsplit

graphics/g15ln15.jpg

Indicates that a vertical divider (splitter bar) can be moved horizontally

No

graphics/g15ln16.jpg

Indicates that the current operation isn't permitted for the object

NoMove2D

graphics/g15ln17.jpg

Indicates that the current object can be panned both horizontally and vertically but that the mouse isn't currently moving

NoMoveHoriz

graphics/g15ln18.jpg

Indicates that the current object can be panned horizontally but that the mouse isn't currently moving

NoMoveVert

graphics/g15ln19.jpg

Indicates that the current object can be panned vertically but that the mouse isn't currently moving

PanEast

graphics/g15ln20.jpg

Indicates that the current object can be panned to the right

PanNE

graphics/g15ln21.jpg

Indicates that the current object can be panned to the right and up

PanNorth

graphics/g15ln22.jpg

Indicates that the current object can be panned up

PanNW

graphics/g15ln23.jpg

Indicates that the current object can be panned up and to the left

PanSE

graphics/g15ln24.jpg

Indicates that the current object can be panned down and to the right

PanSouth

graphics/g15ln25.jpg

Indicates that the current object can be panned down

PanSW

graphics/g15ln26.jpg

Indicates that the current object can be panned down and to the left

PanWest

graphics/g15ln27.jpg

Indicates that the current object can be panned to the left

Hand

graphics/g15ln28.jpg

Often used when pointing to a hyperlink

 

Although all these icons have useful purposes, the three used most often are Default, AppStarting, and WaitCursor. Users get extremely frustrated and perplexed when the program looks as though it will accept input but it doesn't. This often results in a three-fingered salute (Ctrl+Alt+Delete), which just leads to real complications. Most of the time, you can avoid this simply by displaying an indicator the hourglass to show that the program is busy. When your program is busy processing and can't accept input from the user, display the hourglass by setting the form's Cursor property to Cursors.WaitCursor. When the process is finished and control is returned to the user, set the form's Cursor property back to Cursors.Default.

When a procedure that has changed the mouse pointer finishes what it's doing, it must always set the mouse pointer back to the default. When the mouse pointer's icon is not appropriate for a given situation, it confuses and frustrates users. For instance, leaving the pointer as an hourglass when the system isn't busy leads the user to thinking she can't interact with the program even though she can. Imagine waiting for a program to return control to you when all the while the program has been waiting for you to do something.

Incorrect:
Private Sub cmdFillYears_Click(ByVal sender As System.Object, _                                ByVal As System.EventArgs) _                                Handles cmdFillYears.Click    ' Purpose   :  Fill a list box with the years from 1900 to 2050.     Dim intYear As Integer    Const c_YearMin = 1900    Const c_YearMax = 2050    Try        ' Set the pointer to an hourglass so that the user knows       ' we're busy.        Me.Cursor = Cursors.WaitCursor       ' Populate the list box with the range of years.        For intYear = c_YearMin To c_YearMax          lstYears.Items.Add(intYear.ToString)       Next intYear    Catch ex As Exception       ' Do something with the exception.     End Try End Sub 
Correct:
Private Sub cmdFillYears_Click(ByVal sender As System.Object, _                                ByVal As System.EventArgs) _                                Handles cmdFillYears.Click    ' Purpose   :  Fill a list box with the years from 1900 to 2050.     Dim intYear As Integer    Const c_YearMin = 1900    Const c_YearMax = 2050    Try        ' Set the pointer to an hourglass so that the user knows       ' we're busy.        Me.Cursor = Cursors.WaitCursor       ' Populate the list box with the range of years.        For intYear = c_YearMin To c_YearMax          lstYears.Items.Add(intYear.ToString)       Next intYear    Catch ex As Exception       ' Do something with the exception.     Finally        ' Restore the mouse pointer.        Me.Cursor = Cursors.Default    End Try End Sub 
15.2.3 When displaying context menus that perform actions on selected list items, always select the item that is clicked before displaying the context menu.

Although the right mouse button is used to display context menus, the list box control doesn't recognize the right click as a way to select an item. When you display a context menu for a list box control, you must write code to ensure that the item under the mouse when the right-click occurred is the item that is selected when the menu appears. This is best done with the MouseDown event, because it fires before the context menu appears.

Selecting an item in a list box with the right mouse button used to require some tricky code. Essentially, you had to calculate the row that was clicked by considering the y-coordinate of the mouse and the height of a capital letter of a list item. This functionality is now available via a single method call: IndexFromPoint. For example, to ensure that the item under the cursor was selected before displaying a context menu, you could use a procedure such as this:

Private Sub lstYears_MouseDown(ByVal sender As Object, _             ByVal As System.Windows.Forms.MouseEventArgs) _             Handles lstYears.MouseDown    If e.Button = MouseButtons.Right Then        ' Make sure the item under the cursor is selected before       ' the context menu is displayed.       lstYears.SelectedIndex = lstYears.IndexFromPoint(e.X, e.Y)    End If End Sub 

If the list contains no items, the SelectedIndex method is smart enough to know this and won't throw an exception. Also, if no item is located at the specified coordinates, the SelectedIndex method doesn't throw an exception but does deselect any selected items.

15.3 Create thoughtful and functional message boxes.

The most common way to notify a user about something is to call MessageBox.Show. The MessageBox.Show method is extremely flexible with it you can ask a question or make a statement. You can also dictate the type of icon shown (if any) as well as the buttons available to the user. Because creating message boxes is such a common and easy task, the process is often taken for granted and it's easy to create bad message boxes. In this section, I'll discuss the techniques you can use to create better messages.

When writing messages, use a formal tone. Don't use large words, and avoid using contractions. The text should be immediately understandable and not overly fancy. Remember: a message box is not a place to show off your literary prowess; it's a place to convey a simple and clear message to a user. When a message box must ask a question, create an accurate and succinct question so that the user can make an educated decision.

Sometimes you simply can't avoid displaying a long message, but you should strive to limit messages to only two or three lines. You want a user to feel comfortable and in control at all times. Lengthy messages spanning multiple lines not only are harder for a reader to digest but also can intimidate the user, which you absolutely don't want to do.

It's a fact that users make mistakes, and sometimes they really screw up. However, it's your job to make them feel as though they haven't done anything wrong even when they do. If a message comes across as personal, a user will take it personally.

Practical Applications
15.3.1 Create the proper type of message box for a given situation.

There are four types of messages: informational, warning, critical, and question (or query). Information message boxes should be displayed with the information icon (as shown in Figure 15-8), warning messages with the warning icon (Figure 15-9), and critical messages with the Stop icon (a red circle with an X in it) as shown in Figure 15-10. For messages that ask the user a question, display the question-mark icon shown in Figure 15-11. To display an icon in a message box, you supply the appropriate enumerated member in the MessageBox.Show method's icon parameter. The values have changed somewhat from those used with the MsgBox function in previous editions of Visual Basic. The odd part is, there are now duplicate values for the same icons, and the warning icon is now the same as the exclamation icon. To display the red circle with an X in it, use the Stop icon. (The Hand icon is the same as Stop, and I have absolutely no idea why it's called Hand.) Table 15-2 lists the icons and their descriptions. (Note that I do not list the duplicates in this table.)

Figure 15-8. Information message boxes are simple, noncritical notifi cations. They should display the information icon.

graphics/f15ln08.jpg

Figure 15-9. Warning message boxes are used to notify the user of something that's fairly important. When the user sees the exclamation icon, the user knows to take note.

graphics/f15ln09.jpg

Figure 15-10. Critical message boxes are used to notify the user of something that absolutely must be attended to. Don't overuse the critical message icon on less-than-important messages you'll be crying wolf, and the user won't pay attention when it's necessary.

graphics/f15ln10.jpg

Figure 15-11. The question icon should be reserved for messages that ask the user a question.

graphics/f15ln11.jpg

 

Table 15-2. Members of the MessageBoxIcon Enumeration

Member

Description

Information

Displays a lowercase "i" within a white balloon

Warning

Displays an exclamation point within a yellow triangle

Stop

Displays white X within a red circle

Question

Displays question mark within a white balloon

 

For the caption of a message box (the text that appears in the title bar), I recommend that you use the name of your program. You might consider creating a global constant for this purpose, as you're likely to have a lot of message boxes in a program. When you use the application name for the title bar text of your message boxes, the message boxes will have a more consistent feel and users will know which application is displaying the messages.

Incorrect:
Figure 15-12. This message box does not have an icon, and therefore it does not provide a visual clue as to its importance.

graphics/f15ln12.jpg

Correct:
Figure 15-13. This notification needs to be taken seriously by the user, and the warning icon should do the trick.

graphics/f15ln13.jpg

15.3.2 Provide buttons that make sense.

Designating the proper icon as described in Practical Application 15.3.1 is just the first step in building a good message box. The message box is capable of displaying many different buttons, and it's up to you to choose which button or buttons will appear in any given message box. Table 15-3 lists the members of the MessageBoxButtons enumeration and their descriptions, which are available for specifying buttons.

 

Table 15-3. Members of the MessageBoxButtons Enumeration

Member

Description

OK

Displays the OK button only

OKCancel

Displays the OK and Cancel buttons

AbortRetryIgnore

Displays the Abort, Retry, and Ignore buttons

YesNoCancel

Displays the Yes, No, and Cancel buttons

YesNo

Displays the Yes and No buttons

RetryCancel

Displays the Retry and Cancel buttons

 

To designate a specific button as the default button (that is, the button that appears with a dark rectangle around it and that is "clicked" when the user presses Enter or the spacebar), specify one of the enumeration members listed in Table 15-4 for the defaultButton parameter. Note that the buttons appear in the order in which they are listed in the MessageBoxButtons enumeration. So, if you specified an OK and a Cancel button by using MessageBoxButtons.OKCancel and you wanted to make the Cancel button the default button see Figure 15-14 you'd specify MessageBoxDefaultButton.Button2.

Figure 15-14. Notice that the Cancel button is the default button in this message box.

graphics/f15ln14.jpg

 

Table 15-4. Members of the MessageBoxDefaultButton Enumeration

Member

Description

Button1

The first button in the message box is the default button.

Button2

The second button in the message box is the default button.

Button3

The third button in the message box is the default button.

 

Make the default button of every message box a deliberate choice. For example, if you're displaying a message box with a Yes button and a No button and you're asking the user whether he wants to format his hard drive, set No as the default button.

When using MessageBox.Show to solicit a decision from the user, the function returns a member of DialogResult. (See Table 15-5 for a list of the members of DialogResult.) Note that these values correspond to the MessageBoxButtons enumeration.

For example, you could use code similar to the following for displaying the message box shown in Figure 15-14:

' Give the user a chance to back out of formatting their hard drive. If MessageBox.Show("You are about to format the C: drive.", _       "My Application", MessageBoxButtons.OKCancel, _       MessageBoxIcon.Warning, _       MessageBoxDefaultButton.Button2) = DialogResult.OK Then     ' Code to format the hard drive goes here. End If 

 

Table 15-5. Members of the DialogResult Enumeration

Member

Abort

Cancel

Ignore

No

None

OK

Retry

Yes

 

The icon, buttons, and default button must all be chosen to work in unison. If, for example, you aren't asking a yes/no question, don't use a question-mark icon. If you're displaying a critical message prior to performing some task that the user won't be able to undo, provide a Cancel button. Every message box is different, and I can't give you a hard-and-fast rule for every situation. Consider the ideas presented here, and use common sense. Consider what you would want and expect from each message box if you were a user.

Incorrect:
Figure 15-15. This message box has a few problems. First, if you're going to update a user's files, provide a Cancel button so that the user can stop and back up the files. If you're not giving an option, there's no need for the message box. Second, you don't press a button, you click it. And, finally, there's no need to tell the user to click anything; that much is obvious.

graphics/f15ln15.jpg

Correct:
Figure 15-16. This message box is simple and to the point. Furthermore, the user is given an opportunity to prevent an irreversible process from starting.

graphics/f15ln16.jpg

15.3.3 Proofread all messages.

This idea is so fundamental that it seems silly to have to mention it. Yet time and time again messages with poor spelling and bad grammar are displayed. If you're not particularly adept at writing, find someone in your organization who is and have that person proofread your messages. Also, if you're localizing a program into a language that's not your native language, find someone who speaks the language fluently to check your messages.

Think of message box text as though it were an important document on company letterhead, signed by your CEO, and sent to all your customers. If your messages are terse, they will reflect negatively on your company. If you have a particular developer who's a bit short on people skills, write that developer's message box statements or at least proofread them before they're released.

Incorrect:
Figure 15-17. Even forgetting the spelling errors, this is rather unpleasant. Can't put what where? Why the exclamation icon?

graphics/f15ln17.jpg

Correct:
Figure 15-18. Notice the friendlier tone and the information icon. This message box is helpful, as opposed to obnoxious.

graphics/f15ln18.jpg

15.3.4 Avoid using technical jargon in a message box.

Have you ever tried to explain a programming-related issue to a person who has never programmed before? If so, you're probably familiar with the glazed look that appears on the person's face as a little yellow propeller attached to a red beanie is pictured atop your head. When you live and breathe a technology, it's easy to forget that not everyone else does. Also, just because a person uses software doesn't mean he or she is a technical person.

Unless your program is written for a very specific vertical market, avoid using technical jargon in your messages. Remember that messages should be clear and concise. When you use technical jargon, you risk confusing the reader. If you find yourself creating a message with technical jargon, consider rewriting the message in a nontechnical way.

Users are continuously interacting with your program. Make it easy for them to navigate your program and execute the functions they need to get their jobs done. When your program must stop the user's work flow to display a notification or get an answer to a question, make sure that it does so in the clearest and most concise manner possible. The smoother the interaction, the more productive (and grateful) the user will be.

Note

This practical application doesn't include incorrect/correct examples.


 

15.4 If your application lets a user open and save a lot of files, make your application remember the user's chosen paths.

Have you ever had to open a large number of documents and been frustrated that, each time the Open dialog box appeared, the application defaulted to some arbitrary path? If users are going to open or save a lot of files in your application, store the open and save paths (separately) and default the next dialog box to the saved path. This will make it easier for users to work with lots of files. If you're feeling really clever, consider storing the paths in the registry or a database so that the paths are used the next time the user runs your application.



Practical Standards for Microsoft Visual Basic. NET
Practical Standards for Microsoft Visual Basic .NET (Pro-Developer)
ISBN: 0735613567
EAN: 2147483647
Year: 2005
Pages: 84

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net