(100分)我想写一个类,vc和bcb都可以使用,事件处理方面有什么好的办法吗?
比如,我要封装socket,那么socket有一些事件,比如onreceive,在bcb中,可以直接用bcb的事件定义模式,在vc中,有vc的事件定义方式,2者不通用
我想是不是有什么办法可以使得我的代码再2者之间不需要修改就能用?
我可以通过继承我自己写的类的方法,然后重载onreceive函数来实现自定义类与整个程序逻辑的交互,这样稍微显得有点不是特别直观,我想通过事件来实现,这样比较容易使用,代码量更小一些
我有个想法,就是通过回调函数,程序里实现回调函数,然后在初始化类的时候把函数指针传入,但是具体怎么实现还没有想好。
论坛上的高手们有没有好的办法?有就贴一些代码出来参考参考哦!
多谢
[最优解释]
#include <stdio.h>
#include <windows.h>
#include "Unit.H"
void __stdcall StdAlert(Object* sender){
/* EventPtr中的 isa 就是用来判断该函数是否是类成员函数 */
MessageBox(0,sender->ClassName(),"全局函数",MB_OK);
}
class Clock : public Object{
DeclareClassName(Clock)
public:
Clock(){
this->_Tep.OnExecute += this->EventHandler(this->Alert);/* 代理成员函数 */
this->_Tep.OnExecute += this->EventHandler(StdAlert);/* 代理全局函数 */
/* this->_Tep.OnExecute -= this->EventHandler(this->Alert); */
this->_Tep.Run();
}
void __stdcall Alert(Object* sender){
/* 这里的sender其实就是线程类对象 :看类名 */
MessageBox(0,sender->ClassName(),this->ClassName(),MB_OK);
}
private:
Thread _Tep;
};
/*楼主:看你的问题我不能确定是否 你是想要在BCB和VC上都能有一个相同的
事件机制:如果不是,那就是我理解错了。
注意事项:1>代理的方法调用规则一定要为 :__stdcall
3> 根据我个人经验以及参考C#语言。不要代理virtual函数:
君不见
.NET 类库中UI控件的事件代理都不是虚函数吗?
*/
int main(int argc,char* argv[]){
Clock c;
MessageBox(0,"暂停主线程","测试",0);
return 0;
}
#define DeclareClassName(_NAME_)\
public:\
virtual char* ClassName(){\
return #_NAME_;\
}
struct EventPtr{
void*oob;
void*vpr;
void*isa;
struct EventPtr* next;
};
class Object{
DeclareClassName(Object)
public:
Object();
virtual ~Object();
protected:
EventPtr*__stdcall EventHandler(...);/* 代理类成员函数,包含 this 指针 */
EventPtr*__stdcall EventHandler(void* pvf);/* 代理全局非类成员函数,不包含 this 指针 */
};
class EventObject : public Object{
DeclareClassName(EventObject)
public:
EventObject();
virtual ~EventObject();
public:
void operator += (EventPtr* evt);
void operator -= (EventPtr* evt);
protected:
EventPtr*Head;
EventPtr*Tail;
};
class EvtDefault : public EventObject{
DeclareClassName(EvtDefault)
public:
EvtDefault();
virtual ~EvtDefault();
public:
void operator()(Object* sender);
};
/* 如果要模仿.NET UI事件 比如OnClick:
void operator()(Object* sender,EventArgs* e)
.NET 中UI事件发生时的参数都有EventArgs传递。
这里只是做个演示。你可以继承EvenObject实现
自己的事件类
class EvtUIDefault : public EventObject{
DeclareClassName(EvtUIDefault)
public:
EvtUIDefault(){};
virtual ~EventObject(){};
public:
void operator()(Object* sender,EventArgs* e){
EventPtr* _Cyc = this->Head;
while ( _Cyc != NULL ){
__asm{
movebx,_Cyc
moveax,sender
pusheax
moveax,e
pusheax
moveax,8[ebx]
cmpeax,1
JNENotOrient
moveax,0[ebx]
pusheax
NotOrient:
call4[ebx]
}
_Cyc = _Cyc->next;
}
};
};
譬如:
Class Frame{
public:
Frame(){
this->btnOk.OnClick += this->EventHandler(this->btnOk_Click);
}
void __stdcall btnOk_Click(Object* sender,EventArgs* e){\
this->btnOk.OnClick -= this->EventHandler(this->btnOk_Click);
};
private:
Button btnOk;
};
*/
class Thread : public Object{
DeclareClassName(Thread)
public:
Thread();
virtual ~Thread();
public:
static DWORD WINAPI TepCallBack(void* par);
void Run();
HANDLEGetHandle();
DWORDGetId();
protected:
HANDLEHandle;
DWORDId;
public:
EvtDefault OnExecute;
};
#include <windows.h>
#include "Unit.H"
/**
*OBJECT
*/
Object::Object(){
}
Object::~Object(){
}
EventPtr* __stdcall Object::EventHandler(void* pvf){
EventPtr* retval = new EventPtr;
memset(retval,0,sizeof(EventPtr));
__asm{
movebx,retval
mov0[ebx],dword ptr 0/* oob = NULL */
moveax,dword ptr [ebp + 0CH]
mov 4[ebx],eax/* vpr = pvf */
mov8[ebx],dword ptr 0/* isa = FALSE */
mov 12[ebx],dword ptr 0/* next = NULL */
}
return retval;
}
EventPtr* __stdcall Object::EventHandler(...){
EventPtr* retval = new EventPtr;
memset(retval,0,sizeof(EventPtr));
__asm{
movebx,retval
moveax,dword ptr [ebp + 08H]
mov0[ebx],eax/* oob = $this$ */
moveax,dword ptr [ebp + 0CH]
mov4[ebx],eax/* vpr = pvf */
mov 8[ebx],dword ptr 01H/* isa = TRUE */
mov 12[ebx],dword ptr 00H/* next = NULL */
}
return retval;
}
/**
*EventObject
*/
EventObject::EventObject(){
this->Head = 0;
this->Tail = 0;
}
EventObject::~EventObject(){
while ( NULL != this->Head ){
EventPtr* _Tmp = this->Head;
this->Head = this->Head->next;
delete _Tmp;
}
}
void EventObject::operator +=(EventPtr* evt){
if ( NULL == this->Head ){
this->Head = evt;
this->Tail = this->Head;
}
else if ( this->Tail == this->Head ){
this->Tail = evt;
this->Head->next = Tail;
}
else {
this->Tail->next = evt;
this->Tail = this->Tail->next;
}
}
void EventObject::operator -=(EventPtr* evt){
EventPtr* _Cyc = this->Head;
EventPtr* _Pre = 0;
while ( NULL != _Cyc ){
/* 未重载EventPtr的 == 操作符 !-_- */
if ( _Cyc->vpr == evt->vpr && _Cyc->oob == evt->oob && _Cyc->isa == _Cyc->isa ){
if ( _Cyc == this->Head ){
this->Head = this->Head->next;
}
else{
_Pre->next = _Cyc->next;
}
delete _Cyc;
break;
}
_Pre = _Cyc;
_Cyc = _Cyc->next;
}
}
/**
*EvtDefault
*/
EvtDefault::EvtDefault(){
}
EvtDefault::~EvtDefault(){
}
void EvtDefault::operator ()(Object* sender){
EventPtr* _Cyc = this->Head;
while ( _Cyc != NULL ){
__asm{
movebx,_Cyc
moveax,sender
pusheax
moveax,8[ebx]
cmpeax,1
JNENotOrient
moveax,0[ebx]/* $this$ 指针 */
pusheax
NotOrient:
call4[ebx]
}
_Cyc = _Cyc->next;
}
}
/**
*THREAD
*/
Thread::Thread(){
}
Thread::~Thread(){
}
HANDLE Thread::GetHandle(){
return this->Handle;
}
DWORD Thread::GetId(){
return this->Id;
}
void Thread::Run(){
this->Handle = CreateThread(NULL,0,this->TepCallBack,this,0,&(this->Id));
}
DWORD WINAPI Thread::TepCallBack(void* par){
Thread* _THIS_ = (Thread*)par;
_THIS_->OnExecute(_THIS_);
return 0;
}
[其他解释]
我靠,还内存泄露了。楼主自己小心些。
void EventObject::operator -=(EventPtr* evt){
EventPtr* _Cyc = this->Head;
EventPtr* _Pre = 0;
while ( NULL != _Cyc ){
/* 未重载EventPtr的 == 操作符 !-_- */
if ( _Cyc->vpr == evt->vpr && _Cyc->oob == evt->oob && _Cyc->isa == _Cyc->isa ){
if ( _Cyc == this->Head ){
this->Head = this->Head->next;
}
else{
_Pre->next = _Cyc->next;
}
delete _Cyc;
break;
}
_Pre = _Cyc;
_Cyc = _Cyc->next;
}
delete evt;/** !!!!!!!!!!!!!! **/
}
struct CCppSocket{
signal<void (const void*, int)> sig; //
template<typename Func> void setReceiveHandler(Func f){ //连接事件
sig.connect(f);
}
...
{
//触发"OnReceive"事件
sig(buf, count);
}
...
};
void MyOnReceive(const void*, int) //可以连接直接函数
{
...
}
struct CMyClass{
void OnReceive(const void*, int) //也可以连接成员函数
{
...
}
};
void MyOnReceive2(const void*, int, time) //或者更多
{
...
}
CCppSocket socket;
socket.setReceiveHander( MyOnReceive );
CMyClass myobj;
socket.setReceiveHander( Bind(&CMyClass::OnReceive, &myobj, _1, _2) );
socket.setReceiveHandler( Bind(MyOnReceive2, _1, _2, now()) );