我正在尝试动态创建一个用户窗体并为其分配一个具有行为的按钮,用户窗体和按钮的生成有效,但单击按钮时的操作不起作用...... 这是我的代码(请注意,这是我第一次使用类模块,而且我对事件不熟悉):
名为 ConfPalletsLoader 的模块:
Sub CPL()
Dim fso As New FileSystemObject
Dim ConfigFile As Object
Dim ConfigLines As New Collection
Dim line As String
Dim key As String
Dim value As String
' Open the configuration file
Set ConfigFile = fso.OpenTextFile("C:\TDUFO\pallets.ini", 1)
Do Until ConfigFile.AtEndOfStream
ConfigLines.Add ConfigFile.ReadLine
Loop
ConfigFile.Close
Dim configDict As Object
Dim inFormSection As Boolean
Dim currentForm As String
Dim i As Long
Dim formInstances As Collection
Set formInstances = New Collection ' To store instances of clsDynamicForm
Dim formInstance As clsDynamicForm
' Iterate over configuration lines
For i = 1 To ConfigLines.Count
line = Trim(ConfigLines(i))
' Skip empty lines
If line = "" Then GoTo ContinueLoop
' Detect start of a new form section
If Left(line, 1) = "[" And Right(line, 1) = "]" Then
' If we're already processing a form, display it
If Not configDict Is Nothing Then
Set formInstance = New clsDynamicForm
formInstance.CreateForm configDict
formInstances.Add formInstance ' Store the instance
formInstance.ShowForm
End If
' Start a new form section
Set configDict = CreateObject("Scripting.Dictionary")
currentForm = Mid(line, 2, Len(line) - 2) ' Extract the form name
inFormSection = True
ElseIf inFormSection And InStr(line, "=") > 0 Then
key = Trim(Split(line, "=")(0))
value = Trim(Split(line, "=")(1))
configDict.Add key, value
End If
ContinueLoop:
Next i
' Ensure the last form is created after the loop ends
If Not configDict Is Nothing Then
Set formInstance = New clsDynamicForm
formInstance.CreateForm configDict
formInstances.Add formInstance ' Store the instance
formInstance.ShowForm
End If
End Sub
名为 clsDynamicForm 的 ClassModule :
Option Explicit
Private buttonHandlers As Collection ' This should persist for the lifetime of the form
Private DynamicForm As Object ' Store the dynamically created form here
Public Sub CreateForm(configDict As Object)
' Load the template UserForm and store it in the DynamicForm variable
Set DynamicForm = LoadFormInstance("TemplateUserForm")
' Initialize the button handler collection to keep handlers alive
Set buttonHandlers = New Collection
' Set the UserForm properties using Object type
With DynamicForm
.Width = CLng(configDict("FormWidth"))
.Height = CLng(configDict("FormHeight"))
.Top = CLng(configDict("FormTop"))
.Left = CLng(configDict("FormLeft"))
' Add buttons dynamically
Dim buttonIndex As Long
buttonIndex = 1
Do While configDict.Exists("Button" & buttonIndex & "Caption")
Dim btn As MSForms.CommandButton ' Ensure this is MSForms.CommandButton
Set btn = .Controls.Add("Forms.CommandButton.1")
' Set button properties
btn.Caption = configDict("Button" & buttonIndex & "Caption")
btn.Top = CLng(configDict("Button" & buttonIndex & "Top"))
btn.Left = CLng(configDict("Button" & buttonIndex & "Left"))
btn.Width = CLng(configDict("Button" & buttonIndex & "Width"))
btn.Height = CLng(configDict("Button" & buttonIndex & "Height"))
' Debugging: Check that the button is created
Debug.Print "Button created: " & btn.Caption
' Create a new button handler for each button
Dim btnHandler As clsButtonHandler
Set btnHandler = New clsButtonHandler
btnHandler.AssignButton btn
' Store the button handler in the collection to keep it in memory
buttonHandlers.Add btnHandler
' Increment the button index to create the next button
buttonIndex = buttonIndex + 1
Loop
End With
End Sub
' Show the form modelessly
Public Sub ShowForm()
DynamicForm.Show vbModeless
End Sub
' Helper function to load a new instance of a UserForm by name
Private Function LoadFormInstance(formName As String) As Object
Dim frm As Object
Set frm = VBA.UserForms.Add(formName) ' Load a new instance of the template UserForm
Set LoadFormInstance = frm ' Return the loaded UserForm instance
End Function
名为 clsButtonHandler 的 ClassModule :
Option Explicit
' This class will handle the button click events
Private WithEvents Button As MSForms.CommandButton ' Ensure this is CommandButton
' Assign the button to the class
Public Sub AssignButton(ByVal btn As MSForms.CommandButton)
Set Button = btn
Debug.Print "Button assigned: " & btn.Caption ' Ensure the button is assigned
End Sub
' Handle the click event of the button
Private Sub Button_Click()
MsgBox "Button clicked: " & Button.Caption, vbInformation
Debug.Print "Button clicked: " & Button.Caption
Call ButtonClickedSub
End Sub
名为 TemplateUserForm 的 UserForm,为空。
如果您需要运行我的代码,这是pallets.ini 包含的内容(C:\TDUFO\pallets.ini):
[Form1]
FormWidth = 300
FormHeight = 200
FormTop = 100
FormLeft = 100
Button1Caption = "Button 1"
Button1Top = 30
Button1Left = 50
Button1Width = 80
Button1Height = 30
项目的活跃参考:
您知道为什么不调用“按钮单击”例程吗?
问题在于
formInstance
的范围为 CPL()
。 当 CPL()
完成时,参考就被破坏了。
Dim formInstance As clsDynamicForm
使
formInstance
变量Static
将使变量引用保持活动状态,但最好将其设为模块级变量。
Static formInstance As clsDynamicForm