Reputation: 1020
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?
Upvotes: 3
Views: 2982
Reputation: 1020
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
Upvotes: 1
Reputation: 1372
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
Upvotes: 1