Visual FoxPro provides true modeless operation so that you can easily coordinate multiple forms automatically and run multiple instances of a form simultaneously. Visual FoxPro also manages event processing for you so you can give your users a much richer interactive environment.
This chapter describes:
Event code is triggered automatically by the system in response to some user action. For example, code written for the Click event is automatically processed by the system when the user clicks on a control. Event code can also be triggered by system events, as in the case of the Timer event in a timer control.
The following table contains a list of the core set of Visual FoxPro events, which apply to most controls.
Core Event Set
Event | When the event is triggered |
Init | An object is created. |
Destroy | An object is released from memory. |
Click | The user clicks the object using the primary mouse button. |
DblClick | The user double-clicks the object using the primary mouse button. |
RightClick | The user clicks the object using the secondary mouse button. |
GotFocus | The object receives the focus, either by user action such as tabbing or clicking, or by changing the focus in code using the SetFocus method. |
LostFocus | The object loses the focus, either by user action such as tabbing to or clicking another object, or by changing the focus in code using the SetFocus method. |
KeyPress | The user presses and releases a key. |
MouseDown | The user presses the mouse button while the mouse pointer is over the object. |
MouseMove | The user moves the mouse over the object. |
MouseUp | The user releases the mouse button while the mouse pointer is over the object. |
There are two basic rules to keep in mind when you are writing event code for controls:
When a user interacts with an object in any way — by tabbing to it, clicking it, moving the mouse pointer over it, and so on — object events take place. Each object receives its events independently. For example, even though a command button is on a form, the form’s Click event is not triggered when a user clicks the command button; only the command button’s Click event is triggered.
Container event code is separate from control event code
If there is no Click event code associated with the command button, nothing happens when the user clicks the button, even though there is Click event code associated with the form.
This rule is also true of grid controls. The grid contains columns which in turn contain headers and controls. When events occur, only the innermost object involved in the event recognizes the event. The higher-level containers do not recognize the event. The following illustration shows which objects process the MouseMove events that are generated when a user moves the mouse pointer across the grid.
MouseMove events for a grid
There is an exception to this rule, however. If you have written event code for an option button group or a command button group but there is no code for the event in a particular button in the group, the group event code is executed when the button event occurs.
For example, you can have an option button group with associated Click event code. Only one of the two option buttons in the group has associated Click event code:
Event code for button groups can be used as the default
If a user clicks Option1, the Click event code associated with Option1 is executed. The Click event code associated with the option button group is not executed.
Because there is no Click event code associated with Option2, if the user clicks Option2, the option group Click event code is executed.
Note When a sequence of events, such as MouseDown then MouseUp, is initiated for a control, the whole sequence of events belongs to the control.
For example, if you click the left mouse button on a command button and drag the mouse pointer away from the command button, the command button’s MouseMove events continue to occur, even though the mouse pointer is moving over the form. If you release the left mouse button over the form instead of over the command button, the MouseUp event that occurs is associated with the command button rather than the form.
If a control on a form is based on a user-defined class (which, in turn, could be based on another user-defined class), Visual FoxPro checks in the immediate control for event code when an event occurs. If there is code in that event procedure, Visual FoxPro executes it. If no code exists in the event procedure, Visual FoxPro checks the next level up in the class hierarchy. If at any point in the class hierarchy Visual FoxPro finds code for the event, that code is executed. Any code further up the hierarchy is not executed.
If no event code is associated with an object, Visual FoxPro checks the parent class.
You can, however, include code in an event procedure and explicitly call the code in classes that the control is based on by using the DODEFAULT( ) function.
The Visual FoxPro event model is extensive, allowing you a great deal of control over the components of your application in response to a wide variety of user actions. Some of the event sequences are fixed, as for example, when a form is created or destroyed. Some events occur independently, but most occur in conjunction with several other events based on user interaction.
The best way to see the Visual FoxPro event sequences is to set event tracking on in the debugger. Event tracking allows you to see when each event associated with your own forms and controls occurs in relation to other events, so that you can determine the most efficient place to include your code.
To set event tracking on
The events in the Events to track list are written to the Debugger Output window or a file as they occur.
The Event Tracking dialog box
Note this example, the MouseMove and Paint events have been removed from the Events to track list because these events occur so frequently that they make it more difficult to see the sequences of the other events.
Sometimes a single event is triggered by a user action, such as the user moving the mouse pointer over a control. Often, however, a user action triggers multiple events.
This section describes the order in which events occur in response to user interaction, using the following form as an example.
A sample form to illustrate event sequences
In this example scenario, the user performs the following actions on the form:
These actions trigger one or more system events for each object. The following tables detail the events triggered in response to each user action.
The user runs the form by typing the following command in the Command window:
DO FORM form1 NAME frmObject
Visual FoxPro loads the form, initializes each object, then initializes the form; the form is activated and then the first field receives input focus.
Object | Event |
DataEnvironment | BeforeOpenTables |
Form1 | Load |
DataEnvironment | Init |
Text1 | Init |
Text2 | Init |
Command1 | Init |
Command2 | Init |
Form1 | Init |
Form1 | Activate |
Form1 | GotFocus |
Text1 | When |
Text1 | GotFocus |
The user types Test in Text1. Each keystroke generates two events. The KeyPress event receives 2 parameters: the pressed key and the state of the SHIFT, ALT, and CTRL keys.
Object | Event |
Text1 | KeyPress(84, 1) “T” |
Text1 | InteractiveChange |
Text1 | KeyPress(101, 0) “e” |
Text1 | InteractiveChange |
Text1 | KeyPress(115,0) “s” |
Text1 | InteractiveChange |
Text1 | KeyPress(116,0) “t” |
Text1 | InteractiveChange |
The user double-clicks Text1 to select the text, then presses CTRL+C to copy the text to the Clipboard. Mouse events and a Click event accompany the DblClick event. The MouseMove and MouseDown events receive four parameters: a number indicating which button was pressed, the Shift state, and X and Y locations. The X and Y locations are relative to the form and reflect the scale mode (for example, pixels) of the form. Only one MouseMove event is listed for each control. In actuality, this event would probably fire half a dozen times or more.
Object | Event |
Form1 | MouseMove(0, 0, 100, 35) |
Text1 | MouseMove(0,0,44,22) |
Text1 | MouseDown(1, 0, 44, 22) |
Text1 | MouseUp(1, 0, 44, 22) |
Text1 | Click |
Text1 | MouseDown(1, 0, 44, 22) |
Text1 | MouseUp(1, 0, 44, 22) |
Text1 | DblClick |
The user presses TAB to move to Text2.
Object | Event |
Text1 | KeyPress(9, 0) |
Text1 | Valid |
Text1 | LostFocus |
Text2 | When |
Text2 | GotFocus |
The user pastes the copied text into Text2 by pressing CTRL+V.
Object | Event |
Text2 | InteractiveChange |
The user clicks Command2, which closes the form.
Object | Event |
Form1 | MouseMove |
Command2 | MouseMove |
Text2 | Valid |
Command2 | When |
Text2 | LostFocus |
Command2 | GotFocus |
Command2 | MouseDown(1, 0, 143, 128) |
Command2 | MouseUp(1, 0, 143, 128) |
Command2 | Click |
Command2 | Valid |
Command2 | When |
As the form closes and the object is released, these additional events take place, in opposite order to the events in Action 1.
Object | Event |
Form1 | Destroy |
Command2 | Destroy |
Command1 | Destroy |
Text2 | Destroy |
Text1 | Destroy |
Form1 | Unload |
DataEnvironment | AfterCloseTables |
DataEnvironment | Destroy |
The following table shows the general firing sequence of Visual FoxPro events. The data environment’s AutoOpenTables property is assumed to be set to true (.T.). Other events can occur based on user interaction and system response.
Object | Events |
Data environment | BeforeOpenTables |
Form set | Load |
Form | Load |
Data environment cursor(s) | Init |
Data environment | Init |
Objects 1 | Init |
Form | Init |
Form set | Init |
Form set | Activate |
Form | Activate |
Object1 2 | When |
Form | GotFocus |
Object1 | GotFocus |
Object1 | Message |
Object1 | Valid 3 |
Object1 | LostFocus |
Object2 3 | When |
Object2 | GotFocus |
Object2 | Message |
Object2 | Valid 4 |
Object2 | LostFocus |
Form | QueryUnload |
Form | Destroy |
Object 5 | Destroy |
Form | Unload |
Form set | Unload |
Data environment | AfterCloseTables |
Data environment | Destroy |
Data environment cursor(s) | Destroy |
1. For each object, from innermost object to outermost container
2. First object in the tab order
3. Next object to get focus
4. As the object loses focus
5. For each object, from outermost container to innermost object
Unless you associate code with an event, nothing happens when that event occurs. You’ll almost never write code for all of the events associated with any Visual FoxPro object, but you’ll want to incorporate functionality in response to certain key events in your applications. To add code to be executed when an event occurs, use the Properties window in the Form Designer.
The sequence of events affects where you should put code. Keep in mind the following tips:
For more information about using the Form Designer, see Chapter 9, Creating Forms. For information on coding classes and adding event code, see Chapter 3, Object-Oriented Programming.