向事件系統注冊事件的流程

首先客戶調用EventSet::subscribeEvent方法,傳入的參數為參數名和回調方法.實際上第二個參數的傳入過程中有一個創建臨時變量SubscriberSlot,其實質上是一個綁定的回調函數(函數指針,成員函數指針,仿函數等)的過程,在圖中并沒有表現出來.
接著, EventSet::subscribeEvent方法中會首先調用EventSet::getEventObject方法獲取事件,在EventSet::getEventObject中,如果沒有查找到事件,則會創建之.當獲取到事件之后, EventSet::subscribeEvent會調用Event::subscribe方法.
在Event::subscribe方法中,會先創建一個BoundSlot的實例,而在BoundSlot的構造方法當中,它會創建一個SubscriberSlot的實例,并將EventSet::subscribeEvent傳入的第二個參數保存到SubscriberSlot的實例里面去.
事件系統響應事件的流程

首先要說明的是,客戶首先必須要從EventSet繼承下來才行,CEGUI里面有System,Renderer,Window,MouseCursor以及GlobalEventSet.其中GlobalEventSet是單件,系統創建以后就要創建它,EventSet對它是有依賴的,由上圖就可以得知.
EventSet是什么呢?EventSet它是一個事件的容器,它是一個事件處理中心.可以說是事件系統的接口.
當客戶向事件系統發送了一個事件之后,即是執行EventSet::fireEvent. EventSet::fireEvent首先執行了GlobalEventSet:: fireEvent,而后才執行其自身的一個方法EventSet::fireEvent_impl,該方法才是真正進行事件處理的方法,由該方法的后綴impl即可得知了. EventSet::fireEvent_impl先是執行了getEventObject方法查找到事件,然后調用該事件Event的仿函數,該仿函數調用BoundSlot:: m_pSubscriber的仿函數,它最終將會調用到SlotFunctorBase接口的實現的仿函數,而這個仿函數內部調用到的是真正的回調方法.
SlotFunctorBase這一塊實際上是Gof模式之一的適配器模式(adapter pattern)的應用.
測試代碼:
using namespace CEGUI;


/**//// 事件參數
class TestEventArgs : public EventArgs


{
public:

TestEventArgs(const int& _n) : n(_n)
{}

int n;
};


/**//// 事件
class testEvent : public EventSet


{
public:

testEvent()
{}

static const String EventNamespace;
static const String EventTest;

void injectTest(int n)

{
TestEventArgs e(n);
fireEvent(EventTest, e, EventNamespace);
}
};
const String testEvent::EventTest("test");
const String testEvent::EventNamespace("testEvent");


/**//// 客戶
class testClient


{
public:
testClient()

{
Init();
}

void Init()

{
new GlobalEventSet();
mEvent.subscribeEvent(testEvent::EventTest, Event::Subscriber(&testClient::handleTest, this) );
}

bool handleTest(const CEGUI::EventArgs& e)

{
int val = static_cast<const TestEventArgs&>(e).n;
std::cout << val << std::endl;
return true;
}

void exe()

{
mEvent.injectTest(99);
mEvent.injectTest(5555);
}

private:
testEvent mEvent;
};

int main()


{
testClient client;
client.exe();

system("pause");
return 0;
}
下面對代碼進行講解.
首先,我們需要聲明一個事件參數,在CEGUI主模塊里面都是一些鍵盤鼠標的輸入事件參數.
然后,我們需要聲明一個事件集,它由EventSet繼承而來.
在測試代碼里面,我們聲明了一個testClient的類,代表著客戶在里面我們聲明一個回調方法:testClient::handleTest.testClient::Init方法作為客戶的初始代碼,在這里面,我們注冊事件.在testClient::exe里面執行觸發事件的代碼.而后,事件將會被觸發,繼而testClient::handleTest方法將會被回調執行.