1 // SignalSlot.h: interface for the CSignalSlot class. 2 // 3 ////////////////////////////////////////////////////////////////////// 4 5 #if !defined(AFX_SIGNALSLOT_H__A686E4F2_5477_4D5E_9A1F_03883EEBAB1E__INCLUDED_) 6 #define AFX_SIGNALSLOT_H__A686E4F2_5477_4D5E_9A1F_03883EEBAB1E__INCLUDED_ 7 8 #include <Afxtempl.h> 9 10 #if _MSC_VER > 1000 11 #pragma once 12 #endif // _MSC_VER > 1000 13 14 // 15 // 16 17 //-------------------------------------------------------------------------------------------- 18 // 静态slot接口函数类型指针定义 19 typedef int (__cdecl *SS_STAIC_SLOTFUNC)(void *pSelf,int slot_F,void *pSrc,void *pDes); 20 21 // 数据结构定义 22 struct FuncItem 23 { 24 bool is_use; //是否使用 25 int signal_F; 26 int slot_F; 27 }; 28 29 struct SSItem 30 { 31 bool is_use; //是否使用 32 33 void* signal_pSelf; 34 void* slot_pSelf; 35 36 void* slot_pFunc; 37 CArray<FuncItem,FuncItem>*pFuncArray; 38 }; 39 40 //---------------------------------------------------------------------------------------------------------------------- 41 /* 42 宏定义1: 信号槽类注册 43 说明: 信号槽(接收方)类定义需要使用该宏声明 44 在类定义最开始位置声明,结尾不需要冒号。例子如下所示: 45 class CTest 46 { 47 SS_REGISTER(CTest) 48 public: 49 ... 50 } 51 52 参数: ClassName 为类名称 53 宏展开: 定义了一个公有静态函数: 54 SS_STATIC_SLOT: 函数名称 55 pSelf: 类对象指针 56 slot_F: 槽函数ID (成员函数指针转换得到) 57 pSrc: 信号发送方输入参数void通用指针 58 pDes: 返回参数内存指针(由调用方提供) 59 */ 60 #define SS_REGISTER(ClassName) 61 public: static int _SS_STATIC_SLOT_(void *pSelf,int slot_F,void *pSrc,void *pDes) 62 { 63 typedef int(ClassName::*SLOTFUNC)(void*pSrc,void*pDes=NULL); 64 SLOTFUNC slot_Func; 65 int TEMP = (int)(&slot_Func); 66 *((int*)(TEMP)) = slot_F; 67 int res = (((ClassName*)(pSelf))->*slot_Func)(pSrc,pDes); 68 return res; 69 } 70 71 // 宏定义2: 信号函数定义 72 #define SS_SIGNAL(ClassName,FuncName) 73 int FuncName(void*pSrc,void*pDes=NULL) 74 { 75 typedef int(ClassName::*SLOTFUNC)(void*,void*); 76 SLOTFUNC pfunc = &ClassName::FuncName; 77 int funcID = *((int*)((int)(&pfunc))); 78 return CSignalSlot::SignalSS(this,funcID,pSrc,pDes); 79 } 80 81 // 宏定义3: 初始化连接 82 #define SS_INITE(signalSelf,slotSelf,res) 83 *res = CSignalSlot::IniteSS(signalSelf,slotSelf,(slotSelf)->_SS_STATIC_SLOT_); 84 85 // 宏定义4: 解除对象连接 86 #define SS_CLOSE(signalSelf,slotSelf,res) 87 *res = CSignalSlot::CloseSS(signalSelf,slotSelf); 88 89 // 宏定义5: 连接功能函数 90 #define SS_CONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) 91 { 92 typedef int(signalClassName::*SIGNAL_PF)(void*,void*); 93 typedef int(slotClassName::*SLOT_PF)(void*,void*); 94 SIGNAL_PF Signal_F = &signalClassName::signalFunc; 95 SLOT_PF slot_F = &slotClassName::slotFunc; 96 *res = CSignalSlot::ConnectSS(signalSelf,*((int*)((int)(&Signal_F))),slotSelf,*((int*)((int)(&slot_F)))); 97 } 98 99 // 宏定义6: 断开功能连接 100 #define SS_DISCONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) 101 { 102 typedef int(signalClassName::*SIGNAL_PF)(void*,void*); 103 typedef int(slotClassName::*SLOT_PF)(void*,void*); 104 SIGNAL_PF Signal_F = &signalClassName::signalFunc; 105 SLOT_PF slot_F = &slotClassName::slotFunc; 106 *res = CSignalSlot::DisConnectSS(signalSelf,*((int*)((int)(&Signal_F))),slotSelf,*((int*)((int)(&slot_F)))); 107 } 108 109 // 宏定义7: 初始化连接(3与5的功能组合) 110 #define SS_INICONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res) 111 SS_INITE(signalSelf,slotSelf,res) 112 if(*res!=-1) 113 SS_CONNECT(signalClassName,signalSelf,signalFunc,slotClassName,slotSelf,slotFunc,res); 114 //------------------------------------------------------------------------------------------------------------------------------ 115 116 class CSignalSlot 117 { 118 public: 119 static int DisConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F); 120 static int CloseSS(void *signal_pSelf,void*slot_pSelf); 121 static int IniteSS(void* signal_pSelf,void* slot_pSelf,SS_STAIC_SLOTFUNC slot_pFunc); 122 static int SignalSS(void *signal_pSelf,int signal_F,void *pSrc,void *pDes=NULL); 123 static int ConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F); 124 CSignalSlot(); 125 virtual ~CSignalSlot(); 126 private: 127 static void CloseFuncArray(CArray<FuncItem,FuncItem>*pFuncArray); 128 static CArray<SSItem,SSItem>m_SSArray; 129 static int m_loopback; 130 }; 131 132 #endif // !defined(AFX_SIGNALSLOT_H__A686E4F2_5477_4D5E_9A1F_03883EEBAB1E__INCLUDED_)
1 // SignalSlot.cpp: implementation of the CSignalSlot class. 2 // 3 ////////////////////////////////////////////////////////////////////// 4 5 #include "stdafx.h" 6 #include "SignalSlot.h" 7 8 #ifdef _DEBUG 9 #undef THIS_FILE 10 static char THIS_FILE[]=__FILE__; 11 #define new DEBUG_NEW 12 #endif 13 14 ////////////////////////////////////////////////////////////////////// 15 // Construction/Destruction 16 ////////////////////////////////////////////////////////////////////// 17 CArray<SSItem,SSItem> CSignalSlot::m_SSArray; 18 int CSignalSlot::m_loopback = 0; 19 20 CSignalSlot::CSignalSlot() 21 { 22 23 } 24 25 CSignalSlot::~CSignalSlot() 26 { 27 28 } 29 30 //初始化对象连接 建立非对称连接 signal对象可以往slot对象发消息 一条单向通信链路定义为一个连接项 31 // 返回值:1 成功 0 已存在该连接 -1 添加失败 32 int CSignalSlot::IniteSS(void* signal_pSelf,void* slot_pSelf,SS_STAIC_SLOTFUNC slot_pFunc) 33 { 34 int len = CSignalSlot::m_SSArray.GetSize(); 35 SSItem tItem; 36 int nPos = -1; 37 // 扫描是否已存在该连接(同时记录下第一个位置内存项记录) 38 for(int i=0;i<len;i++) 39 { 40 tItem = CSignalSlot::m_SSArray.GetAt(i); 41 if(true==tItem.is_use) 42 { 43 if(signal_pSelf==tItem.signal_pSelf && slot_pSelf==tItem.slot_pSelf) 44 { 45 return 0; // 已存在该连接 46 } 47 } 48 else 49 { 50 if(-1==nPos) 51 { 52 nPos = i;// 记住第一个扫描到的位置用内存项位置 53 } 54 } 55 } 56 57 //增加新连接 58 if(nPos!=-1)// 占用空闲位置项 59 { 60 tItem = CSignalSlot::m_SSArray.GetAt(nPos); 61 tItem.is_use = TRUE; 62 tItem.signal_pSelf = signal_pSelf; 63 tItem.slot_pSelf = slot_pSelf; 64 tItem.slot_pFunc = slot_pFunc; 65 66 CSignalSlot::m_SSArray.SetAt(nPos,tItem); 67 return 1; 68 }else //新增位置项 69 { 70 tItem.is_use = TRUE; 71 tItem.signal_pSelf = signal_pSelf; 72 tItem.slot_pSelf = slot_pSelf; 73 tItem.slot_pFunc = slot_pFunc; 74 tItem.pFuncArray = new CArray<FuncItem,FuncItem>; 75 CSignalSlot::m_SSArray.Add(tItem); 76 return 1; 77 } 78 } 79 80 // 信号|槽连接: <signal对象+成员函数ID,slot对象+成员函数>作为一个连接项 81 // 返回值:1:成功 0:已存在该连接项 -1:添加失败 82 int CSignalSlot::ConnectSS(void* signal_pSelf,int signal_F,void* slot_pSelf,int slot_F) 83 { 84 int len = CSignalSlot::m_SSArray.GetSize(); 85 SSItem sItem; 86 FuncItem fItem; 87 int nPos = -1; 88 for (int i=0;i<len;i++) 89 { 90 sItem = CSignalSlot::m_SSArray.GetAt(i); 91 if(signal_pSelf==sItem.signal_pSelf && slot_pSelf==sItem.slot_pSelf && true==sItem.is_use) 92 { 93 int sum = sItem.pFuncArray->GetSize(); 94 for(int k=0;k<sum;k++) 95 { 96 fItem= sItem.pFuncArray->GetAt(k); 97 if(true==fItem.is_use) 98 { 99 if(signal_F==fItem.signal_F && slot_F==fItem.slot_F) 100 { 101 return 0; //已存在该连接 102 } 103 }else 104 { 105 if(-1==nPos) 106 { 107 nPos = k; 108 } 109 } 110 } 111 // 新增连接 112 fItem.is_use = true; 113 fItem.signal_F = signal_F; 114 fItem.slot_F = slot_F; 115 if(nPos!=-1) 116 { 117 sItem.pFuncArray->SetAt(nPos,fItem); 118 return 1; 119 }else 120 { 121 sItem.pFuncArray->Add(fItem); 122 return 1; 123 } 124 } 125 } 126 127 return -1; // 对象连接没有初始化 128 } 129 130 // 返回值: 调用槽的执行数目(每调用一个槽函数,返回值加1) 131 int CSignalSlot::SignalSS(void *signal_pSelf,int signal_F,void *pSrc, void *pDes) 132 { 133 int res = 0; 134 int len = CSignalSlot::m_SSArray.GetSize(); 135 for(int i=0;i<len;i++) 136 { 137 SSItem ssitem = CSignalSlot::m_SSArray.GetAt(i); 138 if(ssitem.is_use == true && signal_pSelf==ssitem.signal_pSelf) //找到对象连接 139 { 140 int sum = ssitem.pFuncArray->GetSize(); 141 for(int k=0;k<sum;k++) 142 { 143 FuncItem fitem = ssitem.pFuncArray->GetAt(k); 144 if(fitem.is_use==true && signal_F==fitem.signal_F) //找到信号|槽连接 145 { 146 //////////////////////////////////////////////////////////////////////////// 147 if(CSignalSlot::m_loopback>0) //判断是否出现回环(避免信号函数的嵌套调用) 148 { 149 CSignalSlot::m_loopback = 0; //清除嵌套计数 150 return 0; // 中断返回 151 } 152 CSignalSlot::m_loopback += 1; 153 ///////////////////////////////////////////////////////////////////////////// 154 155 SS_STAIC_SLOTFUNC tempFunc = (SS_STAIC_SLOTFUNC)ssitem.slot_pFunc; 156 tempFunc(ssitem.slot_pSelf,fitem.slot_F,pSrc,pDes); //通过静态槽接口函数发起调用 157 res+=1; 158 } 159 } 160 } 161 } 162 163 CSignalSlot::m_loopback=0; //清除嵌套计数 164 return res; 165 } 166 167 // 关闭删除对象连接(单向) 168 // 返回值:>0 成功 0 已不存在该连接 -1 删除失败 169 int CSignalSlot::CloseSS(void *signal_pSelf, void *slot_pSelf) 170 { 171 int len = CSignalSlot::m_SSArray.GetSize(); 172 SSItem sItem; 173 int res = 0; 174 for(int i=0;i<len;i++) 175 { 176 sItem = CSignalSlot::m_SSArray.GetAt(i); 177 if(false==sItem.is_use) 178 { 179 continue; 180 } 181 if(NULL==signal_pSelf) 182 { 183 if(slot_pSelf==sItem.slot_pSelf) 184 { 185 sItem.is_use = false; 186 CSignalSlot::CloseFuncArray(sItem.pFuncArray); 187 res+=1; 188 } 189 }else if(NULL==slot_pSelf) 190 { 191 if(signal_pSelf==sItem.signal_pSelf) 192 { 193 sItem.is_use = false; 194 CSignalSlot::CloseFuncArray(sItem.pFuncArray); 195 res+=1; 196 } 197 }else if(signal_pSelf==sItem.signal_pSelf && slot_pSelf==sItem.slot_pSelf) 198 { 199 sItem.is_use = false; 200 CSignalSlot::CloseFuncArray(sItem.pFuncArray); 201 res+=1; 202 break; 203 } 204 } 205 return res; 206 } 207 208 209 // 删除信号槽连接 210 // 返回值:1 成功 0 已不存在该连接 -1 删除失败 211 int CSignalSlot::DisConnectSS(void *signal_pSelf, int signal_F, void *slot_pSelf, int slot_F) 212 { 213 int len = CSignalSlot::m_SSArray.GetSize(); 214 SSItem sItem; 215 for (int i=0;i<len;i++) 216 { 217 sItem = CSignalSlot::m_SSArray.GetAt(i); 218 if(signal_pSelf==sItem.signal_pSelf && slot_pSelf==sItem.slot_pSelf &&true==sItem.is_use) 219 { 220 int sum = sItem.pFuncArray->GetSize(); 221 FuncItem item; 222 for(int k=0;k<sum;k++) 223 { 224 item = sItem.pFuncArray->GetAt(k); 225 if(signal_F==item.signal_F && slot_F==item.slot_F) 226 { 227 item = sItem.pFuncArray->GetAt(k); 228 item.is_use = false; 229 sItem.pFuncArray->SetAt(k,item); 230 return 1; //删除连接 231 } 232 } 233 } 234 } 235 236 return 0; // 对象连接没有初始化 237 } 238 239 240 void CSignalSlot::CloseFuncArray(CArray<FuncItem,FuncItem>*pFuncArray) 241 { 242 int sum = pFuncArray->GetSize(); 243 FuncItem item; 244 for(int k=0;k<sum;k++) 245 { 246 item = pFuncArray->GetAt(k); 247 item.is_use = false; 248 pFuncArray->SetAt(k,item); 249 } 250 }