Hour 28


During this hour you will learn

Using Keyboard and Mouse I/O

This lesson explains how to use the keyboard and mouse to exercise more user interface control. Although the controls you've seen provide for excellent I/O, your programs may need to respond to the keyboard differently from the ways you've seen so far. For example, you may want to know whether users have pressed a key, even if no keyboard-based control (such as a text box) now has the focus. You can determine exactly when users press a key and even when users release that key.

After you master the mouse, you'll not only be able to respond to mouse movements and clicks, you'll also be able to support drag-and-drop operations. Surprisingly, no mouse control exists. The mouse (as with the keyboard's keystrokes) generates events that your procedures can test for and respond to.

Topic 1: Programming the Keyboard

Keyboard events let your applications monitor the keyboard's input. After your application receives keyboard input, the application can then modify the input or ignore the pressed key if it isn't an expected keystroke. Keystroke testing is useful for triggering a splash screen's closing, validating input, and even playing some types of games.

Overview

Mastering the keyboard requires that you master the following events:

In addition to these events, the Form control's KeyPreview property determines the way your application responds to keystrokes. This topic section explains how to use these events and the KeyPreview property to manage the user's keyboard.

Users can combine certain keys, such as Alt, Shift, and Ctrl, with mouse clicks. This lesson's second topic explains how to check for these keystrokes if they happen at the same time as a mouse event.

The KeyPress Event

The KeyPress event occurs when users press any key that corresponds with one of these characters:

When describing the KeyPress event, most programmers say that KeyPress tests for ASCII characters (those characters that appear in Appendix B's ASCII table). As you can see, KeyPress doesn't test for all ASCII characters (such as the horizontal tab or the arrow keys), but it certainly does test for most of them. Use KeyPress to determine exactly which key users pressed. For example, KeyPress will return a letter A if users press that key.

The KeyPress event occurs on the downstroke and will repeat as the keyboard auto-repeats characters.

An event, as you know, is always associated with an object, such as a command button or the form. The KeyPress event always associates with whatever object now has the focus when users press the key. If no object has the focus, the KeyPress event associates with the form. (An exception can occur, depending on the KeyPreview property explained at the end of this topic section.)

Don't use a keystroke event to test for a menu shortcut key. The Menu Editor supports shortcut keys for you and sets up the response automatically by triggering the menu item's Click() event procedure. If you test for keystroke events, your program won't be able to respond to menu selections.

The KeyPress event procedure always contains an integer argument. Therefore, if you were to write a KeyPress event for a Text Box control, the event procedure might begin and end like this:

Private Sub Text1_KeyPress (KeyAscii As Integer)

'

' Code goes here to test and respond to keystroke

'

End Sub

The KeyAscii argument is an integer that represents the ASCII code of the character the user pressed. You can use If or a Select Case statement to see whether the character is an expected keystroke.

One of the most important tasks you can perform with KeyPress is to change users' keystrokes. The KeyPress event occurs as soon as users press the key and before a control gets the keystroke. Normally, for example, a Text Box control immediately displays whatever key users pressed when the Text Box control has the focus. If, however, you write a KeyPress event procedure for a text box control, the KeyPress event procedure can change the key, as is done in the following code:

Private Sub txtTryIt_KeyPress(KeyAscii As Integer)

' Change any uppercase A to an uppercase B

If KeyAscii = 65 Then ' 65 is ASCII for A

KeyAscii = 66 ' 66 is ASCII for B

End If

End Sub

If the text box named txtTryIt has the focus, the text box will accept and display any keystroke the user presses until the user presses an uppercase A with an ASCII code value of 65. The If statement changes the keystroke's KeyAscii value to a letter B (ASCII 66), and the Text Box control shows the B and not the A because the KeyPress event gets the keystroke before the text box gets the KeyAscii value.

Search VB's online help for Key Code Constants. The online help displays named literals that you can use in keyboard testing. For example, you can test for a Backspace press by checking KeyAscii for vbKeyBack, test for an Enter press by checking for vbKeyReturn, and test for Tab press by checking for vbKeyTab. (Remember that KeyPress tests for only these three controls, in addition to letters, numbers, and punctuation.) Although the text box will respect the other keystroke controls (such as Home and End), KeyPress reliably responds only to Enter, Tab, and Backspace.

The KeyDown and KeyUp Events

Whereas KeyPress tests for a wide range of keystrokes, the KeyDown event is more specific. KeyDown occurs when users press a key down just as KeyPress does, but KeyDown gives you a more detailed-albeit slightly more complicated-status of your keyboard. For example, KeyPress returns a different ASCII value for the uppercase T and the lowercase t keypresses. KeyDown returns the same value, as well as another value called the state argument that describes the state of the Shift key.

The KeyDown event occurs whenever users press a key. Therefore, both the KeyDown and KeyPress events can occur at the same time (assuming that users press an ASCII key).

Use KeyPress if you want to test for an ASCII keystroke, because KeyPress is simpler to program than KeyDown.

Here are the opening and closing statements of a KeyDown event procedure:

Private Sub txtTryIt_KeyDown(KeyCode As Integer,

[ccc]Shift As Integer)

'

' Keyboard code handler goes here

'

End Sub

KeyCode contains the keystroke, and the Shift argument determines the state of the control keys such as Shift, Ctrl, and Alt. The KeyCode matches the uppercase equivalent of the key pressed. Therefore, if users press a lowercase t, the KeyCode argument contains 84 (the ASCII value for an uppercase T).

KeyDown's ignorance of the lowercase keys can cause confusion if you're not careful. If you receive a number keypress, you must check the Shift argument. If Shift indicates that users pressed Shift at the same time as the number, users actually wanted the corresponding character above the number (such as the caret, ^, above the 6).

The primary advantage of KeyDown over KeyPress is that, despite KeyDown's Shift problems, you can check for virtually any keystroke, including the arrow keys, Home, End, and so on. Again, check online help for the key-code constants that VB uses to test these special keystrokes.

The shift state is the key-either Shift, Ctrl, Alt, or none-that users press with the other key. The internal binary pattern of the shift argument determines the kind of shift state. To check the shift state, you must perform an And against a number 7. (This special kind of And is called a bitwise And, as opposed to the more common logical And that works as a compound comparison operator.) The code in Listing 28.1 is the shell that performs the common shift state test.

Listing 28.1 Code That Tests for the Shift State

Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer)

Dim intShiftState As Integer

intShiftState = Shift And 7 ' Special bitwise And

Select Case intShiftState

Case 1

' Code for Shift combinations

Case 2

' Code for Ctrl combinations

Case 4

' Code for Alt combinations

Case 3

' Code for Shift+Ctrl combinations

Case 5

' Code for Shift+Alt combinations

Case 6

' Code for Ctrl+Alt combinations

Case 7

' Code for Shift+Ctrl+Alt combinations

End Select

End Sub

The KeyUp event occurs whenever users release a pressed key. You can test for the specific key released (such as the A if users release half of a Shift+A keystroke) by analyzing the argument passed to KeyUp(). Therefore, KeyUp occurs after both KeyDown and KeyPress events.

Using SendKeys

The SendKeys statement sends keystroke to your application as though the user were typing those keystrokes. SendKeys is useful for controlling the placement of the text cursor because you can send keystrokes such as the Home and End keys to position the text cursor in a text box or other data-entry control. Here is the syntax of SendKeys:

SendKeys strKeystrokes[, blnWait]

strKeystrokes is often a string literal, such as "Widgets, Inc.", if you want to type the value for users. The Boolean blnWait option is usually omitted and, if False (the default if you omit blnWait), control returns to the executing procedure as soon as the keystrokes are sent. If blnWait is True, the system processes the keystrokes before the code continues, meaning that the keystroke events are active during the keystroke entry.

You must enclose the following special characters inside braces, ({}), if you send them with SendKeys: caret (^), plus sign (+), percent sign (%), tilde (~), and parentheses. Therefore, to simulate typing 7 + 6, the SendKeys statement must embed the plus sign in braces, like this:

SendKeys "7 {+} 6"

Several special keystroke characters, such as the Home and function keys, require a SendKeys code and the braces. For example, to send the Home keypress to an application, you must use the {Home} literal as follows:

SendKeys "{Home}"

All these special keys have code equivalents you can use. You can look up SendKeys in online help to learn which keystroke codes are defined for the special keys.

You can't send the Print Screen keystroke to an application with SendKeys.

Form or Control Response

When users press a key, either the form or the control with the active focus gets the keystroke. If no control currently has the focus, the form gets the keystroke event. If, however, a control has the focus, either the control or the form gets the focus, depending on the result of the form's KeyPreview property.

If the form's KeyPreview property is True, the form receives the keystroke event. Therefore, if you had coded two event procedures named frmAcct_KeyDown() and txtEntry_KeyDown(), and if the form's KeyPreview property contains True, the frmAcct_KeyDown() event procedure executes when users press a key. If the form's KeyPreview property contains False, the txtEntry_KeyDown() control executes (assuming that the text box has the current focus).

Example

The following code shows an event procedure for a text box. The code converts any lowercase letters the user types into the Text Box control to uppercase:

Private Sub txtTry_KeyPress(KeyAscii As Integer)

' Convert any lowercase letters to uppercase

If (KeyAscii >= 97) And (KeyAscii <= 122) Then

KeyAscii = KeyAscii - 32 ' Adjust to upper

End If

End Sub

The ASCII value range for lowercase letters, as you can verify from Appendix B, is 97 (for a) to 122 (for z). The ASCII value difference between the uppercase letters and their lowercase counterparts is 32. Therefore, if the KeyPress event procedure successfully gets a lowercase letter ASCII value, the procedure subtracts 32 from the value to convert the value to its uppercase equivalent.

Don't use the keyboard events to write your own masked edit routine if you use the Professional or Enterprise edition of VB. Both editions let you add the Microsoft Masked Edit Controls 5.0 to the Toolbox, and the Masked Edit control lets you set up input fields, such as phone numbers with area codes and automatic parentheses and hyphens.

Next Step

Hour 26, "Using Form Templates," described the Options dialog box form template that contained the code shown here in Listing 28.2.

Listing 28.2 Formtemp.bas: Handling Options Dialog Box Selections

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)

Dim i As Integer

'handle ctrl+tab to move to the next tab

If Shift = vbCtrlMask And KeyCode = vbKeyTab Then

i = tbsOptions.SelectedItem.Index

If i = tbsOptions.Tabs.Count Then

'last tab so we need to wrap to tab 1

Set tbsOptions.SelectedItem = tbsOptions.Tabs(1)

Else

'increment the tab

Set tbsOptions.SelectedItem = tbsOptions.Tabs(i + 1)

End If

End If

End Sub

You can now understand this complete event procedure, whereas you really didn't posses all the tools before now. The code's purpose is to move the focus between tabbed pages in the Options dialog box. As users press Ctrl+Tab, the next tabbed page is to display and the previously displayed page is to disappear behind the new one. The If statement shows an interesting way to check for Ctrl+Tab. If users haven't pressed the Ctrl+Tab combination, nothing executes and the event procedure ends.

Topic 2: Mouse Events

Controlling the mouse is one fundamental task that Windows applications must be able to do. A number of events can result from user interaction with the mouse. By mastering the mouse events, you'll be able to sense the user's mouse movement, clicks, and double-clicks. Also, you'll be ready to master drag and drop.

Overview

This topic section teaches you how to monitor the mouse movements and button clicks. Before responding to the mouse, you may want to change the mouse cursor to reflect the current activity. For example, you might change the mouse cursor to an hourglass cursor during a long update or disk read. Also, you might want to change the mouse cursor to a different shape (such as the international Not symbol, the circle with a slash) if users move an object over a control that doesn't accept the moved object. After you set the mouse cursor, you can monitor the mouse-generated events so that you can respond to various mouse actions.

The Mouse Cursor

Table 28.1 lists the possible mouse cursors you can set. Almost every control that you place on the form contains a special property called MousePointer. The MousePointer property can take on any of Table 28.1's values. If you'd like to display an icon graphic in place of one of the predefined mouse pointers in Table 28.1, set the MouseIcon property to an icon file and then set the MousePointer property to 99 - Custom.

Table 28.1 Mouse Pointer Named Literals

Literal

Description

VbArrow

Regular mouse-pointer arrow

VbCrosshair

Cross hair

VbIbeam

I-beam

VbIconPointer

Small square within a square

VbSizePointer

Four-pointed arrow pointing up, down, left, and right

VbSizeNESW

Double-arrow pointing northeast and southwest

VbSizeNS

Double-arrow pointing up and down

VbSizeNWSE

Double-arrow pointing northwest and southeast

VbSizeWE

Double-arrow pointing left and right

VbUpArrow

Up arrow

VbHourglass

Hourglass (indicating wait)

VbNoDrop

No drop (the international Not sign)

VbArrowHourglass

Arrow with an hourglass

vbArrowQuestion

Arrow with a question mark

vbSizeAll

Size all for resizing operations

vbCustom

The shape indicated by the MouseIcon property

You can set these values at runtime by assigning the named literals or at design time by selecting one of the values in a control's MousePointer property.

Mouse Moves and Clicks

You'll use mouse events to check for a mouse movement or click. Windows generates these events and sends them to your program. Although your program might choose to ignore the events, you can place code in any of the events that you want to respond to. Table 28.2 describes each mouse event.

Table 28.2 Windows Generates These Mouse Events

Event

Description

Click

The user clicked a mouse button.

DblClick

The user double-clicked a mouse button.

MouseDown

The user pressed and held a mouse button.

MouseMove

The user moved the mouse.

MouseUp

The user released the mouse button.

All the mouse events associate with controls. You'll find the mouse events listed for almost every control, as well as for forms. For example, if you wanted to test for a mouse button click event on your form that's named frmTest, the event procedure would be named frmTest_MouseDown().

When users double-click a mouse button, the DblClick and MouseUp events occur. (Windows doesn't trigger a MouseDown event if users double-click the mouse.)

The MouseDown, MouseMove, and MouseUp event procedures always require these four arguments:

Visual Basic generates a movement event after users move the mouse every 10 to 15 twips. Although 15 twips is an extremely small portion of the window, VB doesn't get a mouse movement event for each twip movement.

Example

Suppose that you want the mouse cursor to change to a happy face when users move the mouse pointer over a command button named cmdHappy. From the cmdHappy Properties window, you would click the ellipses to select an icon file from the \VB\Graphics\Icons\Misc directory. Select the file named Face03.ico.

Now that you've displayed the mouse icon, change cmdHappy's MousePointer property to 99 - Custom. The customized value tells VB to check the MouseIcon property for the file to display if users move the mouse over the command button. Figure 28.1 shows the resulting happy mouse pointer.

FIG. 28.1

The mouse pointer now looks happy.

Next Step

Create a new project and then place an Image control named imgMouse on the form. Set the value of the image's Picture property to the bulls-eye icon, which can be found in the \VB\Graphics\Icons\Misc directory. Move the image to the upper-center portion of the Form window.

Add a text box named txtMouse to the form that lets a message be written on-screen. Adjust the text box to look something like Figure 28.2's Form window.

FIG. 28.2

Users will click this image.

Blank the text box's Caption and add the code shown in Listing 28.3.

Listing 28.3 Caption.bas: Testing for Various Mouse Events

Private Sub Form_Click()

txtMouse.Text = "You clicked the form"

End Sub

Private Sub Form_DblClick()

txtMouse.Text = "You double-clicked the form"

End Sub

Private Sub Form_MouseDown(Button As Integer, Shift As Integer,

[ccc]X As Single, Y As Single)

' Clicked over the form

txtMouse.Text = "Clicked over the form at " & X & ", " & Y

End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer,

[ccc]X As Single, Y As Single)

txtMouse.Text = "Moving the mouse..."

End Sub

Private Sub imgMouse_Click()

txtMouse.Text = "You clicked the image"

End Sub

Private Sub imgMouse_DblClick()

txtMouse.Text = "You double-clicked the image"

End Sub

Private Sub imgMouse_MouseDown(Button As Integer,

[ccc]Shift As Integer, X As Single, Y As Single)

' Clicked over the image

txtMouse.Text = "Clicked over the image at " & X & ", " & Y

End Sub

Private Sub imgMouse_MouseMove(Button As Integer,

[ccc]Shift As Integer, X As Single, Y As Single)

txtMouse.Text = "You moved over the image"

End Sub

The code tests for the various mouse-based event procedures and changes the text box according to user actions. If the MouseDown event doesn't seem to occur, click and hold your mouse button to read the MouseDown description. As you click, the x- and y-coordinates describe the mouse's twip location at the time of the click.

Topic 3: Dragging and Dropping

Now that you've mastered the standard mouse events, you're ready to master dragging and dropping. One of the most important features you can add to a visual graphics-based program is drag-and-drop support. Visual Basic makes drag-and-drop support extremely simple to implement.

Overview

Drag-and-drop is the process of the user, with the mouse, clicking an object on-screen, holding down the mouse button, and dragging that object to another location on-screen. Visual Basic gives you the choice of automatic drag-and-drop or manual drag-and-drop; the method you select depends on the needs your application has at the time.

Automatic Drag and Drop

Almost every control in the Toolbox contains the property named DragMode. This property lets users move the control with the mouse. When users move the control, Visual Basic displays an outline of the control. Your job is to move the control to the place where users release the mouse button. Although the automatic mode shows the moving control's outline, the automatic mode doesn't actually move the object.

The form's DragDrop event controls the placement of the drop. To set up the drag, you only need to change the control's DragMode property to 1 - Automatic. The control then can allow the drag and show the moving outline. The Form_DragDrop() event procedure takes care of the second half of the drag-and-drop operation by placing the dragged control in its new location.

Completing the Drag

Although the control's dragged outline appears as users move the mouse, you can change the outline to any icon file (such as the icon files in the \VB\Graphics\Icons directory). When you drag the control, the icon replaces the mouse pointer during the drag.

After users complete the drag, you should code the following Form_DragDrop() procedure to take care of moving the object to its final location. The DragDrop event takes care of removing the first location and moving to the placed location. Here's the code that performs the placement:

Private Sub Form_DragDrop(Source As Control, X As Single,

[ccc]Y As Single)

Source.Move X, Y

End Sub

The DragOver event procedure occurs when the user drags one control over another. DragOver receives four arguments:

Manual Drag-and-Drop

Manual drag-and-drop works just like automatic. except for these three differences:

The MouseDown event procedure can perform the special Drag method on the object if you want to continue the drag-and-drop process. The following code drags the image if the image control's DragMode property is set to 0 - Manual:

Private Sub imgMouse_MouseDown(Button As Integer,

[ccc]Shift As Integer, X As Single, Y As Single)

' Clicked over the image

txtMouse.Text = "Clicked over the image at " & X & ", " & Y

imgMouse.Drag

End Sub

The Drag method turns on drag-and-drop. Without the Drag method, the MouseDown() event procedure couldn't initiate the drag-and-drop operation. Use manual drag-and-drop operations if you want to perform processing and drag-and-drop limitations before and during the drag-and-drop process.

Example

Open the project you created in the second topic section. This example modifies the project somewhat to let you drag the bulls-eye icon around the form and drop the icon somewhere else.

Perform these steps to add drag-and-drop capabilities to the project:

  1. Change the image's DragIcon property by clicking the ellipses and selecting the Clock02 icon from \VB\Graphics\Icons\Misc. The bulls-eye image will turn into a clock during subsequent drag-and-drop activities.
  2. Change the image's DragMode to 1 - Automatic so that VB takes care of the dragging details for you.
  3. Open the Code window and add the following event procedure to the form's event procedures:

Private Sub Form_DragDrop(Source As Control, X As Single,

[ccc]Y As Single)

Source.Move X, Y ' Drop the image

End Sub

  1. The DragDrop event's Source argument is the control you're dropping onto the form, and the X and Y coordinate values tell the control where the drop is occurring. The Move method actually moves the control (the image in this case) to the location of the drop.
  2. Run the application and drag-and-drop the bulls-eye image around the form. When performing most drag-and-drop operations, you'll want to use automatic drag-and-drop so that VB handles the details of the drag.

Next Step

You can see how to easy it is to implement manual drag-and-drop by following these steps to turn the previous example into a manually controlled (via code) drag-and-drop application:

  1. Change the image's DragDrop property to 0 - Manual.
  2. You must now initiate the dragging when users click over the image. Change the image's MouseDown event procedure to the following code:

Private Sub imgMouse_MouseDown(Button As Integer,

[ccc]Shift As Integer, X As Single, Y As Single)

' Clicked over the image

txtMouse.Text = "Clicked over the image at " & X & ", " & Y

imgMouse.Drag ' Initiate the drag and drop

End Sub

  1. The only new statement is the imgMouse.Drag statement. Your MouseDown event must initiate the drag-and-drop operation. The advantage is that you can now perform other kinds of processing in response to the MouseDown click, if needed, before starting the drag-and-drop operation. Without the manual drag mode, the drag would take place outside your control.
  2. Run the application. You'll be able to drag-and-drop the image as easily as you did in the previous example.

Summary

Because of this lesson, you can now analyze the keyboard and respond to keyboard events that don't associate with a specific control's events. Therefore, you can decide exactly which keystrokes to allow or ignore when users enter text in a Text Box control. The keyboard events also let you respond to immediate keystrokes.

Controlling a mouse is simple due to the mouse-related events that VB supports. The mouse events are relatively simple because you can perform only four basic tasks with a mouse: click, double-click, multi-button click, and move. The mouse events inform your code, with appropriate arguments, of the mouse pointer's location.

This lesson's final topic section explained how to implement drag-and-drop. VB's automatic drag-and-drop mode is the easiest kind of drag-and-drop to implement, although you can manually control drag-and-drop if you need more control over the operation.

In Hour 29, "Building a Help Subsystem," you'll learn how to add help files to your application so that your users can request assistance when needed.

Hour 28 Quiz

  1. What's the difference between the KeyPress and KeyDown events?
  2. Describe how the ASCII table is invaluable for keyboard interpretation.
  3. True or false: The KeyDown event occurs before a text box control can display users' text as they type text.
  4. What's the difference between KeyPress and KeyPreview?
  5. Which mouse events respond to specific mouse buttons? Which mouse events respond to either mouse button?
  6. How can you determine the button clicked when a MouseDown event occurs?
  7. How do you program the outline that appears for some drag-and-drop operations?
  8. How can you change the icon that appears during a drag operation?
  9. What happens when users drag one control over another?
  10. Name two differences between an automatic drag-and-drop operation and a manual drag-and-drop operation.

Hour 28 Homework Exercises

  1. Write the code that changes all uppercase letters to lowercase letters as users type text in a Text Box control.
  2. Add a splash screen (such as a form with the message Press any key...) to the application you wrote in exercise 1. Keep the splash screen on-screen until users press any key on the keyboard.
  3. Play musical mouse! Write a simple application that plays a wave file when users click anywhere on the form and stops playing the file as soon as users release the mouse button.
  4. Write a drag-and-drop application that drags a letter into an envelope (let the envelope seal on its own). Use the icons in \VB\Graphics\Icons.


© 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.