我有一个UserForm
,我在其中添加了一个带有足够的Let和Get语句的属性。当房产发生变化时,我希望事件发生。已在RaiseEvent
模块中声明了事件UserForm
和例程。但是,我无法找到将例程分配给事件的方法。
据我所知,这与通常的类模块中的自定义事件情况不同,因为它未在类模块中声明,其类I可以在常规模块中实例化。我的所有搜索都提供了类模块中的自定义事件或UserForms中的内置事件的示例,但没有关于UserForms中自定义事件的材料。
这实际上让我想知道是否可以在UserForms和Private Subs中创建自定义事件来处理这些事件。那有可能吗?如果是这样,我错过了什么?如何让Private Sub UFStatus_StatusChange()
处理此事件?
任何帮助都会被贬低!
到目前为止,代码都在UserForm模块中:
Public Event StatusChange (old_status As Long, current_status As Long)
Dim old_status As Long
Private current_status As Long
Public Property Let UFStatus (RHS As Long)
old_status = current_status
current_status = RHS
RaiseEvent StatusChange(old_status, current_status)
End Property
Private Sub UFStatus_StatusChange()
MsgBox("Status changed from " & old_status & "to " & current_status)
End Sub
答案 0 :(得分:11)
是的,但您需要了解VBA / COM事件的工作原理。
请注意VBE代码窗格顶部的下拉/组合框?最左边的列出了所有可用的接口和事件提供程序 - 最右边的列出了可用的成员和事件通过最左边的下拉菜单中选择的任何内容进行曝光。
因此,当您在Click
的代码隐藏中处理某些OkButton
的{{1}}事件时,处理程序存根可能如下所示:
UserForm1
无论您是实现接口还是处理事件,签名都以非常特殊的方式构建,始终以相同的方式构建:
Private Sub OkButton_Click()
End Sub
这是重要的。无论您做什么,不要使用包含下划线的标识符命名事件(或接口成员)。在事件的情况下,您将遇到编译错误:
编译错误:无效的事件名称
对于接口,你也会遇到编译错误,VBE抱怨接口成员没有实现。
这就是为什么VB中的所有内容都是Private Sub [Provider]_[MemberName]([Args])
而不是PascalCase
。坚持惯例,避免公开成员名称中的下划线。
如果你不知道是什么接口,为什么我提到他们在一个有关事件后,在查找Upper_Snake_Case
关键字,知道接口和事件是非常密切相关的和工作在一个非常相似的时装,并继续阅读; - )
任何类都可以定义事件。一个Implements
是一个类,它可以绝对定义事件,是的。您可以使用UserForm
关键字
Event
定义事件的类是事件提供程序 - 它是唯一允许引发它定义的事件的类。
您使用Public Event SomethingHappened(ByVal SomeArg As Long)
关键字引发事件,并提供参数:
RaiseEvent
你举起活动的时间和原因完全取决于你的想象力。
考虑Private Sub OnSomethingHappened()
RaiseEvent SomethingHappened(42)
End Sub
上Click
的{{1}}事件:CommandButton
类可能有一个侦听涉及鼠标的Win32消息的方法,当它决定时要处理左键单击,它会引发其UserForm
事件,而某事并且CommandButton
过程会运行。正确?
MSForms自动为您做的部分是,当您在表单上添加Click
并将其命名为OkButton_Click
时,此CommandButton
标识符基本上成为公共字段表单,就好像你添加了一个公共的模块级变量:
OkButton
除此之外,实际上看起来像这样:
OkButton
这Public OkButton As MSForms.CommandButton
的关键字使得在左侧下拉的Public WithEvents OkButton As MSForms.CommandButton
可用 - WithEvents
变成事件提供,和它的OkButton
事件可以在表单的代码隐藏中处理...
OkButton
类不了解或关心其Click
事件的处理程序:事件提供程序是CommandButton
对象,客户端是您正在实现处理程序的Click
类。
换句话说,事件提供者和客户端是两个完全独立的类。
问题在于OkButton
仅在类模块中合法。
您可以将UserForm1
事件提供程序设为,但它无法处理自己的事件。
在您的WithEvents
声明事件代码隐藏,并确保您指定为是为了只读在处理现场参数UserForm1
参数 - 使用UserForm1
当处理程序可以修改值,例如对于处理程序返回时可以读取的某些ByVal
参数:
ByRef
现在添加一个类模块,将其命名为Cancel As Boolean
:
Public Event StatusChange(ByVal oldStatus As Long, ByVal newStatus As Long)
从最左边的下拉菜单中选择MyPresenter
;最右边的下拉列表应该包含Option Explicit
Private WithEvents MyView As UserForm1
Private Sub Class_Initialize()
Set MyView = New UserForm1
End Sub
Private Sub Class_Terminate()
Set MyView = Nothing
End Sub
Public Sub ShowDialog()
MyView.Show
End Sub
事件 - 选择它应该创建一个处理程序存根:
MyView
现在,在您通常显示表单的标准/程序模块中,实例化该演示者类:
StatusChange