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;
}
2、boot::signals2
换了visual studio,boost代码需要重新编译,改天再写吧。
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;
}