C++通用事件支持宏

来源:互联网 发布:宿舍用品专卖店淘宝 编辑:程序博客网 时间:2024/06/01 12:04
#ifndef _EVENT_SUPPORT_H_#define _EVENT_SUPPORT_H_//#ifdef _DEBUG//#ifdef DEBUG_NEW//#define new DEBUG_NEW//#endif//#endif#include "windows.h"#include <tchar.h> #ifndef TXTRACEinline void TXTRACE(LPCTSTR, ...){}#endif ////C++通用事件支持宏//本代码是经过对Visual C++ 7.0新引入的事件机制进行研究和反编译,//接近乎相同的原理,编写而来.//优点: //任何C++类都可作为事件源和事件接收者//事件接收者的数目不限//支持编译时的类型检测//接口简单//Written by sjh//Version 1.1(2001-09)//Version 1.2(2001-10)//取消了DECLARE_EVENT_SUPPORT宏//加入DECLARE_EVENT_RECEIVER宏//自动判断事件接收对象是否可用,防止接收对象被delete后的访问从突//Version 1.3  (2002-6-12)//加入多线程支持/*使用说明:EVENT:用来在事件源中定义一个事件,事件的参数可自由定义.EVENT( 函数名, (参数定义), (相应的参数列表) ) HookEvent:为事件源添加一个事件接收者.Source.HookEvent(事件名,接收对象指针,接收函数)UnhookEvent:删除一个事件源的事件接收者.Source.UnhookEvent(事件名,接收对象指针,接收函数)RaiseEvent:触发事件源的事件.Source.RaiseEvent(事件名(事件参数))DECLARE_EVENT_RECEIVER(classname)代码示例://事件源class CSource {public://末尾的X是为了区分源与接收者,不易混淆//为CSource添加一个 void OnTimerX(void) 的事件EVENT(OnTimerX,(),());//为CSource添加一个 void OnDataX(BYTE* pBuf, DWORD nLen) 的事件EVENT(OnDataX,(BYTE* pBuf,DWORD nLen),(pBuf,nLen));public:void FireOnTimer()//内部也可以激发事件{RaiseEvent( OnTimerX() );//使用宏触发OnTimerX事件OnTimerX();//也可直接调用OnTimerX}}//接收者class CReceiver{DECLARE_EVENT_RECEIVER(CReceiver)public:void OnTimer();void OnData(BYTE* pBuf,DWORD nLen);}; ...CSource s;CReceiver r;s.HookEvent(OnTimerX, &r, &CReceiver::OnTimer);s.HookEvent(OnDataX, &r, &CReceiver::OnData);s.RaiseEvent(OnTimerX());//激发s的OnTimer事件BYTE buf[128];s.RaiseEvent(OnDataX(buf,128)); //激发s的OnData事件s.FireOnTimer(); ...s.UnhookEvent(OnDataX,&r,&CReceiver::OnData);*///p:带括号参数列表如(BYTE* pBuf,DWORD nLen),//v:带括号参数,如(pBuf,nLen)#define EVENT(f,p,v) DECLARE_EVENT(public,f,p,v)//DECLARE_EVENT定义事件//access为事件激发函数的访问类型//如果事件只允许在内部被激发,可以将access设为protected#define DECLARE_EVENT(access,f,p,v) \private:\struct _event_node_##f\{\virtual bool _NodeValid() = 0;\virtual void _Invoke p = 0;\virtual bool _IsEqual(void* pt,void* pf,bool bD) = 0;\bool bDeleted;\_event_node_##f* _pNext;\};\template<class T,class F>\struct _handler_##f: public _event_node_##f\{\T* _pThis;\F _pFun;\int _nPtrData;\bool _NodeValid ()\{\bool _b = false;\try{if(memcmp((BYTE*)_nPtrData,"################",16)==0)_b=true;}catch(...){}\return _b;\}\void _Invoke p\{\(_pThis->*_pFun)v;\}\bool _IsEqual(void* pt,void* pf,bool bD)\{\if( (void*)_pThis==pt && (pf==NULL || *((void**)&_pFun)==pf) && bD == bDeleted)\return true;\return false;\}\};\struct _nodes_##f\{\CRITICAL_SECTION m_cs;\_nodes_##f(){_pNodes=NULL;InitializeCriticalSection(&m_cs);}\~_nodes_##f(){DeleteCriticalSection(&m_cs);_event_node_##f* pNode = _pNodes;_event_node_##f* pTemp;while(pNode){pTemp=pNode->_pNext;delete pNode;pNode=pTemp;}}\_event_node_##f* _pNodes;\void _Lock(){EnterCriticalSection(&m_cs);}\void _Unlock(){LeaveCriticalSection(&m_cs);}\}_xNodes_##f;\public:\template<class T,class F>\long HookEvent_##f(T* pThis,F pFun)\{\if(pThis)\{\_xNodes_##f._Lock();\_handler_##f<T,F>* pNode = new _handler_##f<T,F>;\pNode->_pThis = pThis;\pNode->_nPtrData = (int)pThis + pThis->_xEventReceiver.nOffset;\pNode->_pFun = pFun;\pNode->_pNext = _xNodes_##f._pNodes;\pNode->bDeleted=false;\_xNodes_##f._pNodes = pNode;\_xNodes_##f._Unlock();\return 1;\}\return 0;\}\template<class T,class F>\long UnhookEvent_##f(T* pThis,F pFun)\{\_xNodes_##f._Lock();\_event_node_##f* pNode = _xNodes_##f._pNodes;\_event_node_##f* pPre = NULL;\long nResult = 0;\void* pTemp = pFun==NULL ? NULL : *((void**)&pFun);\while(pNode)\{\if(pNode->_IsEqual(pThis,pTemp,pNode->bDeleted))\{\pNode->bDeleted = true;\if(pTemp){nResult=1;break;}\}\else\{\pPre = pNode;\pNode = pNode->_pNext;\}\}\_xNodes_##f._Unlock();\return nResult;\}\void RemoveAllEvent_##f()\{\_xNodes_##f._Lock();\_event_node_##f* pNode = _xNodes_##f._pNodes;\_event_node_##f* pTemp = NULL;\while(pNode)\{\pTemp = pNode->_pNext;\delete pNode;\pNode = pTemp;\}\_xNodes_##f._pNodes = NULL;\_xNodes_##f._Unlock();\}\access:\void f p\{\_xNodes_##f._Lock();\{\_event_node_##f* pNode = _xNodes_##f._pNodes;\_event_node_##f* pPre = NULL;\while(pNode)\{\if( !pNode->bDeleted && (pNode->_NodeValid()) )\{\if (pNode->_pNext)\{ (pNode->_Invoke v);pPre = pNode; pNode = pNode->_pNext;}\else\{\_xNodes_##f._Unlock();\\{\(pNode->_Invoke v);\}\return;\}\}\else\{TXTRACE(_T("Detected died event receiver , removed ok .\n"));if(pPre){pPre->_pNext = pNode->_pNext; delete pNode; pNode = pPre->_pNext;}\else{_xNodes_##f._pNodes = pNode->_pNext; delete pNode; pNode = _xNodes_##f._pNodes?_xNodes_##f._pNodes:NULL;}\}\}\}\_xNodes_##f._Unlock();\}\#define HookEvent(e,t,f) HookEvent_##e(t,f)#define UnhookEvent(e,t,f) UnhookEvent_##e(t,f)#define RemoveAllEvent(e) RemoveAllEvent_##e()#define RaiseEvent(e) e#define DECLARE_EVENT_RECEIVER(classname) \public:\struct _event_Receiver\{\_event_Receiver(){memset(data,'#',16);nOffset=offsetof(classname,_xEventReceiver);}\~_event_Receiver(){memset(data,0,16);}\BYTE data[16];\int nOffset;\}_xEventReceiver;\#endif //_EVENT_SUPPORT_H_

原创粉丝点击