熟悉VB的朋友對使用ActiveX控件一定不會陌生,衆多控件極大地友善了程式設計,但唯一的缺陷是不能動态加載控件,必須在設計時通過引用,将控件放置在窗體上。VB6.0已能夠解決該問題,隻是幫助中沒有明确說明,并且沒有描述到一些關鍵功能,由于以前的版本中可以動态建立程序外服務:如果對象是外部可建立的,可在 Set 語句中用 New 關鍵字、CreateObject 或 GetObject 從部件外面将對象引用賦予變量。如果對象是從屬對象,則需使用高層對象的方法,在 Set 語句中指定一個對象引用:
Dim xlApp1 As Excel.Application
Set xlApp1 = New Excel.Application
或
Dim xlApp As Object '定義存放引用對象的變量。
Set xlApp = CreateObject( "excel.application ")
xlApp.Visible = True
這些文法很容易造成誤導,以為動态加載ActiveX控件也是此方法,可能有朋友也象我一樣利用CreateObject嘗試了無數次,卻無功而返,不知微軟公司是出于何種考慮,動态加載ActiveX控件是擴充控件集合的方式實作,通過實際摸索,終于就如何實作動态ActiveX控件找出了一條切實可行的方法,下面以一個具體的執行個體來詳細說明。
一、ActiveX控件
ActiveX 控件是 Visual Basic 工具箱的擴充部分。使用 ActiveX 控件的方法與使用其它标準内裝的控件,如 CheckBox 控件,完全一樣。在程式中加入 ActiveX 控件後,它将成為開發和運作環境的一部分,并為應用程式提供新的功能。
ActiveX 部件通過用戶端/伺服器關系與應用程式— 及與部件互相之間— 互動作用。用戶端是使用部件功能的應用程式代碼或部件。伺服器是部件及其關聯的對象。例如,假設應用程式使用 ActiveX 控件來提供一個标準的雇員窗體,供公司的多種應用程式使用。提供雇員窗體的 ActiveX 控件就是伺服器,使用這個控件的應用程式就是伺服器的用戶端。
二、加載方法
VB6.0中對Controls 集合進行了擴充,以前版本中Controls 集合在窗體上列舉出已加載的控件,這在疊代過程中是很有用的。Controls 集合辨別一個叫做 Controls 的内在窗體級變量。如果忽略可選的 object 所在處的整數,則關鍵字 Controls 必須包括在内。我們通常在視窗中使用如下代碼:
Text1.Text= "Hello, world "
其實也可以使用如下代碼達到同一目的:
Controls(1).Text= "Hello, world "
在VB6.0中除了原來的Clear、Remove 方法外(很奇怪,為什麼微軟在VB5.0中隻提供這兩種方法,而沒有提供Add方法,因為沒有Add,這兩種方法也就沒什麼用處),增加了Add方法,該方法就是用于動态加載控件的:
Controls.Add(progid as String, Name as String);
progid: ActiveX部件的ProgID,如: "VB.CheckBox ";
Name:ActiveX部件加載後的名稱,如: "MyCheckBox ";
若要在窗體上添加一個名為MyButton的按鈕,可以使用:
dim oControl as Object '窗體級變量
注意:這裡聲明為Object對象類型
Private Sub LoadControl()
Set oControl = Controls.Add
( "VB.CommandButton ", "MyButton ")
oControl.Left = 10
oControl.Top = 10
oControl.Visible = True '使控件可見
End Sub
這是VB6.0的标準文法,它在例程中也是如此示範的,不過該方法雖然現實了控件的動态加載,按鈕顯示在窗體上,可以象普通按鈕一樣按下去,但加載的控件不能預先設計響應事件代碼,如:事件Sub MyButton_Click()将是非法的,當然,可以将要響應的事件封裝在控件内部。就程式設計的觀點來看該方法沒什麼大的用處,開發ActiveX控件的目的是為了資源共享,為了被其他開發人員利用,是以要提供必要的事件接口,顯然利用該方法不行,通過分析VBControls等相關對象,找出VBControlExtender對象與EventInfo相結合能提供事件陷井捕捉,VBControlExtender對象對動态添加控件特别有用,它提供了一套通用的屬性、方法、事件給開發人員,它的一個突出特點是能程式設計設計控件的事件,熟習類程式設計的朋友對帶事件的對象聲明一定不會陌生:
Dim WithEvents objElemt as CElemtVBControlExtender也不例外,聲明的文法一樣,隻不過它有個特殊的事件ObjectEvent(Info As EventInfo),它能捕捉到對象使用RaiseEvent産生的所有事件,EventInfo資料結構映射了事件的名稱、參數個數和參數的值。VBControlExtender和 EventInfo相結合,采用Select Case 就可以預先将不同類對象的事件放置一起,各自獨立運作。将上面的代碼改寫一下就能提供Click事件了:
Dim WithEvents oControl As VBControlExtender '帶事件聲明聲明之後您就可以在代碼視窗的左上角的對象下拉框中發現該對象出現了,也就是說,該對象有了事件或方法了,它的事件有DragDrop,DragOver ,LostFocus ,GotFocus ,ObjectEvent和Validate,其中ObjectEvent是通用的事件捕捉。
Set oControl = Controls.Add
( "VB. CommandButton ", "MyButton ")
oControl.Visible = True
Private Sub oControl_ObjectEvent(Info As EventInfo)
Select Case Info.Name
Case "Click " 'Click事件
'您可以添加處理Click事件代碼
MsgBox "您按了MyButton! "
Case Else ' 其他事件
' Handle unknown events here.
End Select
當然對微軟提供的标準控件能采用該方法添加,大家都不會懷疑,但自己開發的控件也能嗎?答案是肯定的,我們可以用一個實際的例子進行說明。
三、執行個體描述
假設一個本地網絡的監控系統,需要在原理圖與實物示意圖間切換,原理圖包括組網結構、傳輸資源、監控主機等,而實物示意圖包括路由器、裝置、采集器等,當然兩種圖的事件要一緻,如輕按兩下某個裝置圖形将顯示給裝置的實時資料等,為了簡化維護,将原理圖與實物示意圖封裝成ActiveX控件,由于每種圖需要加載許多圖形控件,消耗資源較大,不能同時加載,需要将其分解為兩個控件,在切換時首先解除安裝一個控件,然後加載另一個控件,是以要實作動态加載ActiveX控件。
原理圖控件為--Theory.ocx ,對應工程為CTheory;
實物圖控件為---Fact.ocx ,對應工程為CFact;
注意:為了簡化,在設計控件時不設定許可證關鍵字。
實物圖控件上的圖形對象可以被拖動,拖動後的位置資訊通過事件ChangePosition來通知擁有該控件的窗體,以便下次加載能顯示在最後位置,實物圖和原理圖控件都有輕按兩下事件完成的工作相同,其他事件此處忽略。
四、具體示例
1、準備工作
對控件Theory.ocx 、Fact.ocx 進行注冊(利用Regsvr32.exe注冊);
建立窗體frmTest.frm ,在窗體上放置按鈕cmdLoadOcx—“原理圖”
2、聲明窗體級變量與加載函數LoadControl
Dim WithEvents oControl As VBControlExtender
'地圖仿真控件對象
Dim mblnTheory As Boolean '是否顯示原理圖
Private Function LoadControl(intType As Integer)
If Not oControl Is Nothing Then
'首先判斷對象是否存在,若存在則解除安裝
Controls.Remove( "MapView ")
'解除安裝控件,此操作非常重要
End If
If intType = 0 Then
( "CTheory. Theory ", "MapView ")
Else
( "CFact.Fact ", "MapView ")
oControl.Height = 3500
oControl.Width = 6500
oControl.Top = 100
oControl.Visible = True
End Function
Private Sub Form_Load()
mblnTheory = True
3、為按鈕cmdLoadOcx編寫代碼
Private Sub cmdLoadOCX_Click()
If mblnTheory Then
Call LoadControl(0)
mblnTheory = False
cmdLoadOCX.Caption = "實物圖 "
Call LoadControl(1)
mblnTheory = True
cmdLoadOCX.Caption = "原理圖 "
4、為事件ChangePosition編寫代碼
Private Sub oControl_ObjectEvent
(Info As EventInfo)
Select Case Info.Name
Case "ChangePosition "
MsgBox CStr(Info.EventParamters.Item(
1).Value) + ": " + _
CStr(Info.EventParamters.Item(2).Value)
Case "DbClick "
'輕按兩下處理代碼
Case Else '
注意: EventInfo的參數EventParamters集合中是以1開始的,一般來說,微軟新的集合一般是以1開始的,而舊的是以0開始的,如RdoErrors.Item(0)。
5、關閉視窗前解除安裝控件
Private Sub Form_Unload(Cancel As Integer)
Controls.Remove( "MapView ")
Set oControl = Nothing
6、特别注意
通過Controls.Add方法添加的ActiveX控件一定不能在該工程中有該控件的任何引用,否則系統将出錯。
五、小結
通過使用動态加載ActiveX控件使用龐大的應用程式變得很小,将不同的ActiveX控件進行各種組合,使應用程式更加靈活多變,如您的應用系統要處理三十種門禁,而某個具體的使用者可能隻有一種或兩種門禁,根本沒必要首先将所有門禁包含到應用中,可将各個門禁獨立封裝,隻安裝注冊需要的元件,就象Windows的自定義安裝一樣。微軟的未來技術基礎是分布式的元件技術(DCOM),将會把代碼的重用發揮得淋漓盡緻。您不妨試一試動态加載,也許會産生令您驚喜的效果!
===============================================================================
最簡單的方法:控件數組。
在VB程式設計中有一個控件數組的概念, 通過置控件的INDEX 索引值的控制, 不僅可以建立一組具有緊密聯系的相同控件, 而且可以實作在程式運作狀态中增加控件數目功能, 這在實際程式設計中應用的非常廣泛;在程式設計中實作具體增加控件數組如下代碼即可,請先在窗體上添加一個option控件,名稱為option1,并将index屬性設為0.
Private Sub Form_ load()
Dim i As Integer
For i = 1 To 5
Load Option1(i) ' 給數組添加 5 個選項按鈕。
Option1(i).Top = Option1(i - 1).Top + 350’設定頂端位置
Option1(i).left= Option1(i - 1).left+800
Option1(i).Visible = True’顯示增加的控件
Option1(i).caption = i
Next i
End Sub
Private Sub Option1_Click(Index As Integer)
MsgBox ("您點選了index為" & Index & "的option控件.")
End Sub
(二)通過Add方法實作
Add方法在Controls集合中添加一個控件并傳回一個對控件的引用。Add方法的文法為:
Object.Add(ProgID,Name,Container)
其中Object為要添加元素的集合,ProgID為标示的字元串.可通過對象浏覽器來确定,例如,CommandButton控件的ProgID是VB.CommandButton. Name是控件的名稱. Container是包含添加控件的容器,可以為form或Frame控件等等。
Option Explicit
'通過使用WithEvents關鍵字聲明一個對象變量為新的指令按鈕
Private WithEvents NewButton As CommandButton
'增加控件
Private Sub Command1_Click()
If NewButton Is Nothing Then
'增加新的按鈕cmdNew
Set NewButton = Controls.Add("VB.CommandButton", "cmdNew", Me)
'确定新增按鈕cmdNew的位置
NewButton.Move Command1.Left + Command1.Width + 240, Command1.Top
NewButton.Caption = "新增的按鈕"
NewButton.Visible = True
End If
End Sub
'新增控件的單擊事件
Private Sub NewButton_Click()
MsgBox "您選中的是動态增加的按鈕!"
(三)借助 VBControlExtender實作.
如果增加的控件沒有添加在”工具箱”中,必須把控件的License關鍵字添加到License集合中,并且需要聲明它為 VBControlExtender對象,并且向Add方法引用上設定該對象變量。然後,利用VBControlExtender事件來程式設計該控件的事件。請在窗體上添加一個名詞為 text1的控件。
Option Explicit
Dim WithEvents ctlDynamic As VBControlExtender
Private Sub Form_Load()
Dim I as integer
Licenses.Add "MSComctlLib.TreeCtrl"
Set ctlDynamic = Controls.Add("MSComctlLib.TreeCtrl", "myctl", Form1)
' 設定控制的位置和大小
ctlDynamic.Move 1, 1, 2500, 3500
' 添加一些節點到 TreeView控件
For i = 1 To 10
ctlDynamic.object.nodes.Add Key:="Test" & Str(i), Text:="Test" & Str(i)
ctlDynamic.object.nodes.Add Relative:="Test" _
& Str(i), Relationship:=4, Text:="TestChild" & Str(i)
Next i
' 顯示控件
ctlDynamic.Visible = True
Private Sub ctlDynamic_ObjectEvent(Info As EventInfo)
' 測試 TreeView控件的 Click事件
select case Info.Name
case "Click"
Text1.Text = "你點選了 " & ctlDynamic.object.selecteditem.Text
case else
‘添加其他事件
End select
(四)控件删除
删除控件使用Remove方法,但隻能删除那些用Add方法添加的控件.對于(二)中添加的控件NewButton,可以用如下代碼删除
Private Sub Command2_Click()
If NewButton Is Nothing Then
Else
Controls.Remove NewButton
Set NewButton = Nothing
End If
以上程式代碼在vb6.0中文企業版中運作通過。
本文轉自 夢在旅途 部落格園部落格,原文連結:http://www.cnblogs.com/zuowj/archive/2012/12/11/2813739.html ,如需轉載請自行聯系原作者