technorati 標籤:
vba,
自定義事件,
raiseevent,
withevents,
事件過程,
事主,事發現場
出處:http://blog.csdn.net/slowgrace/archive/2008/12/06/3456784.aspx
1、定義事件event
所謂事件是指「一些事情發生了」這麼乙個訊號,或者更確切的說,是指某物件的一些屬性發生了一些變化或者到達了一些狀態。我們不妨稱發生變化的這個物件為事主(這是我原創的概念哈,沒仔細推敲過,不到之處請海涵)。在vba中,定義物件用的是event語句。事件都是和事主綁在一起定義的,所以event語句都是出現在事主類定義模組中的。這個也好理解,只要反覆念叨幾遍oop的基本思想「自己的事自己負責」就可以了。另外,要注意,event必須是public的,否則編輯通不過。我想vbe這麼規定,也許是因為事件機制需要訪問這個event,如果定義為private的,就無法訪問了。
2、觸發事件raiseevent
除了要定義事件本身,還要定義何時事件會被觸發。這就要用到rasieevent語句。同理,這個語句也只能在事主類的模組中出現,因為:只有自己才最了解自己的狀態到鳥哪一步,從而也才知道是否到事件該發生的狀態。那麼,如果需要在事主類之外觸發該事主類的事件,該怎麼辦呢?辦法是,呼叫事主類的包含raiseevent事件的公用方法。
3、事件過程和方法的區別
不過,有時候你要動腦筋想一想,你是需要觸發物件的事件呢,還是需要呼叫物件的方法呢?我剛學會用事件的時候,用事件上癮,不管大事小情,都要造個event,以raiseevent為樂,因為那種你嘛也沒做,事件過程就被自動呼叫了的感覺真的很好玩。其實,很多時候,不需要事件,你直接呼叫物件的方法就可以了。
比如,如果你希望按下乙個button之後,物件做點事情。你有兩種選擇:一種是在buttonclick中直接呼叫物件的方法;一種是在buttonclick中呼叫物件的觸發事件的方法(比如,提供乙個這樣**的方法,裡面揍一行語句: raiseevent ****),然後再由系統呼叫物件對該事件的處理過程。
我初步的感覺是,如果你需要事情發生後,事主物件自己的某些屬性發生一些變化,那麼就呼叫物件的方法;如果你需要事情發生後(也就是事主物件到達某一狀態後),事主物件所在的環境裡其他一些物件(不是事主類物件)發生回應,那麼就用事件過程。
4、withevents宣告和事件過程
事主物件的事件被觸發後,要執行一系列的動作來響應,這些動作寫在事件過程裡,由系統在事件觸發時自動呼叫。
現在再動腦筋想一想,事件過程是應該在類模組中還是在使用類的模組中呢?所謂「使用類的模組」是指,宣告類物件,把類例項化的模組,我們不妨稱它為事發現場模組。ok,my question是:事件過程應該在事主類模組呢還是在事發現場模組呢?
答案是:應該在事發現場模組。其實呢,從邏輯上說,擱哪兒都行、都有它的道理;不過,既然vba現在這麼規定,咱們就本著幫助記憶的目的,盡量把它的規定解釋得合理一些吧。之所以事件過程要放在事發現場,原因是:事件過程要處理事件的各種情況,自然要知道事發現場的各種事情了,還要操作事發現場的各種物件以便善後,所以,當然在事發現場處理是最好的了。
首先在事發現場模組用withevents關鍵字宣告事主類的物件變數
其次在事發現場模組寫該事主類變數的事件過程,事件過程名由系統自動生成,在vbe**區右上的下拉列表中可以找到,形式是:物件名_事件名()
當然,有時候,你會希望發生某事件後,事主會始終執行某些規定序列,而不管事發現場是個什麼情況(比如,你希望你的樹控制項在發生nodeclick事件後,都自動蹦出hello)。也就是,你希望,事件過程是放在事主類那邊的。這個嘛,要實現也可以,不過比較繞,可以看看
俺這篇大作。基本思路是:另外生成乙個以事主類物件為成員變數的類,在該類中同時封裝該成員變數的事件過程。其實質是,把事發現場也封裝成類。
另外,要注意的是,withevents語句只能用在類模組中,如:窗體模組、報告模組、自定義類模組,而不能用在標準模組中。這其實也好理解,因為事發現場這個概念本身是事件機制中的一環,而事件機制是基於物件的概念的,標準模組跟物件沒關係,自然也就無緣做事發現場。
5、示例——來自微軟幫助
下面的示例使用事件來計數100公尺短跑比賽的演示的最短時間秒數。**演示了所有與事件有關的方法、屬性、以及語句。
該示例使用了乙個帶有乙個按紐(command1
)、乙個標籤(label1
)、和兩個文字框(text1
和text2
)的窗體(form1
)。當單擊該按紐時,第乙個文字框顯示「from now」並且第二個文字框開始時間計數。當整個時間(9.84秒)結束時,第乙個文字框將顯示「until now」,並且第二個文字框顯示「9.84」。
事主模組:名為 timerstate 的類模組
事發現場模組
:form1 的**指定了窗體的最初狀態和結束狀態。它同時還包括當事件被引發時所要執行的**。
option explicit
private
withevents mtext as timerstate
private
sub command1_click()
text1.text = "from now"
text1.refresh
text2.text = "0"
text2.refresh
call mtext.timertask(9.84) '注意這個方法裡包含raiseevent語句
endsub
private
sub form_load()
command1.caption = "click to start timer"
text1.text = ""
text2.text = ""
label1.caption = "the fastest 100 meters ever run took this long:"
set mtext = new timerstate
endsub
private
sub mtext_changetext() '事件過程1
text1.text = "until now"
text2.text = "9.84"
endsub
private
sub mtext_updatetime(byval dbljump as
double) '事件過程2
text2.text = str(format(dbljump, "0"))
doevents
endsub
參考文獻:microsoft visual basic幫助
在自定義HttpHandler中使用Session
最近需要做乙個對特定請求進行響應的介面,只是在內部處理,不存在ui,機於這種情況,當然是使用實現ihttphandler來進行處理,可以減掉載入html 控制項的時間。本來都是這樣想的,對於ihttphandler 中定義了兩個方法,processrequest httpcontext ctx 和 ...
structs 在action中使用自定義方法
一般來講,action的預設方法為execute 也就是在執行乙個action時,會自動呼叫這個方法.但是,有時候我們希望乙個action具有多個方法,而不是去建立多個action.那麼我們就需要動態的決定到底使用action中的哪個方法.比如,在名為path的 action中,它具有兩個方法add...
在自定義HttpHandler中使用Session
最近需要做乙個對特定請求進行響應的介面,只是在內部處理,不存在ui,機於這種情況,當然是使用實現ihttphandler來進行處理,可以減掉載入html 控制項的時間。本來都是這樣想的,對於ihttphandler 中定義了兩個方法,processrequest httpcontext ctx 和 ...