“要解釋新的事件處理程序的方法,我們需要先說幾個重要的問題。 ”大李開始嚴肅起來,我也只得挪動一下身子,表現出正襟危坐的架勢。
“我們首先討論一下事件是怎麼產生的。事件是對象發送的消息, 以發信號通知操作的發生。操作可能是由用戶交互,例如鼠標單擊引起的,也可 能是由某些其他的程序邏輯觸發的。引發事件的對象叫做事件發送方(啊,聽到 這,henry突然明白了事件處理程序中的第一個參量為什麼叫sender了,就是指事 件發送的那個對象呀)。捕獲事件並對其作出響應的對象叫做事件接收方。在事 件通訊中,事件發送方類不知道哪個對象或方法將接收到它引發的事件。所需要 的是在源和接收方之間存在一個媒介,或類似指針的機制。.net 框架定義了一個 特殊的類型delegate,也就是委托,該類型提供函數指針的功能。 ”
“啊,我早就聽說過委托的,就是不知道它是什麼意思咧! ”我做出期盼狀。
“委托就是可用於調用其他對象方法的對象 。與其他的類不同,委托類具有一個簽名,並且它只能對與其簽名匹配的方法進 行引用。”大李繼續說著。
““噢,委托也就是一個函 數指針喽。”我好象理解了一點。
“差不多,委托可以等效於 一個類型安全函數指針或一個回調。但不同於函數指針,visual basic.net 委托 是基於 system.delegate 類的引用類型,它可以引用我們先前說過的共享方法( 詳見《共享成員》一篇)和實例方法。”
“明白了一點。 ”我一邊點頭一邊說,“我們想要動態調用事件處理程序,是不是就 要利用委托來聲明是哪個程序用於處理事件呀?”
大李驚異地看著 我,露出了幾分贊許。
“委托是.net中的一個重要的類型,我們以 後還需要詳細討論。現在我們需要關注的就是如何來通過操作委托來實現將事件 與事件處理程序動態聯系起來。”大李接著就開始修改代碼:
module module1 public class chenry public event eventhr() ´ 聲明一個事件 sub causesomeevent() raiseevent eventhr() ´ 引發事件 end sub end class dim obj as new chenry() sub obj_eventhr() ´在handles之後聲明事件 msgbox("事件處理器捕捉到了事件.") ´處理事件. end sub sub main() addhandler obj.eventhr, addressof obj_eventhr obj.causesomeevent() ´調用對象去引發事件 end sub end module
“看到有什麼不同嗎?”大李轉過身來問我。
“主要有兩個不同,首先是obj的定義不再用withevents來標識了, 因此事件處理程序obj_eventhr()也就不能通過handles關鍵字來聲明事件,也就 是說eventhr事件與事件處理程序沒有用withevent-handles進行關聯;其次,是 使用了addhandle和 addressof……”說到這,我也沒有詞了 ,只能語焉不詳。
“呵呵,我來幫你接著說。”大李拍了拍我 的肩膀,接著說“先說addressof吧,addressof 運算符創建的是一個指向 指定的過程的過程委托。我們剛才說過委托相當於一個函數指針,那麼addressof 就是委托的操作符,通過它能得到委托的引用。”
見到我稍稍明白 了,大李又接著說:“光看addhandle能夠將obj.eventhr事件與 obj_eventhr事件處理程序關聯起來的作法,你肯定不了解我所說的動態關聯好處 在哪裡。因為我沒提到另一個方法removehandler。它的使用方法和addhandle是 一樣的,比如:
removehandler obj.eventhr, addressof obj_eventhr
你看,addhandler 與 removehandler 在一起就可以提供比 handles 子句更大的靈活性,只要我們善於利用它們,就可以動態地添加、移除 和更改與某事件關聯的事件處理程序。而且比 handles 要強大的是,addhandler 允許將多個事件處理程序與單個事件進行關聯。”
大李停了一停, 接著說:“你要注意的一點就是addressof後面跟著的委托簽名應該與相應 的事件數據類相一致,我們看一個例子。”
addhandler textbox.mousedown,addressof textboxmousedownhandler ‘錯誤的示例1: private sub textboxmousedownhandler( ) end sub ‘錯誤的示例2 private sub textboxmousedownhandler(byval sender as object, byval e as eventargs) end sub ‘正確的示例: private sub textboxmousedownhandler(byval sender as object, byval e as mouseeventargs) end sub
“事件是一個文本框中的鼠標按下事件,我們不用自帶的 標准關聯事件處理方法,而用addhandler來實現,那麼addressof之後相應的方法 的參數聲明,應該與mousedown事件對應的事件的委托mouseeventhandler具有相 同的簽名,也就是參數聲明上要保持一致,一個object變量,一個 system.windows.forms.mouseeventargs變量。”
我到這一步才算明 白了個大概,事件處理程序可以通過addhandler和removehandler方法在我們需要 的時候動態地建立或斷開事件與事件處理程序的關聯關系。可是,對於大李剛說 的“事件的委托mouseeventhandler”,我還是不太理解。