第一章 第三小節在Duilib中的事件委託

  在win32中,非常常見的各類消息,但消息的源頭是各類事件,那在duilib中,是如何實現各種事件以供sdk運行的呢?首先,它定義了一個CDelegateBase基類,如下所示:

class UILIB_API CDelegateBase     
{
public:
    CDelegateBase(void* pObject, void* pFn);
    CDelegateBase(const CDelegateBase& rhs);
    virtual ~CDelegateBase();
    bool Equals(const CDelegateBase& rhs) const;
    bool operator() (void* param);
    virtual CDelegateBase* Copy() const = 0; // add const for gcc

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

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

  它是一個純虛函數,有Invoke和Copy兩個接口,一個用於調用這個委託的實現(Invoke),另一個用於構建委託在內存中的副本時使用(Copy)。有了純虛函數的範本,接下來有兩種具體實現,一種是全局靜態函數,另一種是對象內部函數。如下所示:

class CDelegateStatic: public CDelegateBase
{
    typedef bool (*Fn)(void*);
public:
    CDelegateStatic(Fn pFn) : CDelegateBase(NULL, pFn) { } 
    CDelegateStatic(const CDelegateStatic& rhs) : CDelegateBase(rhs) { } 
    virtual CDelegateBase* Copy() const { return new CDelegateStatic(*this); }

protected:
    virtual bool Invoke(void* param)//不需要傳遞實體對象
    {
        Fn pFn = (Fn)GetFn();
        return (*pFn)(param); 
    }
};

  另一種是對象內部函數,這時候爲了應對各種不同類型對象的抽象,採用了C++的模板機制,如下所示:

template <class O, class T>//對象及對象下的函數類型
class CDelegate : public CDelegateBase
{
    typedef bool (T::* Fn)(void*);
public:
    CDelegate(O* pObj, Fn pFn) : CDelegateBase(pObj, &pFn), m_pFn(pFn) { }
    CDelegate(const CDelegate& rhs) : CDelegateBase(rhs) { m_pFn = rhs.m_pFn; } 
    virtual CDelegateBase* Copy() const { return new CDelegate(*this); }

protected:
    virtual bool Invoke(void* param)
    {
        O* pObject = (O*) GetObject();
        return (pObject->*m_pFn)(param); 
    }  

private:
    Fn m_pFn;
};

  有了兩種不同的委託對象的實現,接着就有兩種常用的全局構造,如下所示:

template <class O, class T>
CDelegate<O, T> MakeDelegate(O* pObject, bool (T::* pFn)(void*))//根據參數識別類型
{
    return CDelegate<O, T>(pObject, pFn);
}
inline CDelegateStatic MakeDelegate(bool (*pFn)(void*))
{
    return CDelegateStatic(pFn); 
}

  最後纔是委託對象真正的使用位置,事件源對象,它的內部就是委託對象的指針數組,如下所示:

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

protected:
    CStdPtrArray m_aDelegates;
};

  事件源類在Duilib中使用位置,就在CControlUI這個所有控件的基類裏,如下所示;

    public:
        CEventSource OnInit;
        CEventSource OnDestroy;
        CEventSource OnSize;
        CEventSource OnEvent;
        CEventSource OnNotify;

  分爲上述5種事件源,特別是OnNotify事件源,參數實現duilib中的自定義消息循環。具體實現查看下一小節,在duilib中的消息傳遞。


  歡迎光臨知了軟件開發網絡平臺,本公司定製開發各類軟件,主要方向爲桌面專業軟件開發和插件定製開發,桌面軟件主要包括文字圖形識別類軟件,信息管理類軟件,3D打印類軟件,視頻類軟件以及其它涉及專業的各類圖形圖像處理軟件。插件包含AE插件,AI插件,PS插件,PDF插件,3DMAX插件以及Word,Excel等Office插件開發。詳情請諮詢,微信QQ:312117271,手機:18928899728,郵箱: [email protected].
公司網址:http://www.zhiliaos.com

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章