VBA:WithEvents谜题

我有一个用户窗体, xForm ,是在一个类模块(假设TestClass )实例化为:

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

在xForm本身的类模块中,我有一些必须在Form Closing上执行的代码,只有当窗体实际closures时:

 '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中处理,并可以避免窗体closures:

 '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 

我该如何testingCancel = True,在TestFlass中的xForm类模块中设置? 我们来重述一下:如果在TestClass中将Cancel设置为True,我不能在xForm类模块中执行清理代码。 我怎么能做到这一点?

到现在为止,我已经考虑过在xForm类(My_QueryClose?)中实现另一个事件,并在QueryClose事件中引发它。 在表单后面的代码之外我只会处理My_QueryClose事件,所以要完全控制发生的事情。 这是一个可行的/更好的方法?

不能让你的定制事件的想法成为正面或反面,但是让一个class级与另一个class级(forms或其他任何东西,无所谓)交谈的方式就是联系起来; 这里是一个干净的例子:

基本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创build窗体如下所示:

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

然后,当要closures表单时,请检查您是否可以:

 '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 

一个解决方法宣布另一个事件

下面的代码按照我期望的那样做,尽pipe它不像我希望的那样整齐。

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 

基本模块中 ,要testingClass:

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

这里是最终结果(debugging窗口):

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