您的位置:首页 > 产品设计 > UI/UE

Duilib中CEventSource及CDelegate(事件委托)的简单分析

2013-08-02 17:42 302 查看

Duilib中CEventSource及CDelegate(事件委托)的简单分析

分类:
Duilib界面库 2013-04-16 18:24
167人阅读 评论(0)收藏
举报
Duilib界面库

1、CDelegate类:成员主要包含:函数的指针、函数所属对象的指针、invoke函数和其他方便使用的重载操作符;其实就是保存了一个对象指针和它的一个成员函数的指针,invoke函数用于调用对象的成员函数。
class CDelegateBase
{
public:
CDelegateBase(void*pObject, void* pFn);
CDelegateBase(constCDelegateBase& rhs);
virtual~CDelegateBase();
bool Equals(constCDelegateBase& rhs) const;
bool operator()(void* param);
virtualCDelegateBase* Copy() const = 0; // add const for gcc

protected:
void* GetFn();
void* GetObject();
virtualbool Invoke(void* param) = 0;

private:
void* m_pObject;
void* m_pFn;
};

template <class O, class T>
class CDelegate : public CDelegateBase
{
typedefbool (T::* Fn)(void*);
public:
CDelegate(O*pObj, Fn pFn) : CDelegateBase(pObj, &pFn), m_pFn(pFn) { }
CDelegate(constCDelegate& rhs) : CDelegateBase(rhs) { m_pFn = rhs.m_pFn; }
virtualCDelegateBase* Copy() const { return new CDelegate(*this); }

protected:
virtualbool Invoke(void* param)
{
O* pObject= (O*) GetObject();
return(pObject->*m_pFn)(param);
}
private:
Fn m_pFn;
};
2、CEventSource类:主要成员变量:事件代理指针数组、重载的各个操作符;注意:CEventSource的+=操作符,将事件代理CDelegate对象保到其成员变量中;在需要的时候可以调用代理中的函数(通过invoke函数),例如:点击按钮时,见下面的实例。
classUILIB_API CEventSource
{

typedef bool (*FnType)(void*);
public:
~CEventSource();
void operator+= (const CDelegateBase& d);// add const for gcc
void operator+= (FnType pFn);
void operator-= (const CDelegateBase& d);
bool operator() (void* param);

protected:
CStdPtrArray m_aDelegates; //事件代理指针数组
};

3、MakeDelegate宏用于生成一个CDelegate对象。
template<class O, class T>
CDelegate<O,T> MakeDelegate(O* pObject, bool (T::* pFn)(void*))
{
return CDelegate<O, T>(pObject, pFn);
}

4、实例:
voidCFrameWindowWnd::OnPrepare()
{
CButtonUI* pBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("ButtonTest")));//获取控件
if( pBtn)
pBtn->OnNotify += MakeDelegate(this, &CFrameWindowWnd::OnBtnTest); //
}
boolCFrameWindowWnd::OnBtnTest(void* param)
{
TNotifyUI * msg =( TNotifyUI*) param;
if (msg.sType == DUI_MSGTYPE_CLICK)
{
//do something
}

Return true;
}

注意!上面OnNotify为在Control里面定义的CEventSource对象,在PaintManager的MessageHandler消息处理函数中调用,在此不用显式调用CEventSource;Duilib中的所有控件可以像上面那样用。

自定义的CEventSource需要在适当的地方自己调用,调用方法很简单,使用重载的 ()操作符。
//自定义CEventSource
CEventSourcecustomEvent;
还要像上面那样初始化(+=操作),在此省略。

voidCFrameWindowWnd::Notify( TNotifyUI& msg )
{
if (msg.sType == DUI_MSGTYPE_CLICK)
{
if (msg.pSender->GetName()== _T("ButtonTest "))
{
// 在此自己调用
customEvent((void*)msg);//参数如果不需要可以设为NULL
}
}
}

5、在使用时,可以在A类中定义CEventSource eA; eA可以绑定到B类中的函数进行处理;相当于在A中调用了B的函数。
简单举例:
A {
public:
CEventSource eA;
}

B{
Protected:
Am_a;
VoidInit()
{
m_a+= MakeDelegate (this, B::Fb);
}

boolFb(void *)
{
Returntrue;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: