• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 531
  • Last Modified:

Getting events from interfaces' classes

We've got an Interface class. This interface is implemented in 2 different classes located in
different Dlls. As you know the interface doesn't copy the events so we've retyped the events
in both new classes.

We start our main program and then we decide wether to create Dll1.cls1 or Dll2.cls2.
We create this class using "set MyDll=CreateObject (DllName)". MyDll is defined as
prjInterface.Interface. Now we've got acces to the interface's methods and properties but
 we can't use Withevents to get the events.

How could we get events from these classes?
0
JonGartzia
Asked:
JonGartzia
  • 4
  • 4
  • 3
  • +2
1 Solution
 
sirbountyCommented:
Do you have WithEvents added to the declaration statement for your classes?
0
 
JonGartziaAuthor Commented:
If I add WithEvents to the MyDll declaration there's an error when I try to create the class: "Object or class does not support the set of events". The declaration is inside a Form code.
0
 
AlexFMCommented:
Maybe you can use this stupid way:

Private MyDll as prjInterface.Interface
Private WithEvents MyDll1 as Dll1
Private WithEvents MyDll2 as Dll2


set MyDll=CreateObject (DllName)

If  <condition knowh at runtime> Then
    Set MyDll1 = MyDll
Else
    Set MyDll2 = MyDll
End If

Private Sub MyDll1_Event(someData as EventData)
    MyDll_Event someData
End Sub

Private Sub MyDll2_Event(someData as EventData)
    MyDll_Event someData
End Sub

Private Sub MyDll_Event(someData as EventData)
    ' handle event
End Sub
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
JonGartziaAuthor Commented:
I would prefer not to duplicate code.
0
 
SRigneyCommented:
AlexFM has the method that will work for getting events specifically.

There is another option.  You can write a callback class.  Instantiate an instance of the callback class in the server and then pass that instance to the interface.  Then anything that implements the interface will have access to the callback class.  They would then be able to call the functions in it, and the callback class can raise the events because it is not an interface.

In short you do this.

A new class clsCallBackClass
declare your events in clsCallBackClass.
Create Public Functions for each event in class callback.
For Example
Event Progress(ByVal Percentage As Integer)
Public Sub OnProgress(ByVal Percentage As Integer)
   RaiseEvent Progress(Percentage)
End Sub

Modify the interface.  Add a public property Set
Public Property Set CallBackClass(ByRef Value As clsCallBackClass)
End Property

Implement the new property in your .dlls

In your main form.
Dim WithEvents EventHandler As New clsCallBackClass
In the code where you get the Interface class

  Dim MyDll as prjInterface.Interface
  Set MyDll = CreateObject("class1")
  Set MyDll.CallBackClass = EventHandler

In your class that implements the interface
   ' I want to raise an event here so call the callback method.
   MyCallBack.OnProgress(20)
   ' Do some more work
   MyCallBack.OnProgress(40)
   ' Do some more work
   MyCallBack.OnProgress(100)


Then catch the event from the call back class in the main form
Private Sub EventHandler_Progress(ByVal  Percentage As Integer)
   MsgBox Percentage & "% Complete"
End Sub

0
 
crazymanCommented:
Or create another Interface class in your Interface DLL and have your original interface include a method like


InitializeCallBack(pobjInterface as IEvents)

save this in a local variable in your classes that implements this (myDLL1,myDLL2)


Then when you create youor objects

implements InterfaceDLL.IEvents

dim objInterface as InterfaceDLL.Interface
set objInterface = createobject("myDLL.Class")
objinterface.InitializeCallBack me

You will then be able to communicate back to the caller via the IEvents interface...
From the calling dll (MyDll1,2)
m_objInterface.SomeRoutine "Something"

In whatever implements IEvents
private sub IEvents_SomeRoutine(SomeVar as string)
msgbox "Blah Blah Blah"
end sub
0
 
AlexFMCommented:
Notice that in my solution (assuming that is works) code is not duplicated. All message handling is done in MyDll_Event called from MyDll1_Event or MyDll2_Event. This is not generic way, if you have list of MyDll objects unknown at design time, it will not works and you need some smart algorithm. But if all you have is object of Dll1 or Dll2 class, this may be a way.
0
 
crazymanCommented:
You can also pass the class that generated the event/method back through to the caller, this may help in deciding what to do in the event...

See my example here http://www.pscode.com/vb/scripts/ShowCode.asp?txtCodeId=30646&lngWId=1 

I have many many objects in a collection that all raise same event in one class that implements a certain interface, the class that called the method on the interface passes itslef through so that you can do what you like with it...
0
 
SRigneyCommented:
The only reason I don't implement an interface in the caller and pass it in, is because user controls in vb6 won't work correctly as an interface.  They can implement an interface, but nothing that uses that interface against the usercontrol works.  So I always use the Callback class.
0
 
crazymanCommented:
SRigney,
I have had the problem you mention but i managed to get round it.
Do you get a type mismatch when trying to cast your usercontrol to the interface type, if so then this may work.

dim objInterface as ISomeInterface
set objInterface = MyControl.object

I have an app using pluguns with ocx's and this seems to work okay...
0
 
SRigneyCommented:
No, what I was doing was looping through all the controls on a form and if it implemented a certain interface then I wanted to call a function in that interface, but the usercontrol never showed that it implemented that interface.
0
 
JonGartziaAuthor Commented:
Yes, you're right AlexFM: The problem is that we read the name of the dlls from our db and
we don't know them before start. So, SRigney's solution is great.

Thank you everybody.
0
 
JonGartziaAuthor Commented:
We use controls with interfaces in another place of our program and they work perfectly using VBControlExtender.
0
 
crazymanCommented:
Im sure you can use something like..

dim obj as IExtends
dim MyControl as control
on error resume next
for each MyControl in controls
set obj = MyControl.object
if not obj is nothing then
    if type of obj is IExtends then
         obj.SomeMethod "Blah","Blah"
    end if
end if
next MyControl

Anyway im hijacking this question so ill shutup now
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 4
  • 4
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now