VBA:WithEvents 谜题

发布于 2024-10-25 13:57:49 字数 1094 浏览 2 评论 0原文

我有一个 UserForm,xForm,它正在类模块中实例化(比方说 TestClass):

'TestClass
Dim Form as New xForm
Private WithEvents EvForm as MSForms.UserForm
Set EvForm = Form

在 xForm 本身的类模块中,我有一些代码必须仅当表单实际关闭时才在表单关闭时执行:

'xForm class module
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    'Do some cleanup, otherwise the app would hang
    'If not closing, don't cleanup anything, otherwise the app would hang
End Sub

QueryClose 事件也在 TestClass 中处理,并且可以避免表单关闭:

'TestClass
Private Sub EvForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    'Verify if closing is allowed based on User Control values
    Cancel = Not ClosingIsAllowed '<-- Pseudocode on the right side of "="
End Sub

如何测试 Cancel = True(在 xForm 类模块中的 TestClass 中设置)? 让我们重新表述一下:如果 TestClass 中的 Cancel 设置为 True,则我不能在 xForm 类模块中执行清理代码。我怎样才能做到这一点?

到目前为止,我一直在考虑在 xForm 类中实现另一个事件(My_QueryClose?)并在 QueryClose 事件上引发它。在代码隐藏表单之外,我将只处理 My_QueryClose 事件,因此可以完全控制正在发生的事情。这是一种可行/更好的方法吗?

I have a UserForm, xForm, that is being instantiated in a class module (let's say TestClass) as:

'TestClass
Dim Form as New xForm
Private WithEvents EvForm as MSForms.UserForm
Set EvForm = Form

At the class module of the xForm itself I have some code that must be executed on Form Closing, ONLY if the form actually closes:

'xForm class module
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    'Do some cleanup, otherwise the app would hang
    'If not closing, don't cleanup anything, otherwise the app would hang
End Sub

The QueryClose event is also treated in TestClass, and could avoid the form from closing:

'TestClass
Private Sub EvForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    'Verify if closing is allowed based on User Control values
    Cancel = Not ClosingIsAllowed '<-- Pseudocode on the right side of "="
End Sub

How can I test for Cancel = True, set in TestClass, in the xForm class module?
Let's rephrase it: If Cancel is set to True in TestClass, I must not do the cleanup code in the xForm class module. How can I accomplish that?

Until now, I have thought off of implementing another event in the xForm class (My_QueryClose?) and raise it on the QueryClose event. Outside the Code Behind Form I would deal only with the My_QueryClose event, so taking full control over what is happening. Is this a viable/better approach?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

爱给你人给你 2024-11-01 13:57:49

无法弄清楚您的自定义事件想法,但让一个班级与另一个班级交谈(形式或其他任何东西,并不重要)的方法是将它们链接起来;这是一个干净的示例:

Basic TestClass 保存表单对象(这里不需要事件,让表单处理它)

'TestClass code
Private MyForm          As UserForm
Private mbleCanClose    As Boolean

Public Property Get CanClose() As Boolean
    CanClose = mbleCanClose
End Property
Public Property Let CanClose(pbleCanClose As Boolean)
    mbleCanClose = pbleCanClose
End Property

Public Property Get MyFormProp() As UserForm1
    Set MyFormProp = MyForm
End Property

自定义对象和属性添加到表单本身

'UserForm1 code
Private mParent As TestClass

Public Property Get Parent() As TestClass
    Set Parent = mParent
End Property
Public Property Set Parent(pParent As TestClass)
    Set mParent = pParent
End Property

在创建 TestClass 时调用表单如下所示:

'TestClass code
Private Sub Class_Initialize()
    Set MyForm = New UserForm1
    Load MyForm
    Set MyForm.Parent = Me
End Sub

将 表单,您检查是否可以:

'UserForm1 code
Public Function WillMyParentLetMeClose() As Boolean
    If Not (mParent Is Nothing) Then
        WillMyParentLetMeClose = mParent.CanClose
    End If
End Function

Private Sub CommandButton1_Click()
    If WillMyParentLetMeClose = True Then
        Unload Me
    End If
End Sub

这是它想要调用的内容

'standard module code
Public Sub Test_TestClass()
    Dim myclass As TestClass
    Set myclass = New TestClass
    myclass.MyFormProp.Show
End Sub

Can't make heads or tails of your custom event idea, but the way to get one class to talk to another (form or anything else, doesn't matter) is to link them up; here's a clean example:

Basic TestClass holds form object (no events needed here, let the form handle that)

'TestClass code
Private MyForm          As UserForm
Private mbleCanClose    As Boolean

Public Property Get CanClose() As Boolean
    CanClose = mbleCanClose
End Property
Public Property Let CanClose(pbleCanClose As Boolean)
    mbleCanClose = pbleCanClose
End Property

Public Property Get MyFormProp() As UserForm1
    Set MyFormProp = MyForm
End Property

Add a custom object and property to the form itself

'UserForm1 code
Private mParent As TestClass

Public Property Get Parent() As TestClass
    Set Parent = mParent
End Property
Public Property Set Parent(pParent As TestClass)
    Set mParent = pParent
End Property

Invoking the form on TestClass creation looks like this:

'TestClass code
Private Sub Class_Initialize()
    Set MyForm = New UserForm1
    Load MyForm
    Set MyForm.Parent = Me
End Sub

And then when it's time to close the form, you check whether you can:

'UserForm1 code
Public Function WillMyParentLetMeClose() As Boolean
    If Not (mParent Is Nothing) Then
        WillMyParentLetMeClose = mParent.CanClose
    End If
End Function

Private Sub CommandButton1_Click()
    If WillMyParentLetMeClose = True Then
        Unload Me
    End If
End Sub

Here's what it would like to invoke

'standard module code
Public Sub Test_TestClass()
    Dim myclass As TestClass
    Set myclass = New TestClass
    myclass.MyFormProp.Show
End Sub
海夕 2024-11-01 13:57:49

围绕声明另一个事件的解决方法

下面的代码实现了我的预期,尽管它并不像我希望的那样整洁。

UserForm1 代码中:

'***** UserForm1
Public Event MyQueryClose(ByRef Cancel As Integer, ByRef CloseMode As Integer, ByRef Status As String)

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
   Dim Status As String
   Cancel = True
   Status = "QueryClose"
   Debug.Print "Entered QueryClose"
   Debug.Print "Cancel = " & Cancel
   Debug.Print "Status = " & Status
   Debug.Print "Just before raising MyQueryClose"
   RaiseEvent MyQueryClose(Cancel, CloseMode, Status)
   Debug.Print "Just got back from MyQueryClose"
   Debug.Print "Cancel = " & Cancel
   Debug.Print "Status = " & Status
End Sub

Class1 代码中:

'***** Class1
Dim UserForm As New UserForm1
Private WithEvents UF As UserForm1

Sub DoIt()
   Set UF = UserForm
   UserForm.Show
End Sub

Private Sub UF_MyQueryClose(Cancel As Integer, CloseMode As Integer, Status As String)
   Debug.Print "Just entered MyQueryClose"
   Cancel = False
   Status = "MY QueryClose"
End Sub

基本模块 中,测试类:

'***** Basic module
Sub TestClass()
   Dim C As New Class1
   C.DoIt
End Sub

这是最终结果(调试窗口) :

TestClass
Entered QueryClose
Cancel = -1
Status = QueryClose
Just before raising MyQueryClose
Just entered MyQueryClose
Just got back from MyQueryClose
Cancel = 0
Status = MY QueryClose

A work around declaring another event

The code bellow do what I was expecting, although it is not as neat as I wish it could be.

In the UserForm1 code:

'***** UserForm1
Public Event MyQueryClose(ByRef Cancel As Integer, ByRef CloseMode As Integer, ByRef Status As String)

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
   Dim Status As String
   Cancel = True
   Status = "QueryClose"
   Debug.Print "Entered QueryClose"
   Debug.Print "Cancel = " & Cancel
   Debug.Print "Status = " & Status
   Debug.Print "Just before raising MyQueryClose"
   RaiseEvent MyQueryClose(Cancel, CloseMode, Status)
   Debug.Print "Just got back from MyQueryClose"
   Debug.Print "Cancel = " & Cancel
   Debug.Print "Status = " & Status
End Sub

In the Class1 code:

'***** Class1
Dim UserForm As New UserForm1
Private WithEvents UF As UserForm1

Sub DoIt()
   Set UF = UserForm
   UserForm.Show
End Sub

Private Sub UF_MyQueryClose(Cancel As Integer, CloseMode As Integer, Status As String)
   Debug.Print "Just entered MyQueryClose"
   Cancel = False
   Status = "MY QueryClose"
End Sub

In a basic module, to test the Class:

'***** Basic module
Sub TestClass()
   Dim C As New Class1
   C.DoIt
End Sub

And here's the end result (debug window):

TestClass
Entered QueryClose
Cancel = -1
Status = QueryClose
Just before raising MyQueryClose
Just entered MyQueryClose
Just got back from MyQueryClose
Cancel = 0
Status = MY QueryClose
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文