天天看點

vb動态建立控件

熟悉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  ,如需轉載請自行聯系原作者

繼續閱讀