网摘》控件数组
控件數組(針對 Visual Basic 6.0 用戶)
在 Visual Basic 6.0 中,控件數組可用于管理窗體上的控件;它們提供的功能可共享事件處理程序、循環訪問控件組以及在運行時添加控件。
Visual Basic 2008 中不再支持控件數組。對事件模型的更改使控件數組不再必需,而且 .NET Framework 提供了相同的功能來處理控件。
共享事件處理程序
在 Visual Basic 6.0 中,控件數組可用于指定一組共享事件集的控件。這些控件應該為相同的類型,并且具有相同的名稱。
Visual Basic 2008 允許使用任何事件處理程序處理來自多個控件的事件,甚至是具有不同名稱和不同類型的控件。
例如,可以向窗體添加兩個 Button 控件(Button1 和 Button2)以及一個 CheckBox 控件 (CheckBox1),然后創建一個事件處理程序來處理這三個控件的 Click 事件。
Private Sub MixedControls_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click, Button2.Click, CheckBox1.Click
循環訪問控件
Visual Basic 6.0 控件數組的另一個功能是使用 Index 屬性循環訪問控件組。例如,若要清除控件數組中所有 TextBox 控件的文本,可將 Index 屬性作為循環變量循環訪問控件數組。
Visual Basic 2008 控件沒有 Index 屬性,但仍可使用 Control 類的 Control.ControlCollection 循環訪問窗體或容器上的控件。
在 Visual Basic 6.0 中,單個控件數組中的控件可位于不同容器上。例如,兩個不同 Frame 控件上包含的 TextBox 控件可以是同一控件數組的元素。
在 Visual Basic 2008 中,Controls 集合僅返回位于同一容器上的控件。必須分別循環訪問每個容器控件的控件;可使用遞歸函數完成此操作。
在運行時添加控件
在 Visual Basic 6.0 中,可使用 Load 語句在運行時向控件數組添加控件??丶仨毢涂丶到M是同一類型,并且控件數組必須在設計時創建,且必須帶有至少一個元素。添加控件后,必須將 Visible 屬性設置為 True。
在 Visual Basic 2008 中,通過在 Dim 語句中使用 New 關鍵字,然后將 Add 方法用于要添加控件的容器,可在運行時添加控件。
在運行時添加事件處理程序
在 Visual Basic 6.0 中,在運行時向控件數組添加控件時,控件數組的事件自動處理新控件事件。
在 Visual Basic 2008 中,需要為運行時添加的控件定義事件處理程序??墒褂?AddHandler 語句完成此操作。
控件數組的代碼更改
下面的代碼演示 Visual Basic 6.0 與 Visual Basic 2008 在編碼方法方面的差異。
共享事件處理程序
下面的示例演示如何為一組三個 TextBox 控件共享 Change 事件處理程序(Visual Basic 2008 中為 TextChanged)。在 Visual Basic 2008 中,事件處理程序的 Handles 子句指定事件將處理的控件。事件處理程序返回一個泛型 Object,因此必須強制轉換為要使用 Object 方法處理的特定對象類型(在本例中為 TextBox)。
' Visual Basic 6.0
Private Sub Text1_Change(Index As Integer)
Select Case Index
Case 0
MsgBox("The text in the first TextBox has changed")
Case 1
MsgBox("The text in the second TextBox has changed")
Case 2
MsgBox("The text in the third TextBox has changed")
End Select
End Sub
' Visual Basic
Private Sub TextBoxes_TextChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles TextBox1.TextChanged, _
TextBox2.TextChanged, TextBox3.TextChanged
??? Select Case DirectCast(sender, TextBox).Name
??????? Case TextBox1.Name
??????????? MsgBox("The text in the first TextBox has changed")
??????? Case TextBox2.Name
??????????? MsgBox("The text in the second TextBox has changed")
??????? Case TextBox3.Name
??????????? MsgBox("The text in the third TextBox has changed")
??? End Select
End Sub
【說明】事件行為在 Visual Basic 2008 中略有不同。初始化每個控件時(例如在 Form_Load 中)以及運行時更改文本時,引發 TextChanged 事件。在 Visual Basic 6.0 中,僅當文本發生更改時引發 Change 事件。
循環訪問控件
下面的示例演示循環訪問一組文本框控件并清除它們的文本的函數。在 Visual Basic 6.0 示例中,控件數組的 Index 屬性用作循環變量。
在 Visual Basic 2008 中,Control 對象作為參數傳遞;它具有一個包括該控件上所有控件的 Control.ControlCollection 集合。Typeof 運算符用于確定每個控件是否是 TextBox 類型。
【說明】Form 對象是 Control 類型;也可將 Form 作為參數傳遞。
因為 Control.ControlCollection 集合中不包括嵌套控件,所以使用 HasChildren 方法確定每個控件是否包含其他控件,如果包含則遞歸調用 ClearText 函數。
' Visual Basic 6.0
Private Sub ClearText()
For i = 0 To Text1().UBound
Text1(i).Text = ""
Next
End Sub
' Visual Basic
Private Sub ClearText(ByVal container As Control)
??? Dim ctrl As Control
??? For Each ctrl In container.Controls
??????? If TypeOf (ctrl) Is TextBox Then
??????????? ctrl.Text = ""
??????? End If
??????? If ctrl.HasChildren Then
???????????? ClearText(ctrl)
??????? End If
??? Next
End Sub
在運行時添加控件
下面的示例演示如何在運行時向窗體添加文本框控件。在 Visual Basic 6.0 中,控件添加到控件數組。在 Visual Basic 2008 中,該控件會添加到 Control.ControlCollection 集合。在 Visual Basic 6.0 中,新 TextBox 的事件由控件數組自動處理。在 Visual Basic 2008 中,需要通過 AddHandler 語句掛鉤事件處理。
兩個示例都假定文本框控件是在設計時添加到窗體中的,在 Visual Basic 6.0 示例中還假定創建了一個單元素控件數組。Visual Basic 2008 示例還假定對于第一個 TextBox 控件,存在名為 TextChangedHandler 的事件處理程序。
' Visual Basic 6.0
Private Sub AddControl()
' Add a TextBox as the second element of a control array.
Load Text1(1)
' Set the location below the first TextBox.
Text1(1).Move Text1(0).Left, Text1(0).Top + 500
' Make the new TextBox visible
Text1(1).Visible = True
' Visual Basic
' Declare a new TextBox.
Dim TextBox2 As New TextBox
' Set the location below the first TextBox
TextBox2.Left = TextBox1.Left
TextBox2.Top = TextBox1.Top + 30
' Add the TextBox to the form's Controls collection.
Me.Controls.Add(TextBox2)
AddHandler TextBox2.TextChanged, AddressOf TextChangedHandler
http://msdn.microsoft.com/zh-cn/library/kxt4418a(v=vs.90).aspx ? ?控件數組正確使用方法分析
創建數據驅動窗體
所謂數據驅動窗體就是根據所請求的數據的不同生成相應的窗體。舉例來講,假設你現在有一個數據庫,其中有些字段必須根據登錄者的身份加以顯示,授權級別高的用戶可以瀏覽并修改這些字段的內容;授權級別一般的用戶只能瀏覽這些字段中的數據;授權級別低的用戶則不能瀏覽這些字段中的內容。要做到這一點就得利用VB動態添加控件的功能。
動態創建控件
無論你想要創建何種類型的數據驅動窗體,你必須知道如何在運行時動態地創建控件。你可以通過控件數組做到這一點,但 VB6的Controls集合所提供的Add方法,功能更強大,靈活性更高。使用該方法,你不需要在設計時將控件的實例放在窗體上。實際上,用Add方法 你甚至可以創建程序在編譯時根本不存在的控件。這種方法的用法也很簡單:
‘ 聲明一個窗體級的變量
Dim WithEvents txtTotal As TextBox
?
Sub CreateTextbox()
‘ 創建新的Textbox控件
Set txtTotal = Controls.Add("VB.TextBox", "txtTotal")
‘ 將控件移動到你所需要的地方
txtTotal.Move 1000, 800, 1200, 300
‘ 創建時,所有的控件都是不可見的
txtTotal.Visible = True
End Sub
請注意Add方法的第二個參數:分配給控件的名稱。從代碼可讀性出發,這個名稱一般都與變量名相同。你可以用這個名稱從Controls集合中獲取相應的控件或移除該控件。例如:
Controls.Remove "txtTotal"
在變量聲明時加上WithEvents關鍵字,即使在設計時窗體不存在該控件,你也可以為該控件的事件編寫代碼。
上面所講的方法只適合解決VB內置的控件。例如,當你要添加一個TreeView控件時,VB會要求你證明你已經得到了合法的授權來創建該控件的實例。換句話說,VB要證明這個控件是買來的,而不是從其它附有該控件的程序中借來的。
要證明你經過了合法的授權有下面幾種方法:
在窗體上放置一個控件。這也是最簡單的方法。你完全沒有必要將這個窗體顯示出來。
將相關的控件添加到工具箱中,然后在“工程屬性”對話框的“生成”標簽頁中取消選擇“刪除有關未使用的ActiveX控件的信息”這一項。
向Licenses集合添加一個元素。例如:Debug.Print Licenses.Add("MSMask.MaskedEdBox")
僅僅創建了控件并不足夠
要創建一個數據驅動窗體,僅僅知道動態創建控件還不夠。例如:現在你要創建一個能根據數據庫中表的不同字段自動生成控件的窗體。該窗體可能會創建單行文本框,其長度隨字段長度不同而不同;也可能會創建單選按鈕或復選按鈕以顯示布爾型字段;甚至可能創建一個多行文本框顯示備注型字段。
你需要解決的第一個問題是:文本框控件的Multiline屬性在運行時是只讀的,只在設計時可用。幸好,微軟的Microsoft Windowless Controls 6.0可以解決這個問題。這組控件集包括了輕量級的TextBox,ComboBox,ListBox,CheckBox,OptionButton, CommandButton和兩個scrollbar控件。這些控件與VB內置的相應的控件最大的區別在于:這些控件的所有屬性在運行時是可讀寫的。在 VB的安裝光盤中的Common\Tools\VB\WinLess文件夾中可以找到這個控件組。用下面的代碼可以創建一個多行文本框:
?
Dim WithEvents txtEditor As MSWLess.WLText
?
Private Sub CreateEditor()
Set txtEditor = Controls.Add( "MSWLess.WLText", "txtEditor")
txtEditor.Move 0, 0, 4000, 4000
txtEditor.MultiLine = True
txtEditor.ScrollBars = wlBoth
txtEditor.Visible = True
End Sub
另外一個問題比較復雜:在事先不知道要創建多少個控件的情況下,如何給每個對新創建的控件的引用分配唯一的帶WithEvents關鍵字的變量。換句話說就是要對新創建的控件的事件進行編程,前提是你在設計時不知道程序會創建多少個控件。使用對象數組顯然不行,因為不能用WithEvents關鍵字聲明一個對象數組;更壞的情況是,資一個變量定義為As Control或As Object也不行,因為還是不能用WithEvents。
問題源自于我們無法在運行時捕獲一個對象數組事件。所以我們只能采取曲線救國的辦法。所要的編寫的代碼可能比你想象的多,不過這個解決方法很有趣,值得我們這樣去做。
我們需要兩個輔助類模塊來捕獲事件,分別取名為ControlItems和ControlItem。ControlItems是一個集合類,其中保存了 ControlItem對象及其數量。該數量等于你所要對之編程的控件的數量。ControlItem類的每一份實例捕獲控件產生的事件,然后調用在其所屬的ControlItems集合類中的過程,最后由ControlItems在窗體中觸發事件并執行事件中的代碼。整個過程如下圖所示:
捕獲多個控件的事件
為簡單起見,假設你要捕獲來自所有的動態添加到窗體上去的控件的Validate事件。為完成這個工作,ControlItems集合類必須向父窗體展示該事件,并隨時準備接收來自其子ControlItem類的通知以觸發事件。代碼如下:
?Event Validate(CtrlItem As ControlItem, Cancel As Boolean)
Private m_ControlItems As New Collection
?
‘ 向集合中添加一個新的ControlItem項目
Function Add(ctrl As Control) As ControlItem
Dim newItem As New ControlItem
newItem.Init ctrl, Me
‘ 添加到私有類
m_ControlItems.Add newItem
‘ 返回新項目給調用者
Set Add = newItem
End Function
?
Friend Sub Notify_Validate(Item As ControlItem, Cancel As Boolean)
RaiseEvent Validate(Item, Cancel)
End Sub
ControlItem 類必須捕獲來自動態添加到窗體中的控件的事件,并通知其所屬的ControlItems集合類。很顯然,ControlItem類必須有一個用 WithEvents關鍵字定義的變量來引用真正的控件。這意味著你不能將變量聲明為As Control或As Object。如果你決定在窗體中所動態添加的控件不使用VB內置的控件的話,這個問題的解決辦法相當的簡單。你只需要將變量聲明為 VBControlExtender類型就行了。對于創建數據驅動窗體來講,不使用VB內置的控件并不是一件大不了的事。
將變量聲明為 VBControlExtender,并加上WithEvents關鍵字,你就能直接捕獲Validate,GotFocus,LostFocus, DragDrop和DragOver這幾個事件了。如果要捕獲其它更多的事件,你可以使用ObjectEvent。下面是ControlItem類模塊中 的代碼:
?Public WithEvents Ctrl As VBControlExtender
‘ 所屬的ControlItems對象
Dim m_Parent As ControlItems
?
Sub Init(ctl As Object, parnt As ControlItems)
Set Ctrl = ctl
Set m_Parent = parnt
End Sub
?
Private Sub Ctrl_Validate(Cancel As Boolean)
‘ 通知所屬的ControlItems類
m_Parent.Notify_Validate Me, Cancel
End Sub
將下面的代碼放入窗體中,就可以捕獲動態添加的控件所產生的事件了:
?
Dim WithEvents CtrlItems As New ControlItems
?
Private Sub cmdCreateControls_Click()
Dim ctrl As Control
‘ 創建兩個文本框并將它們添加到ControlItems集合? Set ctrl = Controls.Add("MSWLess.WLText", "One")
ctrl.Move 100, 200, 1000, 300
ctrl.Visible = True
CtrlItems.Add ctrl
‘ 注意你可以使用同一個變量
Set ctrl = Controls.Add("MSWLess.WLText", "Two")
ctrl.Move 100, 800, 1000, 300
ctrl.Visible = True
CtrlItems.Add ctrl
End Sub
?
Private Sub CtrlItems_Validate( CtrlItem As ControlItem, Cancel As Boolean)
‘ 拒絕空字符串 - 注意如何引用控件的屬? If CtrlItem.Ctrl.Text = ""
Then Cancel=True
End Sub
?
現在解決了最困難的部分,要創建一個數據驅動窗體就變得簡單了
****************************************************************
動態添加控件
VB6有一個新功能,可以動態添加控件,不用控件數組:
object.Add (ProgID, name, container)
參數說明
Object 必需的。一個對象表達式,其值是“應用于”列表中的一個對象。
ProgID 必需的。一個標識控件的字符串。大多數控件的 ProgID 都可通過查看對象瀏覽器來決定??丶?ProgID 是由控件的庫和類組成的。
例如,CommandButton 控件的 ProgID 是 VB.CommandButton。在ProgID 與對象瀏覽器中所顯示的不一樣的情況下,Visual Basic
將顯示一個包括正確 ProgId 的錯誤信息。
name 必要的。一個字符串,用來標識集合的成員。
container 可選的。一個對象引用,它指定控件的容器。如果沒有指定或為NULL,缺省值為 Controls 集合所屬的容器。通過指定該參數,可以把一個控件放置在任何現存的容器控件(如 Frame 控件)中。用戶控件或 ActiveX 文檔也可以作為一個容器。
?
舉例: //在picture1上面添加一個commandbutton
Private Sub Form_Load()
Form1.Controls.Add "VB.CommandButton", "cmdOk", Picture1
With Form1!cmdOk
.Visible = True
.Width = 500
.Caption = "確認(&Y)"
End With
End Sub
?
重點:當您添加一個未引用的需要許可證的控件到一個現存的(已部署好的)應用程序時,在使用 Add 方法之前您必須也添加這個控件的許可證關鍵字。
在運行時添加未引用的控件:
您也可以利用 Add 方法來動態添加一個在工程中沒有被引用的控件。(“未引用的”控件是不出現在 Toolbox 中的控件)。為此,您必須也把控件的License 關鍵字添加到 Licenses 集合中。下面的示例中在添加控件本身之前添加了控件的許可證關鍵字:
Option Explicit
Private WithEvents extCtl As VBControlExtender
?
Private Sub Form_Load()
Licenses.Add "prjWeeks.WeeksCtl", "xydsfasfjewfe"
Set extCtl = Form1.Controls.Add("prjWeeks.WeeksCtl", "ctl1")
extCtl.Visible = True ‘ The control is invisible by default.
End Sub
?
但是,為了編程這樣一個未引用控件的事件,您必須使用 WithEvents 關鍵字聲明一個對象變量為VBControlExtender 對象(如上),并且設置該對象變量到Add 方法返回的引用上。然后,利用VBControlExtender 對象的 ObjectEvent事件來編程該控件的事件。下面是一個簡單的例子。
?
Option Explicit
Dim WithEvents objExt As VBControlExtender ‘聲明 Extender 變量
?
Private Sub LoadControl()
Licenses.Add "Project1.Control1", "xydsfasfjewfe"
Set objExt = Controls.Add("Project1.Control1", "myCtl")
objExt.Visible = True
End Sub
?
Private Sub extObj_ObjectEvent(Info As EventInfo)
‘使用 Select Case 編程控件的事件。
Select Case Info.Name
Case "Click"
‘這里處理 Click 事件。
‘現在顯示其他的 case
Case Else ‘未知事件
‘這里處理未知事件。
End Select
End Sub
Note: 不能把一個固有的控件指定給這個 VBControlExtender 變量; 任何這種試圖將引起類型不匹配錯誤。
但是,您也可以通過使用 WithEvents 關鍵字聲明一個對象變量,并且設置該方法返回的引用為該變量,從而編程一個動態添加控件的事件,如下所示。
Option Explicit
‘聲明對象變量為 CommandButton 。
Private WithEvents cmdObject As CommandButton
?
Private Sub Form_Load()
Set cmdObject = Form1.Controls.Add("VB.CommandButton", "cmdOne")
cmdObject.Visible = True
cmdObject.Caption = "Dynamic CommandButton"
End Sub
?
Private Sub cmdObject_Click()
Print "This is a dynamically added control"
End Sub
如果希望添加一個用戶控件或任何 ActiveX 控件到您的窗體,必須或者把這個控件添加到“工具箱”,或者把控件的 License 關鍵字添加到 Licenses集合中。有關詳細信息請參閱“增加方法 (Licenses 集合)”。
注意:如果您添加一個 ActiveX 或用戶控件到您的工程,但是沒有在窗體中使用它,您也必須不要選定“工程屬性”對話框的“生成” 選項卡上的“刪除有關未使用的 ActiveX 控件”選項。如果您的應用程序試圖添加該控件,那么該 Add 方法將失敗,因為必需的信息已經被丟棄。
http://blog.csdn.net/yuan_haijiang/article/details/7392468
?
?
?
VB控件數組的操作技巧(混合文本)
控件數組有在設計時設置好的,也有在運行中創建的。控件數組一方面使得程序簡潔、令代碼易于維護,另一方面能使程序具有靈活性??梢?#xff0c;科學地利用控件數組可使編程工作的效率更高。本文是從筆者回答網友的問題中整理出來的,與原來的回答相比略有改動。希望這些"技巧"對大家有些幫助。如有不妥之處,敬請指教。
一、運行中設置數組控件的屬性
設窗體上有若干個以?Command1?命名的命令按鈕,現要求:點擊其中一個按鈕后,該按鈕不可用,而其它的按鈕均可用。以下幾行代碼可以實現這個要求,比一個一個的設置高效得多。
Private?Sub?Command1_Click(Index?As?Integer)
????Dim?i?As?Integer?'計數器
????Dim?comNum?As?Integer?'按鈕的索引號
????comNum?=?0
????For?i?=?0?To?Command1.Count?-?1
????????comNum?=?comNum?+?1
????????If?comNum?>?Command1.Count?-?1?Then?comNum?=?0
????????Command1(comNum).Enabled?=?True?'讓所有按鈕可用
????Next
????Command1(Index).Enabled?=?False?'讓被單擊按鈕不可用
End?Sub
二、運行中添加和卸載數組控件
窗體上已有一個文本框Text1,程序需要在運行時動態地創建若干文本框,可這樣實現:
1.首先,設計時給Text1的Index屬性設置為"0",這一步很重要:有了索引號才能創建數組控件;
2.編寫代碼:[之前請給工程添加兩個命令按鈕,Name屬性取缺省值,Caption屬性分別為:添加、卸載]
Private?Sub?Command1_Click()
????Dim?txtNum?As?Integer?'Text1的Index號
????Dim?Num?As?Integer?'賦給各TextBox的值
????txtNum?=?0?'初值
????Num?=?1?'初值
????Text1(0).Text?=?"Text"?&?Num?'第一個Text1的值
????Dim?i?As?Integer?'計數器
????For?i?=?0?To?4?'添加五個TextBox
????????txtNum?=?txtNum?+?1
????????Num?=?Num?+?1
????????Load?Text1(txtNum)?'加載文本框
????????Text1(txtNum).Top?=?Text1(txtNum?-?1).Top?+?450?'設置位置
????????Text1(txtNum).Text?=?"Text"?&?Num?'加載內容
????????Text1(txtNum).Visible?=?True?'令其可見:不能漏
????Next
????Command1.Enabled?=?False
????Command2.Enabled?=?True
End?Sub
?
Private?Sub?Command2_Click()
????Dim?i?As?Integer,?N?As?Integer
????N?=?0
????For?i?=?1?To?Text1.Count?-?1
????????N?=?N?+?1
????????Unload?Text1(N)
????Next
????Command1.Enabled?=?True
????Command2.Enabled?=?False
End?Sub
三、給運行中添加的數組控件命名并編寫事件
其實例二已經給數組控件命了名,只是簡單了些。本例將文件夾"F:\Txt"下的所有.txt的文件名作為菜單的Caption添加到菜單項里[請事先建立此文件夾并拷貝一些.txt文件,或者更改代碼],當點擊這些菜單,程序將調出Windows的記事本打開相應的文件。
鍵入以下代碼前請啟動VB的菜單編輯器,建立一個父菜單項[Naem和Caption屬性任意],然后在此父菜單下建立一個子菜單,Name屬性為"mnuFiles",Caption屬性為"沒有文件"。
Dim?MyPath?As?String?'路徑名變量
'添加并命名菜單過程
Private?Sub?AddMenu()
????Dim?MenuNum?As?Integer?'菜單索引號變量
????Dim?MyFiles?As?String?'文件名變量
????MenuNum?=?0?'初值
????MyFiles?=?Dir(MyPath?+?"*.txt")?'僅查找文本文檔
????If?MyFiles?=?""?Then?Exit?Sub?'為空則退出過程
????mnuFiles(0).Caption?=?MyFiles?'給第一個菜單命名
????Do?Until?MyFiles?=?""
????????MyFiles?=?Dir()
????????If?MenuNum?=?0?Then?MenuNum?=?1
????????MenuNum?=?MenuNum?+?1
????????Load?mnuFiles(MenuNum)?'加載菜單
????????mnuFiles(MenuNum).Visible?=?True?'設置為可見:不能漏
????????mnuFiles(MenuNum).Caption?=?MyFiles
????????If?mnuFiles(MenuNum).Caption?=?""?Then?Unload?mnuFiles(MenuNum)
????????'若菜單名為空則卸載掉
????Loop
End?Sub
Private?Sub?Form_Load()
????MyPath?=?"F:\Txt\"?'規定路徑
????Call?AddMenu?'執行添加菜單過程
End?Sub
Private?Sub?mnuFiles_Click(Index?As?Integer)
????Dim?ret?As?String
????'用Windows的記事本打開文件:注意中間的空格不能少
????ret?=?"Notepad.exe"?&?"?"?&?MyPath?&?mnuFiles(Index).Caption
????Shell?ret,?vbNormalFocus
End?Sub
四、控件在窗體上的排列問題
曾有一位網友兩次問土人怎樣才能在窗體上添加100萬個文本框。呵呵,這要多大的顯示器才能顯示出來呀!不過,添加的數組控件多了,排列確實是個問題。下面的例子給窗體添加499個Label控件,連同事先繪制好的Index號定義為0的控件,總共有500個,能在窗體上從左到右、從上到下整齊地排列。程序運行時要花些許時間。
Option?Explicit
Private?Sub?Form_Load()
????Me.Width?=?6800
????Me.Height?=?6000
????Me.Caption?=?"添加標簽演示"
????With?Label1(0)
????????.Top?=?0
????????.Left?=?120
????????.Height?=?200
????????.Width?=?300
????????.Caption?=?""
????End?With
????AddLabels
End?Sub
Private?Sub?AddLabels()
????Dim?i?As?Integer?'計數器
????Dim?Num?As?Integer?'Label的Index號
????Dim?k?As?Integer?'判斷是否滿行
????Dim?n?As?Integer?'行數計數器
????Num?=?0
????k?=?0
????n?=?0
????Label1(0).Caption?=?Num?+?1
????For?i?=?1?To?499
????????Num?=?Num?+?1
????????Load?Label1(Num)?'加載Label控件
????????Select?Case?k
????????????Case?0
????????????????Label1(Num).Left?=?Label1(Num?-?1).Left?+?Label1(0).Width?+?20
????????????????If?Num?=?20?Then?n?=?n?+?1:?k?=?n
????????????Case?n
????????????????Label1(n?*?20).Left?=?120
????????????????Label1(n?*?20).Top?=?Label1(0).Height?*?n
????????????????Label1(Num).Top?=?Label1(0).Height?*?n
????????????????Label1(Num).Left?=?Label1(Num?-?1).Left?+?Label1(0).Width?+?20
????????????????If?Num?=?(n?+?1)?*?20?Then?n?=?n?+?1:?k?=?n
????????End?Select
????????Label1(Num).Caption?=?Num?+?1
????????Label1(Num).Visible?=?True
????Next
End?Sub
一個問題的實例
回答人的補充
后面那代碼,是告訴你什么情況用Select?Case。
那就不能這樣做了,2個的index是不同的,改為:
?
Private?Sub?Command1_Click()
????Dim?i,?r,?s?As?Integer
????Dim?p?As?Long
????For?i?=?0?To?2
????????If?Option1(i).Value?Then
????????????Select?Case?i
????????????????Case?0:?s?=?100
????????????????Case?1:?s?=?120
????????????????Case?2:?s?=?160
????????????End?Select
????????End?If
????Next
????For?i?=?0?To?3
????????If?Option2(i).Value?Then
????????????Select?Case?i
????????????????Case?0:?r?=?3000
????????????????Case?1:?r?=?3000?*?1.1
????????????????Case?2:?r?=?3000?*?1.2
????????????????Case?2:?r?=?3000?*?1.3
????????????End?Select
????????End?If
????Next
????p?=?r?*?s
????Label1.Caption?=?"根據所選房價應為:¥"?&?p
End?Sub
?
1.將多個控件取相同的名稱
具體操作步驟是:
1)繪制或選擇要作為一個控件數組的所有控件,必須保證它們為同一類型的控件。
2)決定哪一個控件作為數組中的第一個元素,選定該控件并將其Name屬性值設置成數組名(或使用其原有的Name屬性值)。
3)將其他控件的Name屬性值改成同一個名稱。這時,Visual?Basic會顯示一個對話框,要求確認是否要創建控件數組,選擇“是”則將控件添加到控件數組中。
例如,若原有三個文本框Text1、Text2、Text3,要將它們設置成控件數組,數組名稱為TT,則選擇第一個文本框Text1,將其Name屬性修改成TT,然后再選擇Text2,再將其Name屬性改成TT,這時會出現下圖所示的對話框,單擊“是(Y)”?按鈕將Text2添加到控件數組中。在屬性窗口中可以看出原Text1和Text2文本框的名稱都變成了TT。同樣將Text3的名稱也改成TT,這時不再出現提示對話框,而直接將Text3的名稱改成TT。觀察各控件的屬性窗口中的Index屬性,其值分別變成了0、1、2(即控件數組元素的索引)。
?
圖?通過修改控件名稱建立控件數組
用這種方法建立的控件數組元素僅僅具有相同的Name屬性和控件類型,其他屬性與最初繪制控件時的值相同。
?
2.復制現有的控件,并將其粘貼到所在容器中
具體操作步驟是:
1)在容器(如窗體)中繪制或選擇要作為控件數組的第一個控件。
2)選擇“編輯”菜單中的“復制”命令(或單擊標準工具欄的“復制”按鈕),然后選中容器,再在“編輯”菜單中選擇“粘貼”命令(或單擊標準工具欄的“粘貼”按鈕)。Visual?Basic同樣會顯示與上圖類似的對話框,單擊“是(Y)”按鈕,確定要創建一個控件數組。
這時,繪制的第一個控件具有索引值0,而新粘貼的控件的索引值為1。以后可以繼續使用粘貼的方法向現有的數組中添加控件,只是不再出現提示對話框,直接將新粘貼的控件作為控件數組的下一個元素。每個新數組元素的索引值與其添加到控件數組中的次序相同。用這種方法添加控件時,大多數可視屬性,例如高度、寬度和顏色,將從數組中第一個控件復制到新控件中。
?
3.給控件設置一個Index屬性值
具體操作步驟是:
1)繪制或選擇要作為控件數組的第一個控件。
2)在屬性窗口中直接指定一個Index屬性值(如設置為0)。
3)使用以上兩種方法之一添加數組中的其他控件,這時不再出現提示對話框詢問是否要創建控件數組。
建立了控件數組之后,可以通過修改Index屬性值修改相應控件在數組中的位置。當然,必須保證同一個控件數組中的各元素的Index屬性值是惟一的。
Visual?Basic控件數組的使用示例 - - - 同時移動一組圖形
【例】創建圖形控件數組S1,包含6個圓,當按下“移動”按鈕時,所有圓全部向下移動100緹,當移動到窗體底部時,返回窗體頂部。界面如下圖所示。
?
圖?同時移動一組圖形
分析:移動操作在單擊“移動”按鈕(設名稱為Command1)時進行,因此,代碼應寫在“移動”按鈕的Click事件過程中。這里要特別注意的是,“移動”按鈕不是控件數組元素,因此,其事件過程不會返回Index參數值,也就是在其事件過程中不可以使用Index參數,這里可以用循環變量控制控件數組的索引,通過循環逐個移動圖形。
“移動”按鈕的Click事件過程如下:
?
Private?Sub?Command1_Click()
????For?I?=?0?To?5
????????If?S1(I).Top?+?S1(I).Height?>?Form1.ScaleHeight?Then
????????????'?當圖形底部超過窗體底部時,將圖形移回窗體頂部
????????????S1(I).Top?=?0
????????Else
????????????'?當圖形底部未超過窗體底部時,將圖形向下移動100緹
????????????S1(I).Top?=?S1(I).Top?+?100
????????End?If
????Next?I
End?Sub
?
對于不關心處理次序的控件數組,也可以使用For?Each...Next循環進行處理,例如,上例移動圖形無先后次序問題,程序可以改寫成:
?
Private?Sub?Command1_Click()
????For?Each?X?In?S1
????????If?X.Top?+?X.Height?>?Form1.ScaleHeight?Then
????????????X.Top?=?0
????????Else
????????????X.Top?=?X.Top?+?100
????????End?If
????Next?X
End?Sub
?
?
?
?
各位大神,感謝前幾次的幫助,另有一個問題
圖1圖2
如圖所示,現在有opt1(i)??20個數組控件,正常情況下20個控件都是可以編輯的(opt1(i).Enabled=true),20個控件相連返回結果為true,如圖1所示??????如果因為其它原因導至其中一個或者多個不可編(opt1(i).Enabled=false),造成數組不相連,這樣如何來檢測這些數組中有哪些為不可編輯的,并在彈出的Msgbox中指出不可編輯的地方,如圖2所示
?
樓主看看這個:
Option Explicit
?
Private Function CheckOpt(ByRef strRetVal As String) As Boolean
?? Dim strTemp As String
?? Dim i&, c&
?? strTemp = String(60, "-")
?? c = 0
?? For i = opt1.LBound To opt1.UBound
????? If (opt1(i).Enabled) Then
???????? c = c + 1
????? Else
???????? Mid$(strTemp, i * 3 + 1, 2) = opt1(i).Caption
????? End If
?? Next
?? i = opt1.Count
?? If (i > c) Then
????? strTemp = Replace(strTemp, "-2", " 2")
????? strTemp = Replace(Replace(strTemp, "-1", " 1"), "-0", " 0")
????? strRetVal = Replace(strTemp, "-", "")
?? End If
?? CheckOpt = i = c
End Function
?
' 調用示例
Private Sub Command1_Click()
?? Dim strMSG As String
?? If (CheckOpt(strMSG)) Then
????? MsgBox "全部可編輯!", 64
?? Else
????? MsgBox "以下不可編輯:" & strMSG, 48
?? End If
End Sub
?
If?(i?>?c)?Then??......?End?if?那段可以這樣改下:
If?(i?=?c)?Then
???strRetVal?=?""
Else
???strTemp?=?Replace(strTemp,?"-2",?"?2")
???strTemp?=?Replace(Replace(strTemp,?"-1",?"?1"),?"-0",?"?0")
???strRetVal?=?Replace(strTemp,?"-",?"")
End?If
總結
- 上一篇: [软件更新]MediaCoder(影音转
- 下一篇: wamp5 Apache启动失败的解决方