首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ Builder >

(100分)小弟我想写一个类,vc和bcb都可以使用,事件处理方面有什么好的办法吗

2012-12-17 
(100分)我想写一个类,vc和bcb都可以使用,事件处理方面有什么好的办法吗?比如,我要封装socket,那么socket有

(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;
}

[其他解释]
这样子 
我建议你做成dll;
这样不仅CB、VC能用,其他的delphi、C# 等也能用
[其他解释]
既然要VC和BCB通用,我的建议是用纯SDK写这个类,至于和界面的数据交互,用回调函数也行,用自定义消息也行。
[其他解释]
做成COM标准的DLL才是王道。
[其他解释]
做成dll,不要用mfc或者vcl,用标准的c调用规范。
[其他解释]
做成标准的dll,事件怎么处理呢?最好有例子能参考就好了,光说说比较不容易理解
[其他解释]
做个函数 在你现成的事件里 去调用这个dll里的函数
CB做的DLL,VC去调用 ,之前给别人做的例子
http://blog.csdn.net/zhouzhangkui/archive/2010/08/16/5815797.aspx
[其他解释]

不知道楼主要的是不是这种事件效果..
[其他解释]
如果说你只是封装socket句柄的话,我实现的这种事件机制可以帮上忙.
[其他解释]
引用:
如果说你只是封装socket句柄的话,我实现的这种事件机制可以帮上忙.


可否把代码多贴一些?多谢!
[其他解释]
来关注下
[其他解释]
[img=http://hi.csdn.net/space-73253-do-album-picid-631886-goto-down.html][/img]
[其他解释]

#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;
}


[其他解释]
发了两张图片都不成功,无奈只好发源码了。13楼,15楼,16楼。


[其他解释]
我靠,还内存泄露了。楼主自己小心些。

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;/** !!!!!!!!!!!!!! **/
}

[其他解释]
_嚣张的马甲_禁止连续三次回复
[其他解释]
事件机制  老妖不是说了吗, 回调函数啊, 
来来回回玩函数指针.
[其他解释]
太感谢了,我就是想实现bcb和vc上有相同的事件机制,楼主代码我先研究下
[其他解释]
引用:
发了两张图片都不成功,无奈只好发源码了。13楼,15楼,16楼。


。。 有没有不加汇编的代码呢 ?
[其他解释]
引用:
_嚣张的马甲_禁止连续三次回复

???
[其他解释]
为什么不用signal呢?比如Boost.Signal:

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()) );


上面的代码要在BCB2009以后才能编译通过,事实上你也可以用vector<boost::function3(void,const void*,int) >来代码signal
[其他解释]
引用:
引用:
发了两张图片都不成功,无奈只好发源码了。13楼,15楼,16楼。


。。 有没有不加汇编的代码呢 ?


就我这几行汇编简单的跟白话文似的,不难理解。而且内嵌汇编处理起来方便。
------其他解决方案--------------------


楼主要赖账,怎么不结贴!我可是三更半夜出茅厕,出于回帖热情临时在电脑上完整的重新敲了一遍代码啊!原本的库代码都在公司.靠,就这么太监了.
[其他解释]
做成activex通用性好。
[其他解释]

得这么多分有愧.

楼主,不知代码对你有用不?
[其他解释]
呵呵,不是要赖账,是这几天有点别的事情,好几天没上来了


[其他解释]
null
[其他解释]
要回复才能看里面的东西啊

热点排行