Normally, the host connects event sources and sinks when it loads the designer. To improve performance, a designer can delay the event connections until they are actually needed. To use this feature, the designer must do the following:
The designer sets the DESIGNERFEATURE_DELAYEVENTSINKING flag in the registry to enable delayed event sinking. At run time, the host checks for this flag; if it is not set, the host connects event sources and sinks immediately, using the standard event mechanism. If the flag is set, the host delays event sinking.
If the designer delays event sinking, it must connect its own events (the events of the top-level designer object) in addition to those of its subobjects.
After creating the run-time object, the host calls the designer's IActiveDesignerRuntime::SetSite method, passing a pointer to an IActiveDesignerRuntimeSite interface. This interface is implemented on the site through which the designer's event sources and sinks will be connected.
SetSite is the only method in the IActiveDesignerRuntime interface. It is declared as follows:
HRESULT SetSite (
IActiveDesignerRuntimeSite *pSite
);
The host calls this method again when it destroys the run-time object, passing a NULL pointer. Upon destroying the run-time object, the host calls IActiveDesignerRuntime::SetSite, passing a NULL pointer. In response, the designer should call IConnectionPoint::Unadvise for any event sinks (its own and those of its subobjects) it has connected and release the m_pRuntimeSite
pointer.
In the following example, if the host passes a run-time site pointer that is not NULL, the designer saves the pointer in a global variable, m_pRuntimeSite
, and adds a reference to the object. If the pointer is NULL, the designer unadvises all event sinks and releases the reference.
STDMETHODIMP CMyDesignerRuntime::SetSite
(
IActiveDesignerRuntimeSite *pSite
)
{
CObjSite* pObjSite = m_pObjList;
hresult hr = S_OK;
if(pSite == NULL){
//Unadvise the sinks of our subobjects.
while(pObjSite){
hr = pObjSite->UnadviseSubSinks();
RETURN_ON_FAILURE(hr);
pObjSite = pObjSite->m_pNext;
}
//Unadvise the designer's top-level sink.
UnadviseDesignerSink();
m_pRuntimeSite->Release()
}
else {
//Save the site pointer and add a reference to it.
m_pRuntimeSite = pSite;
m_pRuntimeSite->AddRef();
}
return hr;
}
The designer uses the saved site pointer (m
_pRuntimeSite)
to connect event sources and sinks.
When the ActiveX designer is ready to fire events for itself or a subobject, it must obtain a pointer to the specific event sink interface it requires. To do so, it calls the host's IActiveDesignerRuntimeSite::GetAdviseSink method, passing the Member ID (MemID) of the object that is the source of events. A designer that implements delayed event handling must connect its own events in the same way that it connects events from its subobjects. To get a pointer through which to connect the designer's own events, specify MEMBERID_NIL.
GetAdviseSink returns a pointer to the IUnknown interface for the event sink object that corresponds to the specified source.
The designer must then call QueryInterface with the returned IUnknown pointer to get the connection point container interface for the object. Once it has a pointer to the event sink interface, it can fire events.
In the sample code that follows, the designer hooks up a sink to the event source of one of its subobjects (such as an ActiveX control). Assume that m_pRuntimeSite
is the site pointer passed to SetSite, and that the following additional declarations have been made:
HRESULT hr = S_OK;
IUnknown* punkEventSink = NULL;
DISPID memidMySubobject;
IUnknown* punkICPC;
IConnectionPoint* pICP;
DWORD dwcookie;
IUnknown * punkMySubObject;
The designer first gets a pointer to the event sink associated with a specific object, then queries the subobject for its IConnectionPointContainer interface, as follows (error handling omitted for brevity):
hr = m_pRuntimeSite->GetAdviseSink(memidMySubobject,&punkEventSink);
hr = punkMySubObject->QueryInterface(IID_IConnectionPointContainer,
&punkICPC);
Next, use the FindConnectionPoint method to get the IConnectionPoint interface for the specific object. Then call the Advise method to set up the connection between source and sink:
hr = (IConnectionPointContainer*)
punkICPC->FindConnectionPoint(IID_IMySubobjectEvents, &pICP);
pICP->Advise(punkEventSink, &dwCookie)
After it has connected the source and sink, the subobject can fire events in the usual way, as described in the COM Programmer's Reference in the ActiveX and Object Services section of the Platform Software Development Kit (SDK).