[
uuid(1A6BFAD2-6412-11D3-805E-90DF64000000),
version(1.0),
helpstring("AnATLDLLSvr 1.0 Type Library")
]
library ANATLDLLSVRLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
[
uuid(174B9DAF-62D1-11D3-805D-06EA09000000),
]
dispinterface _IControlWithMultipleEventsEvents
{
properties:
methods:
[id(1)]void Event1();
[id(2)]void Event2();
};
[
uuid(174B9DAF-FFFF-11D3-805D-06EA09000000),
]
dispinterface _IControlWithMultipleEventsMoreEvents
{
properties:
methods:
[id(1)]void Event3();
[id(2)]void Event4();
};
[
uuid(174B9DAE-62D1-11D3-805D-06EA09000000),
]
coclass ControlWithMultipleEventSets
{
[default] interface IControlWithMultipleEventSets;
[default, source] dispinterface _IControlWithMultipleEventsEvents;
[source] dispinterface _IControlWithMultipleEventsMoreEvents;
};
};
Figure 3 Implementing the Event Sinks
class EventSink1:
public IDispEventImpl<1, EventSink1, &DIID__IControlWithMultipleEventsEvents,
&LIBID_ANATLDLLSVRLib, 1, 0>
{
public:
BEGIN_SINK_MAP(EventSink1)
SINK_ENTRY_EX(1, DIID__IControlWithMultipleEventsEvents,
1, OnEvent1)
SINK_ENTRY_EX(1, DIID__IControlWithMultipleEventsEvents,
2, OnEvent2)
END_SINK_MAP()
void __stdcall OnEvent1()
{
OutputDebugString("Firing Event 1\n");
}
void __stdcall OnEvent2()
{
OutputDebugString("Firing Event 2\n");
}
};
class EventSink2:
public IDispEventImpl<1, EventSink2,
&DIID__IControlWithMultipleEventsMoreEvents,
&LIBID_ANATLDLLSVRLib, 1, 0>
{
public:
BEGIN_SINK_MAP(EventSink2)
SINK_ENTRY_EX(1, DIID__IControlWithMultipleEventsMoreEvents,
1, OnEvent3)
SINK_ENTRY_EX(1, DIID__IControlWithMultipleEventsMoreEvents,
2, OnEvent4)
END_SINK_MAP()
void __stdcall OnEvent3()
{
OutputDebugString("Firing Event 3\n");
}
void __stdcall OnEvent4()
{
OutputDebugString("Firing Event 4\n");
}
};
Figure 4 Using Event Sinks in an ATL-based App
class CMainWindow : public CWindowImpl<CMainWindow>
{
protected:
CAxWindow m_HostWindow;
EventSink1 m_EventSink1;
EventSink2 m_EventSink2;
IUnknown* m_pUnk;
BEGIN_MSG_MAP(CMainWindow)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
COMMAND_ID_HANDLER(ID_FILE_EXIT, OnFileExit)
END_MSG_MAP()
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
RECT r;
GetClientRect(&r);
HWND hWnd = NULL;
hWnd = m_HostWindow.Create(m_hWnd, r,
_TEXT("{174B9DAE-62D1-11D3-805D-06EA09000000}"),
WS_CHILD | WS_VISIBLE);
HRESULT hr;
hr = m_HostWindow.QueryControl(IID_IUnknown, (void**)&m_pUnk);
if(SUCCEEDED(hr))
{
hr = m_EventSink1.DispEventAdvise(m_pUnk);
hr = m_EventSink2.DispEventAdvise(m_pUnk);
}
bHandled = TRUE;
return 0;
}
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
m_EventSink1.DispEventUnadvise(m_pUnk);
m_EventSink2.DispEventUnadvise(m_pUnk);
if(m_pUnk)
{
m_pUnk->Release();
}
PostQuitMessage(0);
bHandled = TRUE;
return 0;
}
// more handlers, etc.
};
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
{
HRESULT hRes = CoInitialize(NULL);
_ASSERTE(SUCCEEDED(hRes));
_Module.Init(NULL, hInstance, &LIBID_ATLUSEMULTIPLEEVENTSETSLib);
_Module.dwThreadID = GetCurrentThreadId();
// Initialize the ATL control containment...
// Create the Window...
AtlAxWinInit();
RECT rcPos = { CW_USEDEFAULT };
CMainWindow wndMain;
wndMain.Create(GetDesktopWindow(), rcPos, _T("Hi"),
WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, NULL);
wndMain.ShowWindow(SW_SHOWNORMAL);
wndMain.UpdateWindow();
int nRet = 0;
BOOL bRun = TRUE;
if (bRun)
{
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
}
_Module.Term();
CoUninitialize();
return nRet;
}
Figure 5 Disconnecting an Event Sink
void CMFCUsemultipleeventsetsDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
// TODO: Add extra initialization here
IUnknown* pUnk = NULL;
pUnk = this->GetControlUnknown();
if(pUnk)
{
AfxConnectionUnadvise(pUnk,
DIID__IControlWithMultipleEventsMoreEvents,
m_pUnkEventSink, TRUE, m_dwCookie);
}
}