[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.vb.general.discussion

Implements and WithEvents

bart.smissaert@gmail.com

2/22/2012 11:47:00 PM

In VB6 in an ActiveX dll I have a class with the Implements keyword
(Implements IFunction, which
is a class in Olaf Schmidt's vbRichClient4).
Now from this class I want to raise events to be picked up in a VBA class.
So, I have this in the declaration area of the class:

Implements IFunction
Private arrString(1 To 30) As String
Private arrLong(1 To 30) As Long
Private arrDouble(1 To 30) As Double
Public Event PassArgsToVBA(arrString() As String, _
arrLong() As Long, _
arrDouble() As Double)

Now, in that class I do this:

Private Sub IFunction_Callback(ByVal ZeroBasedNameIndex As Long, _
ByVal ParamCount As Long, _
UDF As vbRichClient4.cUDFMethods)


RaiseEvent PassArgsToVBA(arrString, arrLong, arrDouble)


Problem is that the event is raised, but not picked up in VBA.
My question is if it is possible to raise events from classes with the
Implements keyword?
It compiles fine and no error occurs, but just nil picked up in VBA.


RBS


9 Answers

ralph

2/23/2012 12:26:00 AM

0

On Wed, 22 Feb 2012 23:47:02 -0000, "RB Smissaert"
<bart.smissaert@gmail.com> wrote:

>In VB6 in an ActiveX dll I have a class with the Implements keyword
>(Implements IFunction, which
>is a class in Olaf Schmidt's vbRichClient4).
>Now from this class I want to raise events to be picked up in a VBA class.
>So, I have this in the declaration area of the class:
>
>Implements IFunction
>Private arrString(1 To 30) As String
>Private arrLong(1 To 30) As Long
>Private arrDouble(1 To 30) As Double
>Public Event PassArgsToVBA(arrString() As String, _
> arrLong() As Long, _
> arrDouble() As Double)
>
>Now, in that class I do this:
>
>Private Sub IFunction_Callback(ByVal ZeroBasedNameIndex As Long, _
> ByVal ParamCount As Long, _
> UDF As vbRichClient4.cUDFMethods)
>
>
> RaiseEvent PassArgsToVBA(arrString, arrLong, arrDouble)
>
>
>Problem is that the event is raised, but not picked up in VBA.
>My question is if it is possible to raise events from classes with the
>Implements keyword?
>It compiles fine and no error occurs, but just nil picked up in VBA.
>

Events are not part of a Public Interface and can not be Implemented.

One way around this is to create a "concrete" Adaptor/Mediator object
that can send/receive Events, and pass it as a Reference to any Object
needing its event services. (This is pretty much how VB does it.) The
object can be Project 'global' with a long lifetime and available to
any number of Objects..

There are other ways.

-ralph

bart.smissaert@gmail.com

2/23/2012 12:32:00 AM

0

> create a "concrete" Adaptor/Mediator object

Do you mean creating another class that has the Public Event and using that
class in the
class that has the Implements?
This is what I have tried, but it didn't make the event to be picked up in
VBA.
Again, compiled fine though and no error.

What are the other ways?

RBS



"ralph" <nt_consulting64@yahoo.net> wrote in message
news:p71bk7tbgn0rbfc86ehigund29ibut3f0b@4ax.com...
> On Wed, 22 Feb 2012 23:47:02 -0000, "RB Smissaert"
> <bart.smissaert@gmail.com> wrote:
>
>>In VB6 in an ActiveX dll I have a class with the Implements keyword
>>(Implements IFunction, which
>>is a class in Olaf Schmidt's vbRichClient4).
>>Now from this class I want to raise events to be picked up in a VBA class.
>>So, I have this in the declaration area of the class:
>>
>>Implements IFunction
>>Private arrString(1 To 30) As String
>>Private arrLong(1 To 30) As Long
>>Private arrDouble(1 To 30) As Double
>>Public Event PassArgsToVBA(arrString() As String, _
>> arrLong() As Long, _
>> arrDouble() As Double)
>>
>>Now, in that class I do this:
>>
>>Private Sub IFunction_Callback(ByVal ZeroBasedNameIndex As Long, _
>> ByVal ParamCount As Long, _
>> UDF As vbRichClient4.cUDFMethods)
>>
>>
>> RaiseEvent PassArgsToVBA(arrString, arrLong, arrDouble)
>>
>>
>>Problem is that the event is raised, but not picked up in VBA.
>>My question is if it is possible to raise events from classes with the
>>Implements keyword?
>>It compiles fine and no error occurs, but just nil picked up in VBA.
>>
>
> Events are not part of a Public Interface and can not be Implemented.
>
> One way around this is to create a "concrete" Adaptor/Mediator object
> that can send/receive Events, and pass it as a Reference to any Object
> needing its event services. (This is pretty much how VB does it.) The
> object can be Project 'global' with a long lifetime and available to
> any number of Objects..
>
> There are other ways.
>
> -ralph

Schmidt

2/23/2012 2:10:00 AM

0

Am 23.02.2012 00:47, schrieb RB Smissaert:
> In VB6 in an ActiveX dll I have a class with the Implements keyword
> (Implements IFunction, which
> is a class in Olaf Schmidt's vbRichClient4).
> Now from this class I want to raise events to be picked up in a VBA class.
> So, I have this in the declaration area of the class:
>
> Implements IFunction
> Private arrString(1 To 30) As String
> Private arrLong(1 To 30) As Long
> Private arrDouble(1 To 30) As Double
> Public Event PassArgsToVBA(arrString() As String, _
> arrLong() As Long, _
> arrDouble() As Double)
>
> Now, in that class I do this:
>
> Private Sub IFunction_Callback(ByVal ZeroBasedNameIndex As Long, _
> ByVal ParamCount As Long, _
> UDF As vbRichClient4.cUDFMethods)
>
>
> RaiseEvent PassArgsToVBA(arrString, arrLong, arrDouble)

Assuming this class here is called cMyFuncImplementation

What does VB6 say, when you're trying this (in a different
Form or Class):

Private WithEvents MyFuncImplementation as cMyFuncImplementation


Accompanied in some Init-Proc, e.g. Form_Load -
or another Test-Class' Class_Initialize by:

Set MyFuncImplementation = New cFuncImplementation

I'm pretty sure you will get the Event then in the appropriate
Event-Procedure - just make sure, that the Classes really
remain alive over your test-run.

@Ralph... this should work, because he is raising a
normal Class-Event from Class cMyFuncImplementation then -
and the EventSink (over the WithEvents-Declaration) is
requested over the implementing HostClass-Interface too,
not on the implemented IFunction-Interface, this class
also supports.

So I'm pretty sure that works in VB5/6 - and normally
it should also work in VBA, since it also supports
the WithEvents-Keyword.

Olaf

unknown

2/23/2012 5:07:00 AM

0

"RB Smissaert" <bart.smissaert@gmail.com> wrote in message
news:ji3upt$1n2$1@dont-email.me...
> Problem is that the event is raised, but not picked up in VBA.
> My question is if it is possible to raise events from classes with the
> Implements keyword?
> It compiles fine and no error occurs, but just nil picked up in VBA.

Besides what others suggested, make sure that the object variable in VBA is
not Nothing, otherwise nothing will fire:

Private WithEvents o As Class1
....
Set o = New Class1
....
Set o = Nothing





bart.smissaert@gmail.com

2/23/2012 7:26:00 AM

0

Thanks, will try that later today and report back.
The idea of all this is to avoid passing variables to VBA as variants via
Application.Run with variant arguments.

RBS

"Schmidt" <sss@online.de> wrote in message
news:ji476j$edd$1@dont-email.me...
> Am 23.02.2012 00:47, schrieb RB Smissaert:
>> In VB6 in an ActiveX dll I have a class with the Implements keyword
>> (Implements IFunction, which
>> is a class in Olaf Schmidt's vbRichClient4).
>> Now from this class I want to raise events to be picked up in a VBA
>> class.
>> So, I have this in the declaration area of the class:
>>
>> Implements IFunction
>> Private arrString(1 To 30) As String
>> Private arrLong(1 To 30) As Long
>> Private arrDouble(1 To 30) As Double
>> Public Event PassArgsToVBA(arrString() As String, _
>> arrLong() As Long, _
>> arrDouble() As Double)
>>
>> Now, in that class I do this:
>>
>> Private Sub IFunction_Callback(ByVal ZeroBasedNameIndex As Long, _
>> ByVal ParamCount As Long, _
>> UDF As vbRichClient4.cUDFMethods)
>>
>>
>> RaiseEvent PassArgsToVBA(arrString, arrLong, arrDouble)
>
> Assuming this class here is called cMyFuncImplementation
>
> What does VB6 say, when you're trying this (in a different
> Form or Class):
>
> Private WithEvents MyFuncImplementation as cMyFuncImplementation
>
>
> Accompanied in some Init-Proc, e.g. Form_Load -
> or another Test-Class' Class_Initialize by:
>
> Set MyFuncImplementation = New cFuncImplementation
>
> I'm pretty sure you will get the Event then in the appropriate
> Event-Procedure - just make sure, that the Classes really
> remain alive over your test-run.
>
> @Ralph... this should work, because he is raising a
> normal Class-Event from Class cMyFuncImplementation then -
> and the EventSink (over the WithEvents-Declaration) is
> requested over the implementing HostClass-Interface too,
> not on the implemented IFunction-Interface, this class
> also supports.
>
> So I'm pretty sure that works in VB5/6 - and normally
> it should also work in VBA, since it also supports
> the WithEvents-Keyword.
>
> Olaf

bart.smissaert@gmail.com

2/23/2012 1:35:00 PM

0

Hi Olaf,

Slightly confused here:

Where in your scenario do you put the Public Event,
in the class with Implements or in the other class?
The event will need to be public to be available in VBA.

Where do I put the RaiseEvent, in the class with Implements or in the other
class?

RBS


"Schmidt" <sss@online.de> wrote in message
news:ji476j$edd$1@dont-email.me...
> Am 23.02.2012 00:47, schrieb RB Smissaert:
>> In VB6 in an ActiveX dll I have a class with the Implements keyword
>> (Implements IFunction, which
>> is a class in Olaf Schmidt's vbRichClient4).
>> Now from this class I want to raise events to be picked up in a VBA
>> class.
>> So, I have this in the declaration area of the class:
>>
>> Implements IFunction
>> Private arrString(1 To 30) As String
>> Private arrLong(1 To 30) As Long
>> Private arrDouble(1 To 30) As Double
>> Public Event PassArgsToVBA(arrString() As String, _
>> arrLong() As Long, _
>> arrDouble() As Double)
>>
>> Now, in that class I do this:
>>
>> Private Sub IFunction_Callback(ByVal ZeroBasedNameIndex As Long, _
>> ByVal ParamCount As Long, _
>> UDF As vbRichClient4.cUDFMethods)
>>
>>
>> RaiseEvent PassArgsToVBA(arrString, arrLong, arrDouble)
>
> Assuming this class here is called cMyFuncImplementation
>
> What does VB6 say, when you're trying this (in a different
> Form or Class):
>
> Private WithEvents MyFuncImplementation as cMyFuncImplementation
>
>
> Accompanied in some Init-Proc, e.g. Form_Load -
> or another Test-Class' Class_Initialize by:
>
> Set MyFuncImplementation = New cFuncImplementation
>
> I'm pretty sure you will get the Event then in the appropriate
> Event-Procedure - just make sure, that the Classes really
> remain alive over your test-run.
>
> @Ralph... this should work, because he is raising a
> normal Class-Event from Class cMyFuncImplementation then -
> and the EventSink (over the WithEvents-Declaration) is
> requested over the implementing HostClass-Interface too,
> not on the implemented IFunction-Interface, this class
> also supports.
>
> So I'm pretty sure that works in VB5/6 - and normally
> it should also work in VBA, since it also supports
> the WithEvents-Keyword.
>
> Olaf

Schmidt

2/23/2012 2:07:00 PM

0

Am 23.02.2012 14:34, schrieb RB Smissaert:
> Hi Olaf,
>
> Slightly confused here:
>
> Where in your scenario do you put the Public Event,
> in the class with Implements or in the other class?
> The event will need to be public to be available in VBA.

The Events-Declaration-Line(s) belong into the class,
from where you want to raise them, so - in your case -
into the class which does the 'Implements IFunction'.
Let's call those "the EventRaiser"-classes.

> Where do I put the RaiseEvent, in the class with Implements
> or in the other class?
An RaiseEvent-attempt in a given class needs a matching
(accompanying) Events-Declaration in the same Code-Module,
so these attempts should be placed in "the EventRaiser"
too (in your case this is also the class, which does the
Implements IFunction).

Then there's "EventConsumers", which in VB6 can be
VB-Forms, VB-Usercontrols or any other "normal Class"...
on the VBA-end these could be Excel-Worksheets or
any other "normal VBA-Class-Module". In neither case
is it possible, to use *.bas-Modules as EventConsumers.

Such an EventConsumer-(Class) needs to define(declare)
the EventRaiser-Class with a special Keyword: WithEvents.
usually over (adapted to your scenario):
Private WithEvents MyEventRaiser As cMyRaiserWithImplementsInIt

After this definition was done, you can select the
declared ObjectVariable (in this example: MyEventRaiser)
from the appropriate IDE-CodeModule-ComboBox on the left-hand.
After that, in the right-hand-ComboBox you can select
the Events, this Raising-Capable classType has to offer.
And then fill in your Code into the automatically
inserted EventProc-Definition.
To receive Events therein, you need to ensure of course,
that the "MyEventRaiser"-ObjTypeVariable is filled with
a concrete Instance first (and not remains Nothing).

Maybe play around with that in smaller TestClasses in
VB6 first - a simple RaiserClass - and a ConsumerClass
(or a ConsumerForm), to get a grip on the topic first.

Olaf

bart.smissaert@gmail.com

2/23/2012 2:42:00 PM

0

OK, I got the idea now.
To summarise:
Declare and raise event from the VB6 class with Implements
In a normal class set reference (with WithEvents) to the class with
Implements and pick up events
Then in that second (normal) class raise another event and that event will
be picked up in VBA.
Not quite sure what the difference is with my original scenario (in that
case the VBA class was like
the second VB6 class), but have coded as you suggested, but event not picked
up in VBA.
I have a feeling that the trouble may be to do with what you say here:

> ensure of course,
> that the "MyEventRaiser"-ObjTypeVariable is filled with
> a concrete Instance first (and not remains Nothing).

I do this in the VBA class (called CSQLiteEvents2) like this:

Private WithEvents SQLiteEvents As SQLiteProcs.clsSQLite

Private Sub Class_Initialize()
Set SQLiteEvents = SQLiteProcs.clsSQLite
End Sub

And I initialize the VBA class on startup like this:

Private clsSQLiteEvents As CSQLiteEvents2

Sub InitEventsClass()

If clsSQLiteEvents Is Nothing Then
Set clsSQLiteEvents = New CSQLiteEvents2
End If

End Sub


Is that not sufficient to keep the VB6 class (the second one) alive?


RBS



"Schmidt" <sss@online.de> wrote in message
news:ji5h6b$dir$1@dont-email.me...
> Am 23.02.2012 14:34, schrieb RB Smissaert:
>> Hi Olaf,
>>
>> Slightly confused here:
>>
>> Where in your scenario do you put the Public Event,
>> in the class with Implements or in the other class?
>> The event will need to be public to be available in VBA.
>
> The Events-Declaration-Line(s) belong into the class,
> from where you want to raise them, so - in your case -
> into the class which does the 'Implements IFunction'.
> Let's call those "the EventRaiser"-classes.
>
>> Where do I put the RaiseEvent, in the class with Implements
>> or in the other class?
> An RaiseEvent-attempt in a given class needs a matching
> (accompanying) Events-Declaration in the same Code-Module,
> so these attempts should be placed in "the EventRaiser"
> too (in your case this is also the class, which does the
> Implements IFunction).
>
> Then there's "EventConsumers", which in VB6 can be
> VB-Forms, VB-Usercontrols or any other "normal Class"...
> on the VBA-end these could be Excel-Worksheets or
> any other "normal VBA-Class-Module". In neither case
> is it possible, to use *.bas-Modules as EventConsumers.
>
> Such an EventConsumer-(Class) needs to define(declare)
> the EventRaiser-Class with a special Keyword: WithEvents.
> usually over (adapted to your scenario):
> Private WithEvents MyEventRaiser As cMyRaiserWithImplementsInIt
>
> After this definition was done, you can select the
> declared ObjectVariable (in this example: MyEventRaiser)
> from the appropriate IDE-CodeModule-ComboBox on the left-hand.
> After that, in the right-hand-ComboBox you can select
> the Events, this Raising-Capable classType has to offer.
> And then fill in your Code into the automatically
> inserted EventProc-Definition.
> To receive Events therein, you need to ensure of course,
> that the "MyEventRaiser"-ObjTypeVariable is filled with
> a concrete Instance first (and not remains Nothing).
>
> Maybe play around with that in smaller TestClasses in
> VB6 first - a simple RaiserClass - and a ConsumerClass
> (or a ConsumerForm), to get a grip on the topic first.
>
> Olaf

bart.smissaert@gmail.com

2/23/2012 6:36:00 PM

0

Hi Olaf,

I previously read the last mail a bit quickly (had to go to work) and
thought you said there had to be a second VB6 class to consume the event and
pass it on from there. Can see now that this is not the case and you
describe exactly what I was doing in the first place. Will have another look
and see what might be the problem.
If I understand you right then the whole Implement thing has nil to do with
the event not being picked up in VBA.

RBS


"Schmidt" <sss@online.de> wrote in message
news:ji5h6b$dir$1@dont-email.me...
> Am 23.02.2012 14:34, schrieb RB Smissaert:
>> Hi Olaf,
>>
>> Slightly confused here:
>>
>> Where in your scenario do you put the Public Event,
>> in the class with Implements or in the other class?
>> The event will need to be public to be available in VBA.
>
> The Events-Declaration-Line(s) belong into the class,
> from where you want to raise them, so - in your case -
> into the class which does the 'Implements IFunction'.
> Let's call those "the EventRaiser"-classes.
>
>> Where do I put the RaiseEvent, in the class with Implements
>> or in the other class?
> An RaiseEvent-attempt in a given class needs a matching
> (accompanying) Events-Declaration in the same Code-Module,
> so these attempts should be placed in "the EventRaiser"
> too (in your case this is also the class, which does the
> Implements IFunction).
>
> Then there's "EventConsumers", which in VB6 can be
> VB-Forms, VB-Usercontrols or any other "normal Class"...
> on the VBA-end these could be Excel-Worksheets or
> any other "normal VBA-Class-Module". In neither case
> is it possible, to use *.bas-Modules as EventConsumers.
>
> Such an EventConsumer-(Class) needs to define(declare)
> the EventRaiser-Class with a special Keyword: WithEvents.
> usually over (adapted to your scenario):
> Private WithEvents MyEventRaiser As cMyRaiserWithImplementsInIt
>
> After this definition was done, you can select the
> declared ObjectVariable (in this example: MyEventRaiser)
> from the appropriate IDE-CodeModule-ComboBox on the left-hand.
> After that, in the right-hand-ComboBox you can select
> the Events, this Raising-Capable classType has to offer.
> And then fill in your Code into the automatically
> inserted EventProc-Definition.
> To receive Events therein, you need to ensure of course,
> that the "MyEventRaiser"-ObjTypeVariable is filled with
> a concrete Instance first (and not remains Nothing).
>
> Maybe play around with that in smaller TestClasses in
> VB6 first - a simple RaiserClass - and a ConsumerClass
> (or a ConsumerForm), to get a grip on the topic first.
>
> Olaf