Responding To Mouse and Keyboard Events
Responding To Mouse and Keyboard Events
keyboard events. For example, forms, picture boxes, and image controls can detect
the position of the mouse pointer, can determine whether a left or right mouse button
is being pressed, and can respond to different combinations of mouse buttons and
SHIFT, CTRL, or ALT keys. Using the key events, you can program controls and forms
to respond to various key actions or interpret and process ASCII characters.
In addition, Visual Basic applications can support both event-driven drag-and-drop
and OLE drag-and-drop features. You can use the Drag method with certain
properties and events to enable operations such as dragging and dropping controls.
OLE drag and drop gives your applications all the power you need to exchange data
throughout the Windows environment — and much of this technology is available to
your application without writing code.
You can also use the mouse or keyboard to manage the processing of long
background tasks, which allows your users to switch to other applications or
interrupt background processing.
Note If you are using the Control Creation Edition of Visual Basic, some of the material
covered in this document may not be applicable. With the full editions of Visual Basic you have
the ability to create applications, ActiveX documents, and other types of components. Although
some of the terminology may relate to application specific objects such as forms, in most
cases the underlying concepts also apply to ActiveX control creation.
1
For More Information Other actions and events that involve the mouse or keyboard
(the Click and DblClick events, the Focus events, and the Scroll event) are not
covered in this chapter. For more information on the Click, DblClick, and Focus
events, see the topics "Clicking Buttons to Perform Actions" and "Understanding
Focus" in "Forms, Controls, and Menus."
2
Contents
· Responding to Mouse Events
· Detecting Mouse Buttons
· Detecting SHIFT, CTRL, and ALT States
· Dragging and Dropping
· OLE Drag and Drop
· Customizing the Mouse Pointer
· Responding to Keyboard Events
· Interrupting Background Processing
3
Sample Application: Mouse.vbp
Many of the code examples in this chapter are taken from the Mouse.vbp sample
application. If you installed the sample applications, you'll find this application in
—1
—2
—3
—4
2
How MouseMove Works
How many times does the MouseMove event get called as the user moves the pointer
across the screen? Or, to put it another way, when you move the pointer from the top
of the screen to the bottom, how many locations are involved?
Visual Basic doesn't necessarily generate a MouseMove event for every pixel the
mouse moves over. The operating environment generates a limited number of mouse
messages per second. To see how often MouseMove events are actually recognized,
you can enhance the Scribble application with the following code so that it draws a
small circle at each location where a MouseMove event is recognized. The results
are shown in Figure 11.3.
Private Sub Form_MouseMove (Button As Integer,_
Shift As Integer, X As Single, Y As Single)
Line -(X, Y)
Circle (X, Y), 50
End Sub
13
Figure 11.3 A demonstration of where MouseMove events occur
—5
—6
The MouseDown, MouseUp, and MouseMove events use the button argument to
determine which mouse button or buttons are pressed. The button argument is a bit-
field argument — a value in which each bit represents a state or condition. These
values are expressed as integers. The three least-significant (lowest) bits represent
the left, right, and middle mouse buttons, as shown in Figure 11.4.
—7
5
The default value of each bit is 0 (False). If no buttons are pressed, the binary value
of the three bits is 000. If you press the left button, the binary value, or pattern,
changes to 001. The left-button bit-value changes from 0 (False) to 1 (True).
The button argument uses either a decimal value or an constant to represent these
binary patterns. The following table lists the binary value of the bits, the decimal
equivalent, and the Visual Basic constant:
Binary Value Decimal Value Constant Meaning
001 1 vbLeftButton The left button is
pressed.
010 2 vbRightButton The right button is
pressed.
100 4 vbMiddleButton The middle button is
pressed.
18
Note Visual Basic provides constants that represent the binary values of the button and shift
arguments. These constants can be used interchangeably with their equivalent decimal values.
Not all values have corresponding constants, however. The values for some button and/or shift
combinations are derived by simply adding decimal values.
19
The middle button is assigned to decimal value 4. Pressing the left and right buttons
simultaneously produces a single digit value of 3 (1+2). On a three-button mouse,
pressing all three buttons simultaneously produces the decimal value of 7 (4+2+1).
The following table lists the remaining button values derived from the possible
button combinations:
Binary Value Decimal Value Constant Meaning
000 0 No buttons are pressed.
011 3 vbLeftButton + The left and right
vbRightButton buttons are pressed.
101 5 vbLeftButton + The left and middle
vbMiddleButton buttons are pressed.
—8
—9
—10
—11
—12
7
Any or all of the bits in shift can be set, depending on the state of the SHIFT, CTRL,
and ALT keys. These values and constants are listed in the following table:
Binary Value Decimal Value Constant Meaning
001 1 vbShiftMask The SHIFT key is pressed.
010 2 vbCtrlMask The CTRL key is pressed.
100 4 vbAltMask The ALT key is pressed.
011 3 vbShiftMask + The SHIFT and CTRL keys are pressed.
vbCtrlMask
101 5 vbShiftMask + The SHIFT and ALT keys are pressed.
vbAltMask
110 6 vbCtrlMask + The CTRL and ALT keys are pressed.
vbAltMask
111 7 vbCtrlMask + The SHIFT, CTRL, and ALT keys are pressed.
vbAltMask +
vbShiftMask
33
As with the mouse events' button argument, you can use the If…Then…Else
statement or the And operator combined with the Select Case statement to determine
whether the SHIFT, CTRL, or ALT keys are being pressed and in what, if any,
combination.
Open a new project and add the variable ShiftTest to the Declarations section of the
form:
Dim ShiftTest as Integer
34
Add the following code to the form's MouseDown event:
Private Sub Form_MouseDown(Button As Integer, _
Shift As Integer, X As Single, Y As Single)
ShiftTest = Shift And 7
Select Case ShiftTest
Case 1 ' or vbShiftMask
Print "You pressed the SHIFT key."
—13
—14
—15
—16
—17
—18
—19
—20
—21
—22
—23
—24
9
Which events you’ll need to respond to depends upon how you’ve chosen to
implement the drag-and-drop functionality. For example, you may have created an
application with a text box that you want to allow to automatically accept dragged
data from another application. In this case, you simply set the control’s
OLEDropMode property to Automatic. If you want to allow data to be automatically
dragged from the text box control as well, you set its OLEDragMode property to
Automatic.
If, however, you want to change the default mouse cursors or enhance the
functionality for button states and shift keys, you need to manually respond to the
source- and target-side events. Likewise, if you want to analyze the data before it is
dropped into a control (to verify that the data is compatible, for instance), or delay
when the data is loaded into the DataObject object (so that multiple formats don't
need to be loaded at the beginning), you'll need to use manual OLE drag-and-drop
operations.
Because you can drag and drop data into numerous Visual Basic controls and
Windows applications — with varying limitations and requirements —
implementing OLE drag and drop can range from straightforward to fairly complex.
The simplest implementation, of course, would be dragging and dropping between
two automatic objects, whether the object is a Word document, an Excel
spreadsheet, or a control in your application that has been set to Automatic.
—25
—26
—27
Data.SetData , vbCFText
Data.SetData , vbCFRTF
End Sub
80
The target can query the source to determine which data formats are supported and
then respond accordingly — e.g., if the format of the dropped data is not supported
—28
—29
—30
—31
—32
—33
—34
—35
—36
Caution Retrieving your custom data format with the GetData method may yield
unpredictable results.
Because Visual Basic doesn’t understand your custom data format (because you
defined it), it doesn’t have a way to determine the size of the data. Visual Basic can
determine the memory size of the Byte array because it has been allocated by
Windows, but the operating system usually assigns more memory than is needed.
Therefore, when you retrieve a custom data format, you get back a Byte array
containing at least, and possibly more than, the number of bytes that the source
actually placed into the DataObject object. You must then correctly interpret your
custom data format when it is retrieved from the DataObject object. For example, in
—37
To drag text files into a text box control from the Windows Explorer
5 Start a new project in Visual Basic.
6 Add a text box control to the form. Set its OLEDropMode property to Manual.
Set its MultiLine property to True and clear the Text property.
7 Add a function to select and index a range of files. For example:
1Sub DropFile(ByVal txt As TextBox, ByVal strFN$)
2 Dim iFile As Integer
3 iFile = FreeFile
4
5 Open strFN For Input Access Read Lock Read _
6Write As #iFile
7 Dim Str$, strLine$
8 While Not EOF(iFile) And Len(Str) <= 32000
9 Line Input #iFile, strLine$
10 If Str <> "" Then Str = Str & vbCrLf
11 Str = Str & strLine
12 Wend
13 Close #iFile
14
15 txt.SelStart = Len(txt)
16 txt.SelLength = 0
17 txt.SelText = Str
18
19End Sub
104
8 Add the following procedure to the OLEDragOver event. The GetFormat method
is used to test for a compatible data format (vbCFFiles).
20Private Sub Text1_OLEDragOver(Data As _
21VB.DataObject, Effect As Long, Button As Integer, _
22Shift As Integer, X As Single, Y As Single, State _
23As Integer)
24 If Data.GetFormat(vbCFFiles) Then
25 'If the data is in the proper format, _
26inform the source of the action to be taken
27 Effect = vbDropEffectCopy And Effect
28 Exit Sub
—38
—39
—40
—41
—42
—43
—44
—45
—46
—47
—48
Using DoEvents
Although Timer events are the best tool for background processing, particularly for
very long tasks, the DoEvents function provides a convenient way to allow a task to
be canceled. For example, the following code shows a "Process" button that changes
to a "Cancel" button when it is clicked. Clicking it again interrupts the task it is
performing.
' The original caption for this button is "Process".
Private Sub Command1_Click()
' Static variables are shared by all instances
' of a procedure.
Static blnProcessing As Boolean
Dim lngCt As Long
Dim intYieldCt As Integer
Dim dblDummy As Double
' When the button is clicked, test whether it's
'already processing.
If blnProcessing Then
' If processing is in progress, cancel it.
blnProcessing = False
Else
Command1.Caption = "Cancel"
blnProcessing = True
lngCt = 0
' Perform a million floating-point
' multiplications. After every
' thousand, check for cancellation.
Do While blnProcessing And (lngCt < 1000000)
For intYieldCt = 1 To 1000
—49
—50
—51