ActiveX深入淺出(二)
發表于:2007-06-30來源:作者:點擊數:
標簽:
What an Event 事件是用來通知使用控件的 程序員 ,某件事情發生了,好讓程序員可以相應的處理。事件在 VB 編程中比比皆是,例如,當鼠標點擊控件事會發生Click事件,文本框內容改變了會發生Change事件,等等。但這兒要講的不同于這些東西,也不同于InitProp
What an Event
事件是用來通知使用控件的
程序員,某件事情發生了,好讓程序員可以相應的處理。事件在
VB編程中比比皆是,例如,當鼠標點擊控件事會發生Click事件,文本框內容改變了會發生Change事件,等等。但這兒要講的不同于這些東西,也不同于InitProperties, ReadProperties, WriteProperties前面提到過的事件,那些是系統已經定義好了的。我們要做的是定義自己的事件。自定義的事件必須聲明在模塊的聲明部分,然后就能夠在任何地方任何時候,只要你覺得應該有事件了,就可以觸發它。例如,一個代表眨眼的事件應該這樣聲明:
Public Event Blink()
在括號中,你可以放置任何你想要傳遞給事件的參數。對于一個Click事件,這個參數可能鼠標點擊時x和y坐標。而這在理,應為只是眨眼,就用不到額外的參數了。
觸發事件,得使用RaiseEvent方法。對于我們的眨眼事件,我們把它和一個計時器聯系起來,這樣它就能夠時不時的眨眼了:
Private Sub Blinker_Timer()
RaiseEvent Blink
End Sub
就這樣,一個事件就完成了,沒有任何技巧或者秘密可言?,F在留給程序原作的,只要編寫相應的事件處理過程就行了,就像下面這樣:
Private Sub BodyControl1_Blink()
De
bug.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對象
用 Visual Basic 所創建的 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后,按下回車鍵會觸發控件的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應用程序來的少。
原文轉自:http://www.kjueaiud.com