1、duilib中的CEventSource。以下代码摘自duilib,并且有一点改动。
delegate.h
#include <atlbase.h> class CDelegateBase { public: CDelegateBase(void* pObject, void* pFn); CDelegateBase(const CDelegateBase& rhs); virtual ~CDelegateBase(); bool Equals(const CDelegateBase& rhs) const; bool operator() (void* param); virtual CDelegateBase* Copy() = 0; protected: void* GetFn(); void* GetObject(); virtual bool Invoke(void* param) = 0; private: void* m_pObject; void* m_pFn; }; class CDelegateStatic : public CDelegateBase { typedef bool(*Fn)(void*); public: CDelegateStatic(Fn pFn) : CDelegateBase(NULL, pFn) { } CDelegateStatic(const CDelegateStatic& rhs) : CDelegateBase(rhs) { } virtual CDelegateBase* Copy() { return new CDelegateStatic(*this); } protected: virtual bool Invoke(void* param) { Fn pFn = (Fn)GetFn(); return (*pFn)(param); } }; template <class O, class T> class CDelegate : public CDelegateBase { typedef bool (T::* Fn)(void*); public: CDelegate(O* pObj, Fn pFn) : CDelegateBase(pObj, &pFn), m_pFn(pFn) { } CDelegate(const CDelegate& rhs) : CDelegateBase(rhs) { m_pFn = rhs.m_pFn; } virtual CDelegateBase* Copy() { return new CDelegate(*this); } protected: virtual bool Invoke(void* param) { O* pObject = (O*)GetObject(); return (pObject->*m_pFn)(param); } private: Fn m_pFn; }; template <class O, class T> CDelegate<O, T> MakeDelegate(O* pObject, bool (T::* pFn)(void*)) { return CDelegate<O, T>(pObject, pFn); } inline CDelegateStatic MakeDelegate(bool(*pFn)(void*)) { return CDelegateStatic(pFn); } class CEventSource { typedef bool(*FnType)(void*); public: ~CEventSource(); operator bool(); void operator+= (CDelegateBase& d); void operator+= (FnType pFn); void operator-= (CDelegateBase& d); void operator-= (FnType pFn); bool operator() (void* param); protected: CSimpleArray<LPVOID> m_aDelegates; };delegate.cpp
CDelegateBase::CDelegateBase(void* pObject, void* pFn) { m_pObject = pObject; m_pFn = pFn; } CDelegateBase::CDelegateBase(const CDelegateBase& rhs) { m_pObject = rhs.m_pObject; m_pFn = rhs.m_pFn; } CDelegateBase::~CDelegateBase() { } bool CDelegateBase::Equals(const CDelegateBase& rhs) const { return m_pObject == rhs.m_pObject && m_pFn == rhs.m_pFn; } bool CDelegateBase::operator() (void* param) { return Invoke(param); } void* CDelegateBase::GetFn() { return m_pFn; } void* CDelegateBase::GetObject() { return m_pObject; } CEventSource::~CEventSource() { for (int i = 0; i < m_aDelegates.GetSize(); i++) { CDelegateBase* pObject = static_cast<CDelegateBase*>(m_aDelegates[i]); if (pObject) delete pObject; } } CEventSource::operator bool() { return m_aDelegates.GetSize() > 0; } void CEventSource::operator+= (CDelegateBase& d) { for (int i = 0; i < m_aDelegates.GetSize(); i++) { CDelegateBase* pObject = static_cast<CDelegateBase*>(m_aDelegates[i]); if (pObject && pObject->Equals(d)) return; } m_aDelegates.Add(d.Copy()); } void CEventSource::operator+= (FnType pFn) { (*this) += MakeDelegate(pFn); } void CEventSource::operator-= (CDelegateBase& d) { for (int i = 0; i < m_aDelegates.GetSize(); i++) { CDelegateBase* pObject = static_cast<CDelegateBase*>(m_aDelegates[i]); if (pObject && pObject->Equals(d)) { delete pObject; m_aDelegates.RemoveAt(i); return; } } } void CEventSource::operator-= (FnType pFn) { (*this) -= MakeDelegate(pFn); } bool CEventSource::operator() (void* param) { for (int i = 0; i < m_aDelegates.GetSize(); i++) { CDelegateBase* pObject = static_cast<CDelegateBase*>(m_aDelegates[i]); if (pObject && !(*pObject)(param)) return false; } return true; }用法示例:
class ClsA { public: CEventSource EventA; void DoA() { EventA(NULL); } }; bool HandleA(void* p) { ATLTRACE(_T(__FUNCTION__)); return true; } class ClsB { public: bool HandleA(void* p) { ATLTRACE(_T(__FUNCTION__)); return true; } }; int _tmain(int argc, _TCHAR* argv[]) { ClsA a; ClsB b; a.EventA += MakeDelegate(&HandleA); a.EventA += MakeDelegate(&b, &ClsB::HandleA); a.DoA(); a.EventA -= MakeDelegate(&HandleA); a.EventA -= MakeDelegate(&b, &ClsB::HandleA); return 0; }
3、msvc支持的__event
[event_source(native)] class ClsA { public: __event bool EventA(int a, long b); void DoA() { __raise EventA(20, 100); } }; [event_receiver(native)] class ClsB { public: bool OnEventA(int a, long b) { ATLTRACE(_T(__FUNCTION__)); return true; } }; int _tmain(int argc, _TCHAR* argv[]) { ClsA a; ClsB b; __hook(&ClsA::EventA, &a, &ClsB::OnEventA, &b); a.DoA(); __unhook(&ClsA::EventA, &a, &ClsB::OnEventA, &b); return 0; }