【方法一】增加動態物件陣列
1.最初物件陣列必須先存在,如 Text1(0)。
2.引數Index不可以重複。
優點:
Load 新增的控制項物件會繼承(Inheritance)原先控制項物件的屬性設定,
刪除方法:
事件觸發:
Select Case Index
Case 1
'..... 觸發的控制項
End Select
End Sub
【方法二】控制項集合(Controls collection)
Set ControlRef=Controls.Add(ProgID,Name [,Container])
2.Name 是您給控制項的名稱, (這就是控制項Name屬性所傳回名稱) 。
3.Container 為選擇性參數,是一個對收納器控制項(如PictureBox 或
4.ControlRef 為物件變數,是一個對該控制項的引用,透過此變數可
範例:
Private Sub Command1_Click()
Set textCtrl1 = Controls.Add("vb.textbox", "textCtrl1")
textCtrl1.Text = "textCtrl1"
textCtrl1.Visible = True
Set textCtrl2 = Controls.Add("vb.textbox", "textCtrl2")
textCtrl2.Top = 500
textCtrl2.Text = "textCtrl2"
textCtrl2.Visible = True
End Sub
無須最初物件陣列 textCtrl(0),便可以無中生有來動態新增控制項。
Controls.Remove Control
Private Sub Command3_Click()
UnLoadCtrl "textCtrl1"
End Sub
Dim Ctrls As Control
For Each Ctrls In Controls
If Ctrls.Name = ctrlName Then Controls.Remove Ctrls
Next
End Sub
Controls.Remove Control 只能刪除Controls.Add 所建立之物件,不然會發生執行階段錯誤 729。
事件觸發:
使用到 WithEvents 變數可以讓您對它的事件作處理。
Option Explicit
'--- textCtrl 先設定 Events
Dim WithEvents textCtrl1 As TextBox
Dim WithEvents textCtrl2 As TextBox
Private Sub textCtrl1_Change()
Me.Caption = "textCtrl1_Change"
End Sub
Private Sub textCtrl1_GotFocus()
Me.Caption = "textCtrl1_GotFocus"
End Sub
Private Sub textCtrl2_Change()
Me.Caption = "textCtrl2_Change"
End Sub
Private Sub textCtrl2_GotFocus()
Me.Caption = "textCtrl2_GotFocus"
End Sub
《問題》每一次新增控制項就要先設定 WithEvents,使用上非常不方便。
【以下範例可改良上面 WithEvents 的不方便,使用 SubClassing 方法】
Command2_Click 動態新增物件的手法
' 於表單
Option Explicit
'--- textCtrl 設定 Events
Dim WithEvents textCtrl1 As TextBox
Dim WithEvents textCtrl2 As TextBox
Private Sub Command1_Click()
Set textCtrl1 = Controls.Add("vb.textbox", "textCtrl1")
textCtrl1.Text = "textCtrl1"
textCtrl1.Visible = True
Set textCtrl2 = Controls.Add("vb.textbox", "textCtrl2")
textCtrl2.Top = 500
textCtrl2.Text = "textCtrl2"
textCtrl2.Visible = True
End Sub
'----- 新增10個 TextBox 控制項 ( Controls.Add )
Private Sub Command2_Click()
Dim txtArray As Object
Dim Index As Long
Dim str As String
'新增10個 TextBox
Index = 10
ReDim CtrlhWnd(Index - 1)
For Index = 0 To Index - 1
str = "txtArray" & Index
Set txtArray = Controls.Add("vb.textbox", str)
With txtArray
.Top = Index * 300
.Left = 1300
.Height = 280
.Width = 1000
.Text = str
.Visible = True
CtrlhWnd(Index) = .hwnd
End With
Next
'--- txtArray 設定 Events
MeProc = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
Private Sub Command3_Click()
UnLoadCtrl "textCtrl1"
End Sub
Private Sub UnLoadCtrl(ByVal ctrlName As String)
Dim Ctrls As Control
For Each Ctrls In Controls
If Ctrls.Name = ctrlName Then Controls.Remove Ctrls
Next
End Sub
Private Sub Form_Unload(Cancel As Integer)
SetWindowLong Me.hwnd, GWL_WNDPROC, MeProc
End Sub
'---------- ALL Events()
Private Sub textCtrl1_Change()
Me.Caption = "textCtrl1_Change"
End Sub
Private Sub textCtrl1_GotFocus()
Me.Caption = "textCtrl1_GotFocus"
End Sub
Private Sub textCtrl2_Change()
Me.Caption = "textCtrl2_Change"
End Sub
Private Sub textCtrl2_GotFocus()
Me.Caption = "textCtrl2_GotFocus"
End Sub
Public Sub txtArray_Change(Index As Integer)
Me.Caption = "txtArray" & Index & "_Change"
End Sub
Public Sub txtArray_GotFocus(Index As Integer)
Me.Caption = "txtArray" & Index & "_GotFocus"
End Sub
' 於模組
Option Explicit
Public Type LongToByte
B0 As Byte
B1 As Byte
B2 As Byte
B3 As Byte
End Type
Public bLong As LongToByte
Public Const WM_COMMAND = &H111
Public Const GWL_WNDPROC = (-4)
Public MeProc As Long
Public CtrlhWnd() As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case uMsg
Case WM_COMMAND
Dim Index As Integer
For Index = 0 To UBound(CtrlhWnd)
If lParam = CtrlhWnd(Index) Then
CopyMemory bLong, wParam, 4
Select Case bLong.B3
Case &H3
Form1.txtArray_Change (Index)
Case &H1
Form1.txtArray_GotFocus (Index)
End Select
End If
Next
End Select
WindowProc = CallWindowProc(MeProc, hwnd, uMsg, wParam, lParam)
End Function
