Programming Guide: OpenDoc Event Notification

# Programming Guide

## OpenDoc Event Notification

OpenDoc parts can notify other software entities of an event. Event examples are receiving a mouse click or a counter reaching some threshold. A part that can report events is a connectable part and is an event source. The receiver of the notification is the event consumer.

If an OpenDoc part, the event source, receives a mouse click from the system and determines it should notify the event consumer; the OpenDoc part invokes methods that call an event consumer's subroutine.

To make a part connectable, the OpenDoc part must inherit from ODDSConnection, instantiate and ODDSEventMgr for each set of event interfaces the OpenDoc part supports, and add each event manager to the ODDSConnection EventManager list with ODDSConnection's AddEventMgr method.

The ScriptableSimplePartInterface sample is an example of a connectable OpenDoc part. It inherits from ODDSConnection and instantiates an ODDSEventMgr with an ODguid that is equal to the ODguid defined in the ScriptableSimplePartEvents IDL. The event manager maintains a list of event consumers.

ScriptableSimplePartEvents is a non-instantiated class that defines an event method: the MouseDown method. The IDL for this class defines the interface in the SOM interface repository and creates a TYPELIB for OLE event consumers.

When the ScriptableSimplePart receives a MouseDown in its event handling code, it calls the TriggerMouseDown method of ScriptableSimplePartInterface to notify the event consumers. The notification is done by issuing the following ODDSEventMgr methods:

- PrepareEventFiring
- multiple FireEvents
- StopFiring.

If the event consumer is a Visual Basic or a scripting application, OpenDoc scripting support provides the mechanism for calling the event notification method for the event consumer. If the event consumer is an OpenDoc part, the part developer should provide the mechanism for handling the event. This can be done as follows:

The event consumer, in this case `AnObject`, inherits from ScriptableSimplePartEvents and overrides the MouseDown method. `AnObject` instantiates an ODDSSink object passing ScriptableSimplePartEvents' ODGuid on the constructor. The ODDSSink's attribute object is set to reference `AnObject`. `AnObject` requests the notification of events from ScriptableSimplePartInterface by calling ODDSConnection's AddSink method that passes in a reference to the sink. When an event occurs, the event manager invokes the sink's FireEvent method that uses a SOM dispatch to call `AnObject`'s event method.

OLE event consumers use the IConnectionPointContainer and the IConnectionPoint interfaces to receive event notification. An OLE sink object is provided by OpenDoc scripting to support these interfaces.

### Making a Part Connectable

This section describes the necessary steps to make a part connectable as an event source. To illustrate these steps, segments of the IDL and code from the SimplePart are used.

#### IDL Segments

The ScriptableSimplePartInterface IDL segments contain some of the interface definition language from ScriptableSimplePartInterface.idl. The coding segments are preceded by descriptive lines detailing the coding action.

The introduced ScriptableSimpleEvents.idl is discussed in "ScriptableSimplePartEvents IDL Segment".

    #include <iodsimpl.idl>
    #include <oddsconn.idl>
    ...
    interface ODDSEventMgr;
                                                     /* part inheritance*/
    interface ScriptableSimplePartInterface : SimplePart, ODDSConnection {
    ...
    long TriggerMouseDown (in long x, in long y);  /* method definition */
    ...
                                              /* implementation section */
    #ifdef__SOMIDL__
      implementation {
      ...
      Odevent="ScriptableSimplePartEvents";      /* modifier identifier */
      ...
      ODDSEventMgr fEventManager;      /* location where variable saved */
                                    /* override methods to create event */
      };
    #endif
    };

#### ScriptableSimplePartInterface Code Segment

The following code illustrates the TriggerKeyPress method from the sample's ScriptableSimplePartInterface.

    SOM_Scope long SOMLINK ScriptableSimplePartTriggerMouseDown (
                             ScriptableSimplePart *somSelf,
                             Environment *ev,
                             long x,
                             long y)
    {
      __IDL_SEQUENCE_any  inParms;
      ODDSRESULT          result;
      long                sinkCount;
      long                sinkNumber;
      any                 data[2];
      ODDSSinkEnum       *sinkEnum;

                                           /* Set up any for parameters */
      data [0]._type = TypeCodeNew (tk_long);
      data [0]._value = (void *) &x;
      data [1]._type = TypeCodeNew (tk_long);
      data [1]._value = (void *) &y;

      inParms._length  = 2;
      inParms._maximum = 2;
      inParms._buffer  = data;

           /* PrepareEventFiring obtains the enumeration to control the */
     /* event firing sequence.  A count of event consumers is returned. */
      _fEventManager->PrepareEventFiring (ev, &sinkCount, &sinkEnum,);

      for (i=0; i<sinkCount; i ++)
        {
                     /* The next event consumer in the enum is notified */
        _fEventManager->FireEvent (ev, sinkEnum, "MouseDown", &inParms, &result);
        }
                                                    /* Frees enumerator */
      _fEventManager->StopEventFiring (ev, sinkEnum);
      return (0);
    {

#### ScriptableSimplePartEvents IDL Segment

The ODids in the following segment correspond to OLE DISPIDs as defined in the Microsoft OLE Controls Architecture.

    interface ScriptableSimplePartEvents : SOMObject {
      void MouseDown (in long x, in long y);       /* method definition */
    #ifdef __SOMIDL__
      implementation {
      ...
      ODevent;
      releaseorder : MouseDown;
      MouseDown : ODid
                                                 /* ODGuid of interface */
      ODGuid ="{f31fb930-2376-11d0-a5bf-0004ac3280dc}";
    ...

#### Constructor for Event Notification

The constructor for `AnObject` issues the following code to set up to receive the event notification.

                                       /* define sink and set up ODGuid */
    somThis->sink = new ODDSSink (ev, odguid);
                                          /* pointer to the sink object */
    somThis->sink->_set_object (ev, somSelf);

Elsewhere in `AnObject` is the following code.

    ODDSEventMgr *eventMgr;
    ODDSConnection *connection;
    ...
      /* request connection to event manager and add sink to sink list */
    somThis->connection->AddSink (ev,sink1,&eventMgr)

Now, `AnObject` is ready to receive events.

[ Top | Previous | Next | Contents | Index | Documentation Homepage ]