ActiveX深入淺出(二) (轉)
深入淺出(二)
作 者 : 揚眉
What an Event
事件是用來通知使用的員,某件事情發生了,好讓程式設計師可以相應的處理。事件在VB中比比皆是,例如,當滑鼠點選控制元件事會發生Click事件,文字框內容改變了會發生Change事件,等等。但這兒要講的不同於這些東西,也不同於InitProperties, ReadProperties, WriteProperties前面提到過的事件,那些是已經定義好了的。我們要做的是定義自己的事件。自定義的事件必須宣告在模組的宣告部分,然後就能夠在任何地方任何時候,只要你覺得應該有事件了,就可以觸發它。例如,一個代表眨眼的事件應該這樣宣告:
Public Event Blink()
在括號中,你可以放置任何你想要傳遞給事件的引數。對於一個Click事件,這個引數可能滑鼠點選時x和y座標。而這在理,應為只是眨眼,就用不到額外的引數了。
觸發事件,得使用RaiseEvent方法。對於我們的眨眼事件,我們把它和一個計時器聯絡起來,這樣它就能夠時不時的眨眼了:
Private Sub Blinker_Timer()
RaiseEvent Blink
End Sub
就這樣,一個事件就完成了,沒有任何技巧或者秘密可言。現在留給程式原作的,只要編寫相應的事件處理過程就行了,就像下面這樣:
Private Sub BodyControl1_Blink()
De.Print "嘻嘻,我又眨眼了!"
End Sub
到這兒,大部分關於ActiveX控制元件的基本問題都講了。後面的將是一些更高階的內容,包括圖片和字型屬性,“關於”對話方塊,執行時之讀屬性等等。在繼續之前,再看看前面的內容,好好的在理解一下。好了嗎?OK,現在開始更為激動的歷程。
首先,我們先來看看對於屬性,還有什麼可以挖掘的東西,比如顏色或者圖片之類的東西。
高階屬性設計
色彩值被存貯在長整形變數中,但是如果你只是定義一個長整形變數,顯然是不能夠得到像vb中所提供的那個顏色選單:
這看起來很複雜,實際上做起來卻一點也不難:所有你要做的只是把屬性宣告為OLE_COLOR型別,就像下面這段程式碼所作的那樣:
Public Property Get BackColor() As OLE_COLOR
BackColor = UserControl.BackColor
End Property
Public Property Let BackColor(ByVal New_BackColor As OLE_COLOR)
UserControl.BackColor = New_BackColor
PropertyChanged "BackColor"
End Property
記得前面曾經提過除了Let,Get,還有第三種屬性過程嗎?現在揭開迷底:它就是Set屬性過程,當要給變數賦值的時候,是不能用Let,而必須用Set來代替。這是因為儲存在控制元件內部的物件變數,儲存的並不是物件的複製,而只是物件的引用,也就是一個地址了。為了同一般變數的複製儲存區別開來,VB引入了Set屬性過程。
或許你可能知道:字型和圖片就是儲存在物件中的,而且,它們都擁有各自的的對話方塊來設定相關屬性。要用到這些對話方塊,所有我們要作的就是把圖片或者字型申宣告為Picture或者Font物件型別,並且為其設定Set屬性過程。
Public Property Get Font() As Font
Set Font = lblText.Font
End Property
Public Property Set Font(ByVal New_Font As Font)
Set lblText.Font = New_Font
PropertyChanged "Font"
End Property
看看上面的程式碼,你是不是在想:也沒有什麼很難的啊。確實,就是這樣簡單啊。下面,我們來看看如何為控鍵建立只讀屬性。這也是在控制元件的設計中用的比較多的一個內容。
只讀屬性
最簡單的方法,就是不要在Let/Set屬性過程中加入任何東西。但通常,這並不能滿足要求,有時,你可能需要一個執行時只讀的屬性。所謂執行時——和設計時相對應,是指控制元件最終在一個開發完成的程式中執行,而設計時指的是控制元件被使用在開發程式的過程中。
要實現執行時只讀,要用到Usercontrol的AmbientProperties物件。它提供了很多關於控制元件容器的屬性。中有一個UserMode屬性,當控制元件處在執行時狀態時,UserMode值為真。透過在Let/Get過程中提供對UserMode的檢測,就可以很容易的實現執行是隻讀屬性了:
Public Property Get MultiLine() As Boolean
MultiLine = m_MultiLine
End Property
Public Property Let MultiLine(ByVal New_MultiLine As Boolean)
If Ambient.UserMode Then
Err.Raise 382
Exit Sub
EndIf
m_MultiLine = New_MultiLine
PropertyChanged "MultiLine"
End Property
這段程式碼保護屬性只能夠在設計時被修改,如果在執行時試圖改變它, 就會產生“Property is read-only at run-time”錯誤。
和AmbientProperties物件相近的還有Extender物件。對於Extender物件,在開始編寫控制元件前有必要好好的瞭解。Extender物件是一個晚期繫結的藉口,開發員可以透過它訪問由控制元件容器(而不是控制元件本身)維護和控制的控制元件屬性。它提供了一些屬性,像Name,Enable,Left,Top,Height,Width等等,這些大多出現在一般的控制元件中,在編寫控制元件屬性前,應該看看是否已經存在在Extender物件中,一方面可以避免重複工作,另一方面也更有。
但是使用Extender物件還存在一些問題:並不是所有的容器都支援訪問相同的Extender屬性。所以選用Extender物件是必須十分小心,否這做出的控制元件只能為特定的容器所使用。但如果你只是為VB開發控制元件,那就不用有這些顧慮了,儘量的用吧。
還有一點要注意的是,Extender物件不能在usercontrol的initialize事件中訪問它,但是可以在initProperties和ReadProperties事件中使用。
列舉
在控制元件中設定屬性時,使用列舉是一種很常見的的方式。它提供了一個下拉選單和若干選項讓你選擇。這樣方便了的操作,又不用考慮過多的相容性和錯誤處理問題,簡化了屬性設定,而且更加。
首先,必須建立一個列舉結構,放在宣告部分。然後給出一系列的常量和對應的字串。常量值可以零,或者是任何比它前面一個常量值大的整數。如果沒有給出常量,那麼VB自動為其賦值,第一個未指定的賦值為零,其它的值為前面一個數加一:
Public Enum eDirection
Left
Right = 1
Up
Down
End Enum
要實現列舉屬性,必須建立一個帶有Let和Get屬性過程的標準屬性。這裡的技巧是將屬性的型別宣告為給出的列舉型別:
Public Property Get Direction() As eDirection
Direction = m_Direction
End Property
Public Property Let Direction(ByVal New_Direction As eDirection)
m_Direction = New_Direction
PropertyChanged "Direction"
End Property
唯一要注意的是,只能夠在設計時修改屬性列表,而不允許在執行時這麼做。其它的,像讀,寫,儲存和檢索,都和使用標準屬性是一樣的。
這就是所有的技巧了。難以置信的簡單,是嗎?你的控制元件是不是看起來更為專業了呢?
Usercontrol物件
用 所建立的 ActiveX 控制元件總是由 UserControl 物件加上選中放到 UserControl 上的任何控制元件(稱為子控制元件或則組成控制元件)所組成。就象 Visual Basic 窗體一樣,UserControl 物件具有程式碼模組以及視覺化的設計器。將組成控制元件放到 UserControl 物件的設計器上,就象把控制元件放到窗體上一樣。 在窗體上放置 ActiveX 控制元件的例項時,就建立了 UserControl 物件,以及放在 UserControl 設計器上的所有子控制元件的例項。這些物件都被封裝在控制元件中。
UserControl 物件有自己的屬性、方法和事件。對於一些屬性,像BorderStyle,BackColor等等,與其自己寫程式碼來實現 BackColor 屬性,不如就直接使用UserControl物件的。這就意味著 ActiveX 控制元件的 BackColor 屬性只需要簡單地 UserControl 物件的 BackColor 屬性就行了。同樣地,也可以在UserControl 物件現有的 Click 事件的基礎上設計您的控制元件的 Click 事件。
事實上在前面的內容中,我們時時都在和這個物件打交道,但是它有一些特別的東西,是應該值的多一些注意的。它的大部分屬性應該在控制元件的設計時來完成設定。在這兒我解釋一些比較晦澀難懂得屬性的含義,還有一些一望既知,就不多費口舌了。
Alignable屬性,當被設定成真的時候,VB將自動為控制元件新增一個新的屬性:align。這樣就能夠像放置工具條那樣安排控制元件在容器中的位置,而且這還意味著你的控制元件能夠被放置在MDI程式中。
CanGetFocus屬性,能夠決定使用者控制元件是否能夠在執行時獲得焦點。當要建立一個圖形控制元件,或者像Timer那樣在執行是不可見的控制元件時,就要設定這個值為False。要注意的是:只要控制元件至少包含一個設定為能夠接收焦點的子控制元件,CanGetFocus 屬性就不能設定為 False。如果 CanGetFocus 設定為 False,則其所有的子控制元件都不能設定為接收焦點。
ControlContainer屬性定義一個控制元件是否能夠像frames或者PictureBoxes控制元件那樣作為控制元件容器包含其它的控制元件。
DefaultCancel 屬性可以為控制元件新增Default和 Cancel屬性。在新增 Default 和 Cancel 屬性後,控制元件就可充當標準命令按鈕。也就是說當Default被設為Ture後,按下Enter鍵會觸發控制元件的click事件,而當Cancel屬性被設為Ture時,Esc鍵按下也會觸發click事件。
你可以透過檢查AmbientProperties物件的DisplayAsDefault屬性來知道控制元件是不是預設控制元件。
InvisibleAtRuntime能夠讓你建立像Timer之類的控制元件,在執行的時候是不可見的。
最後,ToolboxBitmap 屬性用來指定放在VB工具箱上的圖示的。建議的大小是32x32,但是實踐證明23x23或24x24工作起來更好,32x32是被縮放到那麼大了再顯示出來的。
屬性的屬性
說起來有點繞口,也有點費解,是嗎?。VB允許為控制元件的每個成員設定屬性。這裡麵包含了一些較高階的內容,能夠讓你建造更為專業化的控制元件。在選單欄中點選工具|過程屬性,會出現下面的對話方塊:
你可以在描敘框內輸入一段對控制元件的說明,在幫助上下文識別符號內輸入一個幫助的關聯ID號,將你的控制元件與一個幫助關聯起來,這樣當點了屬性後再按F1鍵就可以給出這個屬性的幫助內容。
利用“在屬性瀏覽其中使用本頁”欄位,可以給控制元件的定製屬性頁分配選定的號碼。這樣當使用者從VB的屬性中選擇該成員時,VB將直接線是屬性頁。 “屬性分類”欄位能夠讓屬性在VB的屬性瀏覽器的“按分類序”中出現在特定的類別下。這些類別包括外觀,字型,位置,雜項等等,只要選擇一項就行了。“隱藏該成員”可以讓屬性不在屬性瀏覽器中顯示出來,這對於一些不想讓使用者看到得公有成員有用,但是要記住,它只是隱藏而不是不許被使用。而利用“在屬性瀏覽器中不顯示”可以在控制元件的設計時(而不是在執行時)把屬性從屬性瀏覽器中去掉。作為一般的原則,任何用ReadProperties和WriteProperties實現的永久的屬性,都應當被屬性瀏覽器顯示出來,反之,任何非永久性的屬性就不應被顯露出來。
“預設使用者介面”用來設定控鍵的預設屬性和方法。比如,因為Caption屬性是Lable控鍵的預設屬性,那麼就可以對程式碼進行一些簡化,把
Label1.Caption = "Hello"
可以簡寫為:
Label1 = "Hello"
最後是關於資料繫結的部分。在VB中,的應用是很常見的。利用MS的資料訪問功能,可以很容易的把控制元件屬性和資料庫的欄位聯絡起來。當選擇了“屬性為資料繫結”和“繫結屬性到資料欄位”兩個核取方塊後,該屬性就可以以標準繫結控鍵的方式執行,這意味著你可以在為該屬性選擇資料庫控制元件和欄位名稱。
最後的話
到這兒,幾乎大部分和使用者控制元件有關的內容都講完了。你現在就可以開始為自己的程式定製合適的控制元件,還可以讓別人分享你的成果。雖然內容不是很多,但要完全吃透也不是件容易的事。所以,多看多練還是必要的,學無止境嘛。
當然,沒有十全十美的東西,對於ActiveX控制元件也是這樣的。合理的使用使用者控制元件是必須要注意的事情。ActiveX控制元件很容易就會變得很複雜,一不小心的話,你所付出的會遠遠多於你所得到的。
如果你只是想要一個帶有屬性和方法的物件,那麼類或許是更好的選擇。使用者控制元件與應用程式間相對複雜的介面,會佔用較多的資源。而在程式設計方面,控制元件也要比類複雜一些。但是如果你要求屬性,方法和事件實現永久的資料存貯,後者要在程式的外部實現,那麼就要用到使用者控制元件了。總之,不要以為這是一件容易的是。雖然我在這兒講得很簡單,但是對一個完整的使用者控制元件的設計,編寫,以及測試和所作的工作,絕對不會比一個一般的VB應用程式來的少。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-989670/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- ActiveX深入淺出(一) (轉)
- 《深入淺出MFC》讀書筆記(一,二) (轉)筆記
- 《深入淺出MFC》學習筆記之二 (轉)筆記
- Tomcat深入淺出——Servlet(二)TomcatServlet
- PostgreSQL VACUUM 之深入淺出 (二)SQL
- 深入淺出UML類圖(二)
- 深入淺出OOD(一) (轉)
- 深入淺出RxJava(二:操作符)RxJava
- 深入淺出HOOKS(之伍) (轉)Hook
- 深入淺出HOOKS(之陸) (轉)Hook
- 深入淺出談防火牆(轉)防火牆
- 深入淺出FE(十四)深入淺出websocketWeb
- 深入淺出學習決策樹(二)
- 深入淺出之正規表示式(二)
- 深入淺出話異常-(1) (轉)
- 深入淺出 Runtime(二):資料結構資料結構
- 深入淺出Websocket(二)分散式Websocket叢集Web分散式
- 《Java專欄》 課題二:Java深入淺出Java
- 深入淺出——MVCMVC
- 深入淺出mongooseGo
- HTTP深入淺出HTTP
- 深入淺出IO
- 深入淺出 RabbitMQMQ
- 深入淺出PromisePromise
- ArrayList 深入淺出
- mysqldump 深入淺出MySql
- 深入淺出decorator
- 深入淺出 ZooKeeper
- 機器學習深入淺出機器學習
- 深入淺出HTTPHTTP
- http 深入淺出HTTP
- 深入淺出 ARCore
- 深入淺出 synchronizedsynchronized
- 深入淺出WebpackWeb
- 深入淺出 blockBloC
- block深入淺出BloC
- Flutter深入淺出--(二)Flutter 的發展歷程Flutter
- 深入淺出說強制型別轉換型別