Adding and Firing Events


When something interesting happens in a COM object, we'd like to be able to spontaneously notify its client without the client polling the object. COM provides a standard mechanism for sending these notifications to clients (normally called "firing an event") using the connection-point architecture.

Connection-point events are actually methods on an interface. To support the widest variety of clients, an event interface is often defined as a dispinterface. Choosing Support Connection Points in the ATL Simple Object Wizard generates an event in our IDL file. The following is an example of the wizard-generated code augmented with a single event method (shown in bold):

[     uuid(B830F523-D87B-434F-933A-623CEF6FC4AA),     helpstring("_ICalcPiEvents Interface") ] dispinterface _ICalcPiEvents {     properties:     methods:     [id(1)] void OnDigit([in] short nIndex,         [in] short nDigit); }; 


In addition to changing the IDL file, the Support Connection Points option makes several changes to the class definition. The IConnectionPointContainerImpl base class is added. This class implements the IConnectionPointContainer interface, providing functionality for managing multiple event interfaces on the class. The IConnectionPointImpl base class implements a connection point for a specific event interface: _ICalcPiEvents, in this case. The COM_MAP is also modified to include an entry for IConnectionPointContainer, and a new map, the CONNECTION_MAP, is added to the class.

The wizard also generates a proxy class for the connection point. This proxy class is added to the base class list and provides a convenient way to actually fire the events (that is, call the methods on the connection point). This is very helpful because the typical connection point is a dispinterface.

For example:

STDMETHODIMP CCalcPi::CalcPi(BSTR *pbstrPi) {   // (code to calculate pi removed for clarity)   ...   // Fire each digit   for( short j = 0; j != m_nDigits; ++j ) {     Fire_OnDigit(j, (*pbstrPi)[j+2] - L'0');   }   ... } 


Objects of the CCalcPi class can now send events that can be handled in a page of HTML:

<object class         id=objPiCalculator>         <param name=digits value=50> </object> <input type=button name=cmdCalcPi value="Pi to 50 Digits:"> <span id=spanPi>unknown</span> <p>Distribution of first 50 digits in pi: <table border cellpadding=4> ... <!- table code removed for clarity > </table> <script language=vbscript>   ' Handle button click event   sub cmdCalcPi_onClick     spanPi.innerText = objPiCalculator.CalcPi   end sub   ' Handle calculator digit event   sub objPiCalculator_onDigit(index, digit)     select case digit     case 0: span0.innerText = span0.innerText + 1     case 1: span1.innerText = span1.innerText + 1     ... <! etc >     end select     spanTotal.innerText = spanTotal.innerText + 1   end sub </script> 


The sample HTML page handles these events to provide the first 50 digits of pi and their distribution, as shown in Figure 1.11.

Figure 1.11. Pi to 50 digits


For more information about ATL's support for connection points, see Chapter 9, "Connection Points."




ATL Internals. Working with ATL 8
ATL Internals: Working with ATL 8 (2nd Edition)
ISBN: 0321159624
EAN: 2147483647
Year: 2004
Pages: 172

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net