是否可以在自定义用户窗体中创建和处理自定义事件?

时间:2018-04-04 21:03:44

标签: vba excel-vba excel

我有一个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

1 个答案:

答案 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