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.
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>
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.
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.
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.
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.