ActiveX深入淺出(一)
發表于:2007-06-30來源:作者:點擊數:
標簽:
綱要 可以這樣說,Active平臺代表了Microsoft的世界觀。使用ActiveX控件,來構筑包括從與用戶交互和適應COM的事務處理監視器,到Web 服務器 ,全部實現自動化的機構,這就是Microsoft的打算了。桌面用的、基于COM的組件叫做ActiveX控件。所謂ActiveX控件不過是
綱要
可以這樣說,Active平臺代表了Microsoft的世界觀。使用ActiveX控件,來構筑包括從與用戶交互和適應COM的事務處理監視器,到Web
服務器,全部實現自動化的機構,這就是Microsoft的打算了。桌面用的、基于COM的組件叫做ActiveX控件。所謂ActiveX控件不過是遵從一定的標準、與客戶端交互的COM對象而已?;诮M件的應用
開發,其方法和組裝電子裝置一樣,可以用已制作好的組件部件來構筑應用。這確實是一項很令人神往的技術。雖然說起來高深,但隨著ActiveX的廣泛應用,越來越多的編程工具都支持創建ActiveX控件了。這其中就包括了
VB。在VB中設計一個ActiveX并不比一個普通的VB應用程序難上許多。這篇文章,就是一步步教你如何在VB中創建一個ActiveX控件。
ActiveX深入淺出(一)
作 者 : 揚眉
什么是ActiveX控件?
一個簡單的回答就是:擁有圖形界面的類。你可能曾經用過類來編程,那是一種實現代碼重用的的好方法。當然,它也提供了很多其它的好處,這兒并不打算一一列舉出來。ActiveX 控件將這個概念近一步的深化了,能夠讓你編寫一個窗口小部件(widget),然后把它打包起來,在以后的程序里用到它,或者作為特定的問題的解決方法,給
程序員提供更簡便的編程方法。 用ActiveX你可以建造“復合式”控件,由其它的幾種控件組合而成。也就是說,在ActiveX控件中你不但可以使用VB中諸如文本框,圖片框之類的普通控件,你還可以用其它的ActiveX控件來構成你自己的控件,實現你想要的功能,并把它打包以背后用。
ActiveX控件的組成
一個ActiveX控件由它的一些成員組成:屬性,方法以及事件。它們之間有什么樣的邏輯關聯呢?還是用我們的身體來做個例子吧,將身體就看成一個ActiveX控件。 這個控件首先應該有一些屬性,比如:眼是否睜開屬性。顯然,這個屬性值應該有兩種情況:開或則閉。使用的時候能夠告訴“身體控件”讓這個屬性換一個新的值,以決定睜眼或者閉眼,或者得到當前的屬性值,以知道目前的身體狀況。
方法是控件中過程和函數的統稱,同其它任何的VB函數和過程并沒有什么不同,你同樣可以向它們傳遞參數,并返回想要的值。假設有一個類描敘了身體這個對象,它應該有“Look”這個方法,并且應該能接受“Direction”這個參數,那么,這個方法就應該寫成這樣:
Public Sub Look(Direction As Integer)
Select Case Direction
Case 0
@#向左看
Case 1
@#向右看
Case 2
@#向前看
Case 3
@#向后看
End Select
End Sub
若要求返回值,我們就舉一個“讀”的例子吧。這時你必須把“Read”這個方法聲明成函數而不是過程 :
Public Function Read() As String
@#讀的一些操作
Read = "Hello from the World"
End Function
在身體控件中,我們用的還是“Look”這個方法。當調用這個方法的時候,就是指定眼睛應該去“看”了。同樣,我們還指定了另外一個方法,“Read”。這一個方法將用來返回看到的東西。
“方法”這個概念是不是很簡單呢?如果你還不能夠理解,也可以這樣來想:你的控件就像是一臺機器,你撥動控制開關(輸入參數),轉動把手(調用方法),然后機器的燈閃動,運行起來(執行方法),最后從機器里蹦出一些東西(返回值),就是這樣了。但等等……如果你的機器想告訴你什么事情,它該怎么做呢?這時就該是“事件”出場了。
最后,身體控件還會提供一個“眨眼”的事件,用來在進行眨眼這個動作的時候,通知開發者發生了這個事件,但是不必知道身體內部的工作方式和為什么這個事件會被觸發。
來動手吧,作一個控件。不要以為作一個控件是非常難的事,雖然它和一般應用程序的編寫是有一點不同的地方。在上面我們已經知道,一個ActiveX控件是由屬性,方法和事件組成的,我們先看看如何在程序中實現這些東西,然后再把它們聯系起來,組合成一個右機的整體。屬性最簡單的形式是用public聲明的公用變量。例如,如果把下面這段代碼放到你的控件工程的聲明部分:
Public EyeOpen As Boolean
這樣,你就可以在后邊的代碼中使用這個屬性了。但是,這種屬性所能夠做的事實在太少了。它幾乎是不能夠正常工作的。因為在程序的設計期間,屬性值的任何變化都必須通知Visual Basic,以便把控件實例標記為需要保存。而又因為屬性值可能顯示在多個地方,因此當屬性值發生改變時必須通知開發環境,以便使它能夠同步顯示“屬性”窗口、“屬性頁”對話框等位置上的屬性值。
上面說的是不是有點難理解呢?要是不明白說的什么,不要急,你先打開一個工程,添加一個控件,試著改改這個控件的一些屬性,在來看看上面的話,是不是明白了呢?我們現在的任務,就是要作一個這樣的控件啊。由此可以看出,控件編程和一般的編程還是有一些區別的。那么,該怎么實現數行呢?這要使用到屬性過程。
當一個屬性值被引用或者設置的時候,屬性過程自動的被調用。下面我們就來添加一個這樣的屬性:打開代碼窗口,再點擊“工具”菜單,選擇“添加過程”子菜單,彈出的對話框中,填入過程名“EyeOpen”,然后再把類型設置為“屬性”。當你點了確定之后,VB自動的為你創建了一個屬性過程的原型,代碼會被添加到代碼窗口中:
Public Property Get EyeOpen() As Variant
End Property
Public Property Let EyeOpen(ByVal vNewValue As Variant)
End Property
剩下的你要做的,是寫入屬性處理代碼,把這個骨架填滿。
你可以看到,VB實際上為你寫了兩個,“Get”和“Let”屬性過程,有點疑惑嗎?實際上很簡單:“Get”是當屬性值被引用的時候調用的過程,而“Let”則是當屬性值被寫入的時候調用的。(事實上還有第三種類型的過程,我們將在后面遇到,這里先提個醒)要讓一個屬性過程能夠正確的工作,必須還要有一個變量來保存真正的屬性值。把下面這一行添加到聲明部分:
Private m_EyeOpen As Boolean
注意到那個@#m_@#前綴,一般是放在用戶控件的內部變量之前。 現在該是填充過程框架的時候了。先看看Let過程,這個過程帶有一個參數:缺省的是名字是vNewValue,variant類型。但我們想要一個布爾類型的變量而不是variant,因為眼睛在我們的模型中只有開和閉兩種狀態。所以把這個參數改成“New_EyeOpen As Boolean”。如果你想要這個屬性作為只讀屬性出現,那么就不要再改動Let過程,讓過程體空在那兒。否則,當想要設置這個屬性值的時候,應該執行這樣的代碼:
Public Property Let EyeOpen(New_EyeOpen As Boolean)
m_EyeOpen = New_EyeOpen
PropertyChanged "EyeOpen"
@#后面還可以寫一些相關的代碼,對屬性的設置做出反應
End Property
當要在程序中寫入屬性值的時候,就會調用這個函數,先把屬性值保存在一個私有變量里面,然后執行PropertyChanged這個內部方法,它用來告訴Visual Basic屬性值有了變化,并觸發一個WriteProperties事件。關于這一點的具體的內容,在后面還會提到。
而Get過程更為簡單!它和標準函數沒有兩樣:
Public Property Get EyeOpen() As Boolean
EyeOpen = m_EyeOpen
End Property
做完這些就完了嗎?不!忘了前面說的屬性值是需要保存的,因此當編程會話發生轉換的時候,它們能夠保持下來。那么怎么樣來保存和取出屬性值呢?這時就要用到PropertyBag對象了。
使用PropertyBag
PropertyBag對象包含兩個方法:一個用來讀出,一個用來寫入。前面提到了,當任何的屬性發生變化得時候,會觸發控件的WriteProperties事件。這時就可以把屬性值保存在屬性包中了。下面的代碼實現這個功能:
PropBag.WriteProperty "EyeOpen", m_EyeOpen, True
PropBag是PropertyBag對象的一個實例。WriteProperty函數包含三個參數,第一格是屬性名稱,后面的是要保存的值,最后的參數是在無用戶定義屬性的情況下,將寫入的默認值。把這個和ReadPropertiy方法的默認值設置結合起來,就可以為屬性值設置缺省值了。如果屬性值和缺省值相同,那么屬性值就不會真正的別保存。當要讀出的時候,ReadProperty函數發現在屬性包中沒有內容,就會返回缺省值。這樣可以節省一些系統開銷。要注意的是:必須將一個成員屬性的名稱作為字符串傳遞。當你將控件作國際化處理時,不要改變這一字符串的名稱,它必須與該屬性的申明的名稱相匹配。
當控件被重啟動后,你必須重載如所有保存的屬性值。當每次讀取PropertyBag中的數據時, ReadProperties事件被觸發。在這個事件的處理過程中,你要做的任務就是載入保存在屬性包中的屬性值,調用ReadProperty函數來實現值一點。要注意的是:在讀和寫兩個函數中的缺省值設置要一樣。例如:
m_EyeOpen = PropBag.ReadProperty("EyeOpen", True)
一個同步缺省值的方法是為其設置常量,在需要的時候直接使用常量來代替具體的值,這樣就不用擔心出問題了。例如:
Private Const m_def_EyeOpen = True
“m_def_”前綴通常放在缺省值常量的前面。
當控件被啟動的時候,一般要為屬性設置初始值。這一般是在usercontrol的InitProperties 事件中實現的。這個事件發生于控件實例首次實體化時,也就是把控件實例放置到窗體上的時候,它在以后的整個設計期間里都不會再發生。Usercontrol還有一個Initialize事件,它是每次控件實例被創建時觸發的。顯然,初始化過程如果放在Initialize事件中就太過頻繁了,沒有這個必要。設計 ActiveX 控件需要根本性地轉變一些觀念。需要響應的關鍵事件是往往不同于一般的程序設計。下面是我們想要實現的代碼:
Private Sub UserControl_InitProperties()
m_EyeOpen = m_def_EyeOpen
End Sub
好,到現在關于屬性的部分基本就結束了,下一篇中我們要講到的是另外的一個成員:方法。
原文轉自:http://www.kjueaiud.com