Figure 2   Two Outgoing Interfaces

 [
     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);
     }
 }