所謂事件驅動,簡單地說就是你點什么按鈕(即產生什么事件),電腦執(zhí)行什么操作(即調用什么函數(shù)).當然事件不僅限于用戶的操作. 事件驅動的核心自然是事件镜悉。從事件角度說,事件驅動程序的基本結構是由一個事件收集器医瘫、一個事件發(fā)送器和一個事件處理器組成侣肄。事件收集器專門負責收集所有事件,包括來自用戶的(如鼠標醇份、鍵盤事件等)稼锅、來自硬件的(如時鐘事件等)和來自軟件的(如操作系統(tǒng)叮喳、應用程序本身等)。事件發(fā)送器負責將收集器收集到的事件分發(fā)到目標對象中缰贝。事件處理器做具體的事件響應工作馍悟,它往往要到實現(xiàn)階段才完全確定,因而需要運用虛函數(shù)機制(函數(shù)名往往取為類似于HandleMsg的一個名字)剩晴。對于框架的使用者來說锣咒,他們唯一能夠看到的是事件處理器。這也是他們所關心的內容赞弥。
視圖(即我們通常所說的“窗口”)是“事件驅動”應用程序的另一個要元毅整。它是我們所說的事件發(fā)送器的目標對象。視圖接受事件并能夠對其進行處理绽左。當我們將事件發(fā)送到具體的視圖時悼嫉,實際上我們完成了一個根本性的變化:從傳統(tǒng)的流線型程序結構到事件觸發(fā)方式的轉變。這樣應用程序具備相當?shù)娜嵝云纯梢詰斗N種離散的戏蔑、隨機的事件。
由于Windows本身是基于“事件驅動”模型的鲁纠。因而在Windows操作系統(tǒng)下實現(xiàn)應用程序框架有相當?shù)谋憷芸谩T谑录寗映绦虻?a target="_blank" rel="nofollow">基本單元中,事件收集器已經(jīng)由Windows系統(tǒng)完成改含;事件發(fā)送器也已經(jīng)由Windows完成了部分內容情龄。之所以是部分而非完全是因為Windows是用C語言實現(xiàn)的,而不是C++捍壤。由于沒有對象骤视,Windows將事件發(fā)送到所謂的“窗口函數(shù)”中(盡管不是發(fā)送到具體的對象,但應該說這是面向對象方式實現(xiàn)的一個變體)鹃觉。要感謝Windows做了這件事专酗。確定事件的目標所要做的工作的復雜可能要超出我們的想象。
wxWidgets的中所有可以處理事件的類都繼承自wxEvtHandler帜慢,其中包含frames,buttons,menus,even documents笼裳,所有的窗體類(即從wxWindow繼承的類)和程序類(application class).
這些類可以有一個事件表,用來綁定事件和被調用的函數(shù)(handler functions).
過程 3.2. 建立一個靜態(tài)事件表(即編譯時生成的事件表)的操作步驟
建立一個新類(直接或間接從wxEvtHandler繼承)
為每個要處理的事件聲明被調用的函數(shù)
在被處理的事件所在的類的聲明中加入宏DECLARE_EVENT_TABLE
在宏BEGIN_EVENT_TABLE... END_EVENT_TABLE(就是事件表)中將函數(shù)與枚舉的數(shù)字綁定(因為產生該類型的事件的按鈕不唯一粱玲,要用枚舉數(shù)來區(qū)分)躬柬;有些事件不必與枚舉數(shù)綁定,因為產生該類型的事件的對象可以確定(比如就是this).
例 3.1. 一個事件表
BEGIN_EVENT_TABLE(MyFrame,wxFrame)
EVT_MENU (wxID_ABOUT,MyFrame::OnAbout)
EVT_MENU (wxID_EⅪT,MyFrame::OnQuit)
EVT_SIZE (MyFrame::OnSize)
//不必與枚舉數(shù)綁定抽减,因為產生該類型的事件的對象是this
EVT_BUTTON (wxID_OK,MyFrame::OnButtonOK)
END_EVENT_TABLE()
在事件中指定被綁定的數(shù)字允青,wxWidgets會將其映射到對應的函數(shù),并調用函數(shù)
所有在事件表中被綁定的函數(shù)有相似的形式:返回值都是void卵沉,不是virtual函數(shù)颠锉,參數(shù)為wxCommandEvent類型