为了携带更多参数在线程间调用过程,我最近模仿windows的MFC命令机制,写了一个简单的事件机制
分为事件消息接收器,事件转发器,事件处理器等。主要代码如下
1. JrEvent.h
#define EVENT_MSG WM_USER + 0X100
typedef UINT EVENT_CODE;
typedef HANDLE HEVENT;
struct EventParam
{
void* PInParamBuf;//输入
void* pOutParamBuf; //输出
bool bSuccess;
bool bSyncCall;
HEVENT hNotifyEvent;//调用完成通知事件(用于异步调用)
bool bCalleeReleaseMem; //指示是否由被调用者释放内存,具体是否释放,可综合设计,由具体的事件处理器考虑
EventParam()
{
PInParamBuf = NULL;
pOutParamBuf = NULL;
bSuccess = false;
bSyncCall = true;
hNotifyEvent = NULL;
bCalleeReleaseMem = false;
};
};
typedef EventParam *PEventParam;
class CJrEventSink;
typedef void (CJrEventSink::*JMC_EVENTFUNC)(PEventParam);
struct JMC_EVENTMAP_ENTRY
{
UINT nEventCode;
JMC_EVENTFUNC lpEventFunc;
};
struct JMC_EVENTMAP
{
const JMC_EVENTMAP* (PASCAL* pfnGetBaseMap)();
const JMC_EVENTMAP_ENTRY* lpEntries;
};
#define DECLARE_JMC_EVENT_MAP() /
private: /
static const JMC_EVENTMAP_ENTRY _eventEntries[]; /
protected: /
static const JMC_EVENTMAP eventMap; /
static const JMC_EVENTMAP* PASCAL GetThisEventMap(); /
virtual const JMC_EVENTMAP* GetEventMap() const;
#define BEGIN_JMC_EVENT_MAP(theClass, baseClass) /
const JMC_EVENTMAP* PASCAL theClass::GetThisEventMap()/
{ return &theClass::eventMap; } /
const JMC_EVENTMAP* theClass::GetEventMap() const /
{ return &eventMap; } /
const JMC_EVENTMAP theClass::eventMap = /
{ &(baseClass::GetThisEventMap), theClass::_eventEntries,};/
const JMC_EVENTMAP_ENTRY theClass::_eventEntries[] = /
{
#define END_JMC_EVENT_MAP() /
{0, NULL }, /
};
#define ON_JMC_EVENT(id, memberFxn)/
{ (EVENT_CODE)id, static_cast<JMC_EVENTFUNC>(memberFxn)},
2. receicver, router.h
class JRTL_API CJrEventRouterWnd : public CWnd
{
DECLARE_DYNAMIC(CJrEventRouterWnd)
public:
CJrEventRouterWnd(){}
virtual ~CJrEventRouterWnd(){}
virtual void CreateEventSinks() = 0;
std::list<CJrEventSink*> m_sinks;
protected:
DECLARE_MESSAGE_MAP();
afx_msg LRESULT OnEventMsg(WPARAM wp_, LPARAM lp_);
};
class JRTL_API CJrEventReceiver
{
public:
CJrEventReceiver(void);
virtual ~CJrEventReceiver(void);
LRESULT SynEventProcess(EVENT_CODE nCode_, PEventParam pParam_);
BOOL AsynEventProcess(EVENT_CODE nCode_, PEventParam pParam_);
protected:
virtual CJrEventRouterWnd* GetEventRouterWnd() = 0;
};
3. receiver, router.cpp
IMPLEMENT_DYNAMIC(CJrEventRouterWnd, CWnd)
BEGIN_MESSAGE_MAP(CJrEventRouterWnd, CWnd)
ON_MESSAGE(EVENT_MSG, OnEventMsg)
END_MESSAGE_MAP()
LRESULT CJrEventRouterWnd::OnEventMsg(WPARAM wp_, LPARAM lp_)
{
bool bFind = false;
PEventParam pEP = (PEventParam)lp_;
for (std::list<CJrEventSink*>::iterator _it = m_sinks.begin(); _it != m_sinks.end(); ++_it)
{
if ((*_it)->OnEventMsg((EVENT_CODE)wp_, pEP))
{
if (pEP->hNotifyEvent)
{
//...
}
bFind = true;
}
}
if (pEP->bCalleeReleaseMem)
{
//...
}
return bFind ? 0; -1;
}
CJrEventReceiver::CJrEventReceiver(void)
{
}
CJrEventReceiver::~CJrEventReceiver(void)
{
}
LRESULT CJrEventReceiver::SynEventProcess(EVENT_CODE nCode_, PEventParam pParam_)
{
CJrEventRouterWnd* _pRouter = GetEventRouterWnd();
if (!_pRouter || !_pRouter->GetSafeHwnd())
{
if (pParam->hNotifyEvent)
{
//...
}
if (pParam->bCalleeReleaseMem)
{
//...
}
return -1;
}
return _pRouter->SendMessage(EVENT_MSG, nCode_, (LPARAM)pParam_);
}
BOOL CJrEventReceiver::AsynEventProcess(EVENT_CODE nCode_, PEventParam pParam_)
{
CJrEventRouterWnd* _pRouter = GetEventRouterWnd();
if (!_pRouter || !_pRouter->GetSafeHwnd())
{
if (pParam->hNotifyEvent)
{
//...
}
if (bCalleeReleaseMem)
{
//...
}
return FALSE;
}
return _pRouter->PostMessage(EVENT_MSG, nCode_, (LPARAM)pParam_);
}
4. sink基类.h
#include "JRtl.h"
#include "JrEvent.h"
class JRTL_API CJrEventSink
{
public:
CJrEventSink(void);
virtual ~CJrEventSink(void);
virtual BOOL OnEventMsg(EVENT_CODE nEventCode_, EventParam* pEventParam_);
DECLARE_JMC_EVENT_MAP()
};
5. sink基类.cpp
const JMC_EVENTMAP CJrEventSink::eventMap =
{
NULL, &CJrEventSink::_eventEntries[0],
};
const JMC_EVENTMAP_ENTRY CJrEventSink::_eventEntries[] =
{
{ 0, NULL } // nothing here
};
CJrEventSink::CJrEventSink(void)
{
}
CJrEventSink::~CJrEventSink(void)
{
}
const JMC_EVENTMAP* CJrEventSink::GetEventMap() const
{
return &eventMap;
}
const JMC_EVENTMAP* PASCAL CJrEventSink::GetThisEventMap()
{
return &eventMap;
}
BOOL CJrEventSink::OnEventMsg(EVENT_CODE nEventCode_, EventParam* pEventParam_)
{
for (const JMC_EVENTMAP* pMap = GetEventMap(); pMap != NULL; pMap = (*pMap->pfnGetBaseMap)())
{
const JMC_EVENTMAP_ENTRY* pEntry = pMap->lpEntries;
while (pEntry->nEventCode)
{
if (nEventCode_ == pEntry->nEventCode)
{
if (!pEntry->lpEventFunc)
{
ASSERT(FALSE);
return FALSE;
}
(this->*(pEntry->lpEventFunc))(pEventParam_); //???
return TRUE;
}
pEntry++;
}
if (NULL == (pMap->pfnGetBaseMap))
return FALSE;
}
return FALSE;
}
6. 具体sink类
protected:
DECLARE_JMC_EVENT_MAP()
void OnMyEvent(PEventParam pParam_);
};
//.CPP
BEGIN_JMC_EVENT_MAP(CMySink, CJrEventSink)
ON_JMC_EVENT(EVENT_XXX, &CMySink::OnMyEvent)
END_JMC_EVENT_MAP()
CMySink::CMySink(void)
{
}
CMySink::~CMySink(void)
{
}
void CMySink::OnMyEvent(PEventParam pParam_)
{
TRACE(_T("onMYEVENT Not Implement/n"));
}