Adding Functionality to the Composite Control

Once you have inserted any necessary controls into the composite control, the next step involves adding new functionality. This new functionality usually falls into two categories:

For the purpose and scope of this article, the remaining portion of this section focuses solely on event handling.

Declaration of IDispEventImpl Interfaces for Contained Controls

For each contained control, that you want to handle events from, you must implement an event dispatch interface by deriving from the IDispEventImpl template class. This derivation is done in the declaration of your composite control and consists of two parameters:

The following example code line, found in the base class declaration, declares an IDispEventImpl interface for a control (IDC_CIRCCTRL1), for the composite control class (CMyCompositeCtrl).

public IDispEventImpl<IDC_CIRCCTL1, CMyCompositeCtrl>

Declaration of the Event Sink Map

After declaring the dispatch event classes for each contained control, you need to add an event sink map to the composite control object. This map accomplishes two things:

The event sink map is implemented using several predefined macros:

BEGIN_SINK_MAP(CtrlName)

Declares the beginning of the event sink map for the CtrlName composite control.

SINK_ENTRY(CtrlID, DispIID, dispID, EventHandler)

Declares the handler function (EventHandler) for the specified event (dispID), of the dispatch interface DispIID, for the control identified by CtrlID.

END_SINK_MAP()

Declares the end of the event sink map for the CtrlName composite control.

The following code example (located in the .CPP file of the composite control) declares an event sink map for the CMyCompositeCtrl object. It declares two event handlers for two contained controls (IDC_CIRCCTL1 and IDC_CIRCCTL2). The Click event for both controls is handled by the OnClick_CircCtrl1 and OnClick_CircCtrl2 functions.

BEGIN_SINK_MAP(CMyCompositeCtrl)
   SINK_ENTRY(IDC_CIRCCTL1, DISPID_CLICK, OnClick_CircCtrl1)
   SINK_ENTRY(IDC_CIRCCTL2, DISPID_CLICK, OnClick_CircCtrl2)
END_SINK_MAP()

Once you have declared the event sink map, proceed to implement the event handlers for the composite control.

Declaration and Implementation of Event Handlers

In the Declaration of the Event Sink Map step, you added a new map that declared two event handlers for the two contained Circ controls. It is now time to implement these handlers. The format is as follows:

retVal __stdcall EventHandler (args)
{
   //handle event firing appropriately
}

where retVal is the return value of the event handler, EventHandler is the name of the function handler, and args is an optional listing of arguments for the event. This name must match one of the event handlers declared in the composite control’s event sink map.

The following code example defines an event handler (the Click event) for the contained control identified by IDC_CIRCCTRL1:

void __stdcall OnClick_CircCtrl1( )
{
   MessageBox("Click event fired!", "CircCtl1", MB_OK);
}

Add event handlers for the remaining entries in the event sink map of your composite control.

Initiating and Terminating Contact with Contained Controls

Before the composite control becomes fully active, each contained control, whose events you are handling, is queried for outgoing interfaces, such as an event dispatch interface. If any interfaces are found, connections are established and a reference to the outgoing interface is used to handle events from the control. This procedure is referred to as “advising the control” and is automatically done by the composite control object, using the event sink map, upon initialization of the composite control.

After the user has dismissed the dialog box, all stored references to outgoing interfaces from contained controls are cleaned up. This is referred to as “unadvising the control” and is also done automatically by the composite control.