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

1CDelegate类:成员主要包含:函数的指针、函数所属对象的指针、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 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;

};

2CEventSource类:主要成员变量:事件代理指针数组、重载的各个操作符;注意: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; //事件代理指针数组

};

 

3MakeDelegate宏用于生成一个CDelegate对象。

template

CDelegate MakeDelegate(O* pObject, bool (T::* pFn)(void*))

{

    return CDelegate(pObject, pFn);

}

 

4、实例:

voidCFrameWindowWnd::OnPrepare()

{

      CButtonUI* pBtn = static_cast(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对象,在PaintManagerMessageHandler消息处理函数中调用,在此不用显式调用CEventSourceDuilib中的所有控件可以像上面那样用。

 

自定义的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;

}

}

你可能感兴趣的:(Duilib界面库,Duilib界面库)