The Unified Event Model


In the past, there have been different ways to create and handle events. For example, callback functions are used pervasively within the WIN32 API. A lot of functions require a function pointer that is to be used as the callback function. However, this function has to be a static member function within your class, which means you don't have access to any of the data members of the current class instance. In other words, the this pointer within your static callback function is undefined. There have been a few workarounds for this, such as using global functions or variables, and sometimes, if you're lucky, the function that requires a callback function pointer might have another parameter to which you can assign the this pointer to be passed into the callback function when it is called. As you can see, such workarounds can contribute to bad programming practices, especially if the scale of your project reaches large proportions.

Another way of handling events has been the use of connection points within the Component Object Model (COM) with the help of Active Template Library (ATL) classes. However, the process of creating an event can be complicated, even for a seasoned veteran. Add to this the complexity of ensuring automation compatibility by using only automation-compatible data types, and the process can become a daunting task.

The Unified Event Model within Visual C++ .NET was designed and implemented to handle some of these issues. There are still callback functions and connection points, but now you have another option in the form of an easy-to-use and well-designed model for event handling. First, we'll look at the basic architecture of the Unified Event Model and define some of the new attributes and keywords it contains. This will help you better understand some of the programming lessons later in this hour.

Unified Event Model Architecture

The centerpiece of the Unified Event Model is the delegate. Formally, a delegate is a class that wraps and controls access to a method with a specific signature. This method can either be an instance or a static function pointer. This fact alone solves the problem with using callback functions within C++, which require static function pointers, thus denying access to any instance member variables within the class.

A delegate is declared with the __delegate keyword, and it generally prefaces a function signature, as the following code shows:

 1: __delegate int HelloWorld(); 

However, even though a delegate shares many similarities with a function pointer, and the keyword is placed within the context of a function, a delegate itself is actually a C++ class. You'll learn more about the use of the __delegate keyword and the internal structure of the delegate class later this hour.

Events contain two main components: a sender and a receiver. These are also sometimes known as a source and a sink, respectively. The sender object is specified using the event_source attribute. This attribute is applied preceding the class declaration and is also used to specify whether the source object is a COM component, a managed C++ class, or a native C++ class. Each method used as an event is preceded by the __event attribute. An event is simply a method within an event source object that is used to generate or fire events back to any connected clients. The following code shows a native C++ class that acts as an event source and contains a single event:

 1: [event_source(native) 2: class CSource 3: { 4: public: 5:     CSource(void); 6:     ~CSource(void); 7:     __event void MyEvent( int iParam ); 8: } 

The connected clients are known as the event receivers. An event receiver, much like the event source object, is prefaced with the event_receiver attribute and also contains a parameter specifying the type of class of the event receiver. Within the event receiver object are specific methods with the same signature as an event source event method, as shown in the following code:

 1: [event_receiver(native)] 2: class CSink 3: { 4: public: 5:     CSink(void); 6:     ~CSink(void); 7:     void MyEventHandler( int iParam ); 8: } 

In order to connect and disconnect an event source method with an event receiver event handler, you use the __hook and __unhook methods. Internally, these attributes add the event receiver's function pointers to a list within the event source object. When the event source object generates an event, it references its internal table of function pointers and synchronously calls each of these event handler methods. Figure 18.1 provides a general overview of how event source and event receiver objects communicate to form the event connections.

Figure 18.1. Event communication between one source object and multiple event receivers.



Sams Teach Yourself Visual C++. NET in 24 Hours
Sams Teach Yourself Visual C++.NET in 24 Hours
ISBN: 0672323230
EAN: 2147483647
Year: 2002
Pages: 237

Similar book on Amazon © 2008-2017.
If you may any questions please contact us: