With ”traditional” programming languages (often referred to as procedural languages), the program itself fully dictates what code is executed and when it's executed. When you start such a program, the first line of code in the program executes, and the code continues to execute in a completely predetermined path. The execution of code may, on occasion, branch and loop, but the execution path is completely controlled by the program. This often meant that a program was rather restricted in how it could respond to the user. For instance, the program might expect text to be entered into controls on the screen in a predetermined order, unlike in Windows, where a user can interact with different parts of the interface, often in any order the user chooses.
In the previous hour, you learned how a method is simply a function of an object. Events are a special kind of method; they are a way for objects to signal state changes that may be useful to clients of that object. Events are methods that can be called in special ways—usually by the user interacting with something on a form or by Windows itself, rather than being called from a statement in your code.
There are many types of events and many ways to trigger those events. You've already seen how a user can trigger the Click event of a button by clicking it. User interaction isn't the only thing that can trigger an event, however. An event can be triggered in one of the following four ways:
Users can trigger events by interacting with your program.
Objects can trigger their own events, as needed.
The operating system (whichever version of Windows the user is running) can trigger events.
The most common way an event is triggered is by a user interacting with a program. Every form, and almost every control you can place on a form, has a set of events specific to its object type. For example, the Button control has a number of events, including the Click event, which you've already used in previous hours. The Click event is triggered, and then the code within the Click event executes when the user clicks the button.
The Textbox control allows users to enter information using the keyboard, and it also has a set of events. The Textbox control has some of the same types of events as the Button control, such as a Click event, but the Textbox control also has events not supported by the Button control, such as a TextChanged event. The TextChanged event occurs each time the contents of the text box change, such as when the user types information into the text box. Because you can't enter text within a Button control, it makes sense that the Button control wouldn't have a TextChanged event. Each and every object that supports events supports a unique set of events.
Each type of event has its own behavior, and it's important to understand the events with which you work. The TextChanged event, for instance, exhibits a behavior that may not be intuitive to a new developer because the event fires each time the contents of the text box change. If you were to type the following sentence into an empty text box:
C# is very cool!
the Change event would be triggered 16 times—once for each character typed—because each time you enter a new character, the contents of the text box are changed. Although it's easy to think that the Change event fires only when you commit your entry, such as by leaving the text box or pressing Enter, this is simply not how it works. Again, it's important to learn the nuances and the exact behavior of the events you're using. If you use events without fully understanding how they work, your program may exhibit unusual, and often very undesirable, results.
Triggering events (which are just a type of procedure) using C# code is discussed in detail in Hour 11, “Creating and Calling Methods.” |
Sometimes an object triggers its own events. The most common example of this is the Timer control's Timer event. The Timer control doesn't appear on a form when the program is running; it appears only when you're designing a form. The Timer control's sole purpose is to trigger its Timer event at an interval that is specified in its Interval property.
By setting the Timer control's Interval property, you control the interval, in milliseconds, when the Timer event executes. After firing its Timer event, a Timer control resets itself and again fires its Timer event when the interval has passed. This occurs until the interval is changed, the Timer control is disabled, or the Timer control's form is unloaded. A common use of timers is to create a clock on a form. You can display the time in a label and update the time at regular intervals by placing the code to display the current time in the Timer event. You'll create a project with a Timer control in Hour 8, “Advanced Controls.”
Finally, Windows can trigger certain events within your program —events that you may not even know exist. For example, when a form is fully or partially obstructed by another window, the program needs to know when the offending window is resized or moved so that it can repaint the area of its window that's been hidden. Windows and C# work together in this respect. When the obstructing window is moved or resized, Windows tells C# to repaint the form, which C# does. This also causes C# to raise the form's Paint event. You can place code into the Paint event to create a custom display for the form, such as drawing shapes on the form using a Graphics object. That way, every time the form repaints itself, your custom drawing code executes.
You must make sure never to cause an event to endlessly trigger itself. An event that continuously triggers itself is called a recursive event. To illustrate a situation that causes a recursive event, think of the text box's TextChanged event discussed earlier. The TextChanged event fires every time the text within the text box changes. Placing code into the TextChanged event that alters the text within the text box would cause the Change event to be fired again, which could result in an endless loop. Recursive events terminate when Windows returns a StackOverFlow exception (see Figure 4.1), indicating that Windows no longer has the resources to follow the recursion. |
When you receive a StackOverFlow exception, you should look for a recursive event as the culprit. |
Recursive events can involve more than one event in the loop. For example, if Event A triggers Event B, which in turn triggers Event A, you can have recursion of the two events. Recursion can take place among a sequence of many events, not just one or two.
Accessing an object's events is simple, and if you've been following the examples in this book, you've already accessed a number of objects' default events. To access all of an object's events, you can use the Events icon (the lightning bolt) in the Properties window.
You're now going to create a project to get the feel for working with events. Start C# and create a new Windows Application project titled View Events, and then follow these steps:
1. |
Use the toolbox to add a picture box to the form. |
2. |
Change the name of the picture box to picText. |
3. |
Click the Events button on the Properties window toolbar (the lightning bolt icon). |
Your screen should look like the one in Figure 4.2. Notice that the Properties window now lists all the events for the selected object; in your case, it is the picText PictureBox object.
When you access a control's events, the default event for that type of control is selected. As you can see, the Click event is the default for a PictureBox. Scroll through the picText events and select the MouseDown event. Double-click the word MouseDown and C# will create the MouseDown event procedure and position you within it, ready to enter code (see Figure 4.3).
The full event declaration for the Click event is the following:
private void picText_MouseDown(object sender, _ System.Windows.Forms.MouseEventArgs e)
The words Private and Void are reserved words that indicate the scope and type of the method. Scope and type are discussed in Hour 11. |
The MouseDown event of a form has the following parameters:
object sender
and
System.Windows.Forms.MouseEventArgs e
The first word identifies the type of data the parameter contains, followed by the name of the parameter. The first parameter, sender, holds a generic object. Object parameters can be any type of object supported by C#. It's not critical that you understand data types right now, just that you're aware that different parameter variables contain different types of information. Some contain text, others contain numbers, and still others (many others) contain objects. In the case of the sender parameter, it will always hold a reference to the control causing the event.
The e parameter, on the other hand, is where the real action is with the MouseDown event. The e parameter also holds an object; in this case the object is of the type System.WinForms.MouseEventArgs. This object has properties that relate to the MouseDown_event. To see them, type in the following code, but don't press anything after entering the dot (period):
e.
When you press the period, you'll get a drop-down list showing you the members (properties and methods) of the e object (see Figure 4.4). Using the e object, you can determine a number of things about the occurrence of the MouseDown event. I've listed some of the more interesting items in Table 4.1.
Each time the event occurs, the parameters are initialized by C# so that they always reflect the current occurrence of the event. |
Each event has parameters specific to it. For instance, the TextChanged event returns parameters different from the MouseDown event. As you work with events—and you'll work with a lot of events—you'll quickly become familiar with the parameters of each event type. You'll learn how to create parameters for your own methods in Hour 11.
Deleting an event handler involves more than just deleting the event procedure. When you add a new event handler to a class, C# automatically creates the event procedure for you and positions you to enter code within the event. However, C# does a little bit more for you “under the covers” to hook the event procedure to the control. It does this by creating a code statement in the hidden code of the class. Ordinarily, you don't have to worry about this statement. However, when you delete an event procedure, C# doesn't automatically delete the hidden code statement, and your code won't compile. The easiest way to correct this is to run the project; when C# encounters the error, it will show you the offending statement, which you can delete. Try this now:
1. |
Delete the MouseDown procedure (don't forget to delete the open and close brackets of the procedure, as well as any code within them). This deletes the procedure. |
2. |
Press F5 to run the project. You'll receive a message that a build error has occurred. Click No to return to the code editor. |
3. |
A task for the error has been created in the Task List. Double-click the task and C# will take you to the offending statement. It will read: this.pictureBox1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseDown); |
4. |
Delete this statement, and now your code will compile and run. |
Whenever you delete an event procedure, you will have to delete the corresponding statement that links the procedure to its object before the code will run.
3.149.240.58