Event - RaiseEvents Within Class Modules

  • Thread starter Thread starter John Peterson
  • Start date Start date
J

John Peterson

Is it possible to create an event in one class module and then raise that
event from another class module. I have a class module which provides event
trapping for a control type - class1. The other class module creates a
collection of controls - class2. If I change a control's state through a
class1 click event, I would like to raise an event which will go to the
collection (class2) and update a Boolean array holding the state condition
on each control in the collection. I have tried several examples of
Event-RaiseEvent usage. None of these seem to work across class module
boundaries. I would appreciate any advice on this subject. Regards,

John
 
Hi John,

In order to trap an event raised by Class1 in Class2, you must declare a
WithEvents object reference to Class1 inside Class2, then create an event
stub procedure for the event being raised. A very simple (and admittedly
contrived) example would look like this:

-----------
In Class1
-----------
Event MyEvent()

Public Sub RaiseMyEvent()
RaiseEvent MyEvent
End Sub

-----------
In Class2
-----------
Private WithEvents mclsClass1 As Class1

Private Sub Class_Initialize()
Set mclsClass1 = New Class1
End Sub

Private Sub mclsClass1_MyEvent()
MsgBox "mclsClass1_MyEvent was caught in Class2"
End Sub

Public Sub RaiseMyEvent()
mclsClass1.RaiseMyEvent
End Sub

-----------
In Module1
-----------
Sub Demo()
Dim clsClass2 As Class2
Set clsClass2 = New Class2
clsClass2.RaiseMyEvent
End Sub

When you run this code you'll see a message box that is displayed by
Class2 when it catches the event raised by Class1.

--
Rob Bovey, MCSE, MCSD, Excel MVP
Application Professionals
http://www.appspro.com/

* Please post all replies to this newsgroup *
* I delete all unsolicited e-mail responses *
 
Rob,

Thanks for the explanation. While this example allows for triggering of an
event in class2 from class1, the initial trigger comes from an external
source thru class2 to class1. The problem I have is that a control's click
event in class1 needs to initiate the class2 update event.

Each of the class1 controls resides in the class2 collection container.
When a control is clicked, it causes a change in its own status and needs to
notify the status array external to the collection that its status has been
changed. I can force an external call to class2's update function by hard
coding the call. Unfortunately when this is done it makes the functionality
and design very specific.

Here are the specifics of the classes, form, and standard modules When I
step through the excution of the Images_Click subroutine, the RaiseEvent is
stepped through. Program flow however doesn't get redirected to the update
code in the collection class. I would appreciate any advice you might have.

Regards,
John

'==================
' Class 2 - clsControlCollection
'==================
Option Explicit

Public ControlCollection As New Collection
Private oControls As clsControls
Private MDIndex As Integer

Private WithEvents StatData As clsControls

Public Sub Initialize(frm As UserForm)
Dim Ctrl As Control
Dim xx As Integer

' Create the Button objects
For Each Ctrl In frm.controls
If TypeName(Ctrl) = "Image" Then
Set oControls = New clsControls
Set oControls.Images = Ctrl
oControls.Index = MDIndex
oControls.Status = 1
ControlCollection.Add oControls, Ctrl.Name
oControls.Images.Picture = frm.ImageList1.Overlay(5, 1)
MDIndex = MDIndex + 1
End If
Next Ctrl
For xx = 1 To MDIndex
ControlCollection.Item(xx).Count = MDIndex
Next xx
Set oControls= Nothing
frm.Repaint
End Sub

Public Sub StatData_Update(strStatType As String)

'-------------------------------
' Code to update status array
'-------------------------------
End Sub


'==================
' Class 1 - clsControls
'==================
Option Explicit

Public Event Update(str As String)

Public WithEvents Images As msforms.Image
Private aIndex As Integer
Private aName As String
Private aForm As UserForm
Private aStatus As Integer
Private aCount As Integer

Private Sub Images_Click()

'-------------------------------
' Code to change image
'-------------------------------
RaiseEvent Update("imgMD")
aForm.Repaint
End Sub

'==================
' Userform - Array of 32 Images
'==================
Private Sub UserForm_Activate()

Ctrls.Initialize UserForm2

End Sub


'==================
' Standard Module
'==================
Option Explicit

Public Ctrls As New clsControlCollection
Public Ctrl As New clsControls
 
Hi John,

OK, I somehow missed the details of what you were doing. The short
answer is that there isn't any way to do what you want. In order to trap
events from Class1 in Class2 you have to declare a separate WithEvents
Class1 variable for every instance of Class1 that you need to watch. You
can't trap events from objects inside a collection and you can't declare an
array variable WithEvents.

The next best thing would be to create a Parent-Child relationship
between the two classes. Class2 would be the parent of Class1. Each instance
of Class1 would carry a reference to its Class2 parent object. You then
create a notification method in Class2 that can be called by any Class1
child whenever it needs to notify its parent of a some event. Here's a basic
example of this:

-----------------
In Class1 (child)
-----------------
Private mclsParent As Class2

Public Property Set Parent(ByRef clsNewValue As Class2)
Set mclsParent = clsNewValue
End Property

Private Sub Class_Terminate()
Set mclsParent = Nothing
End Sub

Public Sub Click_Event()
mclsParent.NotifyMe "My Name"
End Sub

------------------
In Class2 (parent)
------------------
Private mclsChild As Class1

Private Sub Class_Initialize()
Set mclsChild = New Class1
Set mclsChild.Parent = Me
End Sub

''' The child passes its name so you know who called.
Friend Sub NotifyMe(ByRef szName As String)
MsgBox szName & " was clicked."
End Sub

''' For testing purposes only.
Public Sub TestChild()
mclsChild.Click_Event
End Sub

------------
In Module 1
------------
Sub Demo()
Dim clsClass2 As Class2
Set clsClass2 = New Class2
clsClass2.TestChild
End Sub

--
Rob Bovey, MCSE, MCSD, Excel MVP
Application Professionals
http://www.appspro.com/

* Please post all replies to this newsgroup *
* I delete all unsolicited e-mail responses *
 
Rob,

Thanks a lot. :) On first pass it looks like it will do the job. It
will be a few days before I get a chance to try it. I will let you know
the outcome.

John
 
Back
Top