| Expose events from implemented classes |
Applies To |
|
| OS: VB: |
NT, 9x, 2000 5, 6 |
|
Using Implements cClass is great. You get to define an interface, safely store it away and then create classes based on this interface. Visual Basic even creates a code stub for you. Almost a no-brainer. It is useful for situation where your classes might have an identical interface but different implementation. For instance, I used to have several classes that did some low-level maintanance on Sybase and Microsoft SQL Servers and Access database. Each of them had an identical interface. This was a perfect place to use Implements technology.
Unfortunately, it has one small caveat - you can't expose events from either the parent or the child class. Consider the following - you have your Interface class (IDatabaseMaintanance), you have your implemented classes (CDatabaseMaintanance_Sybase, CDatabaseMaintanance_MSSQL and CDatabaseMaintanance_Access) and you have your client app. You expose the following properties and events in the Interface class (IDatabaseMaintanance)
Public dbName as StringIn the client app you instantiate iClass using WithEvents
Event StartProcessing(Status as String)
Event Processing(Status as String)
Event EndProcessing()
'(general declarations)Then in some sub you attempt to instantiate the implemented class
Private WithEvents o As iClass
set o = CreateObject("dbMaint.CDatabaseMaintanance_Sybase")And you'll get an error stating that this class doesn't support the set of events.
Too bad. It would be sweet to be able to expose events. Fear not, there is a workaround. But you have to take another tack with it. Create 3 projects: one is a Standard Exe (Client), second one is for the interfaces and it will have 2 classes - the primary interface (IClass) and a secondary one which we will use to create events (IEvents). The 3rd project will be an ActiveX DLL and will contain just one class (CClass) which will implement IClass. In the Client project, add references to the 2 and 3 projects. In the last project, add references to the project with all the interfaces.
First, let's define all the events. In IEvents, type the following:Public Sub StartProcessing(Status as String)
End Sub
Public Sub Processing(Status as String)
End Sub
Public Sub EndProcessing()
End Sub
Now let's define the interface for IClass. Note the parameter to the Execute method
Public FirstName as String
Public LastName as string
Public Sub Execute(oEventsInterface as IEvents)
End Sub
So basically, whoever implements IClass will have the opportunity to fire off methods on the IEvents interface. This will come into play later. Meanwhile, let's implement IClass in CClass (3rd project)
Implements IClass
Public Sub IClass_Execute(oEventsInterface as IEvents)
'fire off the StartProcessing method on the oEventsInterface
oEventsInterface.StartProcessing "In Progress"
End Sub
You may ask at this point, StartProcessing was executed but where will it fire? Good question. Hold on. In the Client project, in the General Declarations implement the IEvents. Then in the Form_Load will fire off the whole thing
Implements IEvents
Private Sub Form_Load()
'define the objectEnd Sub
Dim o as IClass
'now create it from the implemented class
Set o = CreateObject("Project3.CClass")
'now send the form as the target for IEvents methods
o.Execute (Me)
Set o = Nothing
Private Sub IEvents_StartProcessing(Status as String)
'This is where the event will fire
End Sub
The code is kind of weird, but it works, thanks to COM's engine. I realize that it is kind of difficult to explain - but really easy to follow in code. So download it and give it a whirl.
Thanks to Jason Bock for pointing me in the right direction.