Home All Groups Group Topic Archive Search About

Global class and WithEvents

Author
31 Aug 2010 7:25 PM
Alexandros Peropulous
Hello!

I have a class which I needed to make global because it is used in/ on
different forms, and the class opens and closes port handles, so I
cannot simply make a few more copies of them.

However, on some of the forms, I would need a notification about events
that the class handles.

Normally in my form I would dim the class and receive the events by
RaiseEvent like this:

private withevents m_Class as Class1

But since the class is global, I cannot do this.

Does somebody have any ideas? I don't want to poll the class with a
timer to query the event...

Thank you!
Alex

Author
31 Aug 2010 8:00 PM
Spence
Consider using a Standard Module. It is by default global in its' scope. As
a Form object loads it can pass a reference to itself to the Module via
Public Property. (The same Public Property can be used to set the reference
to Nothing as the corresponding Form unloads.) By creating a Public Sub
within a Forms' code module your Standard Module can communicate with the
Form using it's Module-Level Form Variable. (i.e. Call mForm1.MySub().)

Spence


Show quoteHide quote
"Alexandros Peropulous" <perop***@gmail.com> wrote in message
news:%23u7%23sJUSLHA.796@TK2MSFTNGP02.phx.gbl...
> Hello!
>
> I have a class which I needed to make global because it is used in/ on
> different forms, and the class opens and closes port handles, so I cannot
> simply make a few more copies of them.
>
> However, on some of the forms, I would need a notification about events
> that the class handles.
>
> Normally in my form I would dim the class and receive the events by
> RaiseEvent like this:
>
> private withevents m_Class as Class1
>
> But since the class is global, I cannot do this.
>
> Does somebody have any ideas? I don't want to poll the class with a timer
> to query the event...
>
> Thank you!
> Alex
Author
31 Aug 2010 9:20 PM
Larry Serflaten
"Alexandros Peropulous" <perop***@gmail.com> wrote

> I have a class which I needed to make global because it is used in/ on
> different forms, and the class opens and closes port handles, so I
> cannot simply make a few more copies of them.

Can you define global, a little better?  Every class module you add is
available to any other code module in the project.  You don't get more
global than that unless you are talking about access from different
programs, which you did not mention....


> Normally in my form I would dim the class and receive the events by
> RaiseEvent like this:
>
> private withevents m_Class as Class1
>
> But since the class is global, I cannot do this.


Why can't you do that?  That is exactly how you go about recieving
events from a class....

LFS
Author
1 Sep 2010 1:29 AM
Kevin Provance
"Larry Serflaten" <serfla***@gmail.com> wrote in message
news:i5k7ja$e4p$1@news.eternal-september.org...

: Why can't you do that?  That is exactly how you go about recieving
: events from a class....

I'm getting the idea he has a cls file with events that he wants to use
globally.  But since WithEvents won't work in a module and he doesn't have a
central form, but rather several different ones depending on various
criteria, he wants to be able to instance his class with the events for use
from any form.

That said, the OP might want to review this gem from Karl's site:
http://vb.mvps.org/samples/SyncEvts/ (Several ways to share events (timers,
in this demo) amongst multiple objects)

- Kev
Author
1 Sep 2010 4:24 AM
ralph
Show quote Hide quote
On Tue, 31 Aug 2010 21:29:14 -0400, "Kevin Provance" <k@p.c> wrote:

>
>"Larry Serflaten" <serfla***@gmail.com> wrote in message
>news:i5k7ja$e4p$1@news.eternal-september.org...
>
>: Why can't you do that?  That is exactly how you go about recieving
>: events from a class....
>
>I'm getting the idea he has a cls file with events that he wants to use
>globally.  But since WithEvents won't work in a module and he doesn't have a
>central form, but rather several different ones depending on various
>criteria, he wants to be able to instance his class with the events for use
>from any form.
>
>That said, the OP might want to review this gem from Karl's site:
>http://vb.mvps.org/samples/SyncEvts/ (Several ways to share events (timers,
>in this demo) amongst multiple objects)
>

I noticed that my other response to the OP was truncated. And perhaps
mercifully, as that article is far more useful than my rambling. <g>

I think what was bothering the OP was simply that he was not aware he
could set m_Class to a 'global' object.

     Private WithEvents m_Class As Class1
     Set m_Class = globalInstanceOfClass1

I generally prefer to provide a constructor and pass the object as a
parameter to avoid embedding a "global', and to make it a little
clearer that the class has an outside dependency. But that is a matter
of style.

-ralph
Author
1 Sep 2010 5:03 AM
Kevin Provance
Show quote Hide quote
"ralph" <nt_consultin***@yahoo.net> wrote in message
news:ctjr7693b51j7o698mj38q4oiusqn5cap6@4ax.com...
: On Tue, 31 Aug 2010 21:29:14 -0400, "Kevin Provance" <k@p.c> wrote:

: I noticed that my other response to the OP was truncated. And perhaps
: mercifully, as that article is far more useful than my rambling. <g>
:
: I think what was bothering the OP was simply that he was not aware he
: could set m_Class to a 'global' object.
:
:     Private WithEvents m_Class As Class1
:     Set m_Class = globalInstanceOfClass1
:
: I generally prefer to provide a constructor and pass the object as a
: parameter to avoid embedding a "global', and to make it a little
: clearer that the class has an outside dependency. But that is a matter
: of style.

And where exactly are you making those declarations?
Author
1 Sep 2010 1:13 PM
ralph
Show quote Hide quote
On Wed, 1 Sep 2010 01:03:20 -0400, "Kevin Provance" <k@p.c> wrote:

>
>"ralph" <nt_consultin***@yahoo.net> wrote in message
>news:ctjr7693b51j7o698mj38q4oiusqn5cap6@4ax.com...
>: On Tue, 31 Aug 2010 21:29:14 -0400, "Kevin Provance" <k@p.c> wrote:
>
>: I noticed that my other response to the OP was truncated. And perhaps
>: mercifully, as that article is far more useful than my rambling. <g>
>:
>: I think what was bothering the OP was simply that he was not aware he
>: could set m_Class to a 'global' object.
>:
>:     Private WithEvents m_Class As Class1
>:     Set m_Class = globalInstanceOfClass1
>:
>: I generally prefer to provide a constructor and pass the object as a
>: parameter to avoid embedding a "global', and to make it a little
>: clearer that the class has an outside dependency. But that is a matter
>: of style.
>
>And where exactly are you making those declarations?

Inside a module that needs the Event services of a Class1 object.

See Nobody's post for one example.

-ralph
Author
31 Aug 2010 11:57 PM
ralph
On Tue, 31 Aug 2010 21:25:15 +0200, Alexandros Peropulous
<perop***@gmail.com> wrote:

Show quoteHide quote
>Hello!
>
>I have a class which I needed to make global because it is used in/ on
>different forms, and the class opens and closes port handles, so I
>cannot simply make a few more copies of them.
>
>However, on some of the forms, I would need a notification about events
>that the class handles.
>
>Normally in my form I would dim the class and receive the events by
>RaiseEvent like this:
>
>private withevents m_Class as Class1
>
>But since the class is global, I cannot do this.
>

Why not?

Creat
Author
2 Sep 2010 10:26 AM
Dee Earley
On 01/09/2010 00:57, ralph wrote:
Show quoteHide quote
> On Tue, 31 Aug 2010 21:25:15 +0200, Alexandros Peropulous
> <perop***@gmail.com>  wrote:
>
>> Hello!
>>
>> I have a class which I needed to make global because it is used in/ on
>> different forms, and the class opens and closes port handles, so I
>> cannot simply make a few more copies of them.
>>
>> However, on some of the forms, I would need a notification about events
>> that the class handles.
>>
>> Normally in my form I would dim the class and receive the events by
>> RaiseEvent like this:
>>
>> private withevents m_Class as Class1
>>
>> But since the class is global, I cannot do this.
>>
>
> Why not?

If the object is "Global" in a COM server then I don't think there is an
explicit instance that you can assign to a variable.

I assume they mean the Global where you can access the members without
declaring an object, just like the VB and VBA objects.

This can be worked around byt only using a single explicit reference as
others have suggested.

--
Dee Earley (dee.ear***@icode.co.uk)
i-Catcher Development Team

iCode Systems

(Replies direct to my email address will be ignored.
Please reply to the group.)
Author
2 Sep 2010 2:16 PM
ralph
On Thu, 02 Sep 2010 11:26:06 +0100, Dee Earley
<dee.ear***@icode.co.uk> wrote:

Show quoteHide quote
>On 01/09/2010 00:57, ralph wrote:
>> On Tue, 31 Aug 2010 21:25:15 +0200, Alexandros Peropulous
>> <perop***@gmail.com>  wrote:
>>
>>> Hello!
>>>
>>> I have a class which I needed to make global because it is used in/ on
>>> different forms, and the class opens and closes port handles, so I
>>> cannot simply make a few more copies of them.
>>>
>>> However, on some of the forms, I would need a notification about events
>>> that the class handles.
>>>
>>> Normally in my form I would dim the class and receive the events by
>>> RaiseEvent like this:
>>>
>>> private withevents m_Class as Class1
>>>
>>> But since the class is global, I cannot do this.
>>>
>>
>> Why not?
>
>If the object is "Global" in a COM server then I don't think there is an
>explicit instance that you can assign to a variable.
>
>I assume they mean the Global where you can access the members without
>declaring an object, just like the VB and VBA objects.
>
>This can be worked around byt only using a single explicit reference as
>others have suggested.

Are you talking about "late binding"???

I can't see where the OP suggested he was using late-binding or an
external component.

-ralph
Author
2 Sep 2010 3:39 PM
Dee Earley
On 02/09/2010 15:16, ralph wrote:
Show quoteHide quote
> On Thu, 02 Sep 2010 11:26:06 +0100, Dee Earley
> <dee.ear***@icode.co.uk>  wrote:
>
>> On 01/09/2010 00:57, ralph wrote:
>>> On Tue, 31 Aug 2010 21:25:15 +0200, Alexandros Peropulous
>>> <perop***@gmail.com>   wrote:
>>>
>>>> Hello!
>>>>
>>>> I have a class which I needed to make global because it is used in/ on
>>>> different forms, and the class opens and closes port handles, so I
>>>> cannot simply make a few more copies of them.
>>>>
>>>> However, on some of the forms, I would need a notification about events
>>>> that the class handles.
>>>>
>>>> Normally in my form I would dim the class and receive the events by
>>>> RaiseEvent like this:
>>>>
>>>> private withevents m_Class as Class1
>>>>
>>>> But since the class is global, I cannot do this.
>>>
>>> Why not?
>>
>> If the object is "Global" in a COM server then I don't think there is an
>> explicit instance that you can assign to a variable.
>>
>> I assume they mean the Global where you can access the members without
>> declaring an object, just like the VB and VBA objects.
>>
>> This can be worked around byt only using a single explicit reference as
>> others have suggested.
>
> Are you talking about "late binding"???

No, I never mentioned any form of binding.

> I can't see where the OP suggested he was using late-binding or an
> external component.

One of their previous posts was an OOP COM server hosting the Comm32
control.
One of the instancing modes in a COM server is GlobalMultiuse.
I believe this is the "global" they are referring to.

--
Dee Earley (dee.ear***@icode.co.uk)
i-Catcher Development Team

iCode Systems

(Replies direct to my email address will be ignored.
Please reply to the group.)
Author
2 Sep 2010 5:21 PM
ralph
On Thu, 02 Sep 2010 16:39:48 +0100, Dee Earley
<dee.ear***@icode.co.uk> wrote:


>
>> I can't see where the OP suggested he was using late-binding or an
>> external component.
>
>One of their previous posts was an OOP COM server hosting the Comm32
>control.
>One of the instancing modes in a COM server is GlobalMultiuse.
>I believe this is the "global" they are referring to.

Still it wouldn't make any difference.

    Private WithEvents m_Class As Class1
    Set m_Class = globalInstanceOfClass1

is how it is done.

*unless "globalInstanceOfClass1" is an Object Reference to a type
Object and not of type Class1. But I doubt this is the case since the
OP was apparently able to implement an Class1.IConnection~ interface
before deciding to go "global".

But this is so obvious, I must be missing something. <g>

-ralph
Author
6 Sep 2010 7:54 AM
Dee Earley
On 02/09/2010 18:21, ralph wrote:
Show quoteHide quote
> On Thu, 02 Sep 2010 16:39:48 +0100, Dee Earley
> <dee.ear***@icode.co.uk>  wrote:
>
>
>>
>>> I can't see where the OP suggested he was using late-binding or an
>>> external component.
>>
>> One of their previous posts was an OOP COM server hosting the Comm32
>> control.
>> One of the instancing modes in a COM server is GlobalMultiuse.
>> I believe this is the "global" they are referring to.
>
> Still it wouldn't make any difference.
>
>      Private WithEvents m_Class As Class1
>      Set m_Class = globalInstanceOfClass1
>
> is how it is done.
>
> *unless "globalInstanceOfClass1" is an Object Reference to a type
> Object and not of type Class1. But I doubt this is the case since the
> OP was apparently able to implement an Class1.IConnection~ interface
> before deciding to go "global".
>
> But this is so obvious, I must be missing something.<g>

I don't think Global (in COM instancing) gives you access to a single
instance to assign as you will.

As it has already been determined to be a single global variable, this
is all moot now though :)

--
Dee Earley (dee.ear***@icode.co.uk)
i-Catcher Development Team

iCode Systems

(Replies direct to my email address will be ignored.
Please reply to the group.)
Author
6 Sep 2010 7:56 AM
Dee Earley
On 06/09/2010 08:54, Dee Earley wrote:
> On 02/09/2010 18:21, ralph wrote:
>> But this is so obvious, I must be missing something.<g>
>
> I don't think Global (in COM instancing) gives you access to a single
> instance to assign as you will.

Having said that, this works:
Dim X As VB.Global

   Set X = VB.Global
   MsgBox X.Forms.Count

Oh well :)

--
Dee Earley (dee.ear***@icode.co.uk)
i-Catcher Development Team

iCode Systems

(Replies direct to my email address will be ignored.
Please reply to the group.)
Author
2 Sep 2010 5:21 PM
Larry Serflaten
"Dee Earley" <dee.ear***@icode.co.uk> wrote
> One of their previous posts was an OOP COM server hosting the Comm32
> control.
> One of the instancing modes in a COM server is GlobalMultiuse.
> I believe this is the "global" they are referring to.

See the post from 09/02/2010.  Global simply meant application wide,
declared public in a standard module....

LFS
Author
1 Sep 2010 7:00 AM
Nobody
Try:

' Module1

Public g_Class As Class1

Public Sub Main()
    Set g_Class = New Class1
    Form1.Show
End Sub

' Form1

Private WithEvents m_Class as Class1

Private Sub Form_Load()
    Set m_Class = g_Class
End Sub

Private Sub Form_Unload()
    Set m_Class = Nothing
End Sub
Author
2 Sep 2010 11:20 AM
Alexandros Peropulous
I want to instantiate the class only ONCE, therefore I declare it in a
module

Now here is all my code:

Module1:
--------------------------------------
Option Explicit

Public g As Class1

Public Sub Main()

     Set g = New Class1

     Form1.Show
     Form2.Show
     Form3.Show

End Sub
--------------------------------------

Class1:

Option Explicit

Public Event NewMessage(ByVal uString As String)

Public Sub SendGlobalMessage(ByVal u As String)

     RaiseEvent NewMessage(u)

End Sub
--------------------------------------
Form1:

Option Explicit

Private Sub Command1_Click()

     g.SendGlobalMessage Me.Text1.Text

     'I want form2 and form3 to get that event.
     'But I don't want to do this with a timer

End Sub

Private Sub Form_Load()

End Sub
--------------------------------------
Form2:

Option Explicit

Private WithEvents m As Class1

Private Sub m_NewMessage(ByVal uString As String)

     Me.Caption = uString

End Sub
--------------------------------------
Form3:

Option Explicit

Private WithEvents m As Class1

Private Sub m_NewMessage(ByVal uString As String)

     Me.Caption = uString

End Sub
Author
2 Sep 2010 12:00 PM
Schmidt
"Alexandros Peropulous" <perop***@gmail.com> schrieb im Newsbeitrag
news:%23aXSPEpSLHA.5572@TK2MSFTNGP02.phx.gbl...

> I want to instantiate the class only ONCE, therefore
> I declare it in a module

Nothing wrong with that - and you've done that
already in Sub Main with:
Set g = New Class1

> Private Sub Command1_Click()
>
>      g.SendGlobalMessage Me.Text1.Text
>
>      'I want form2 and form3 to get that event.
>      'But I don't want to do this with a timer

No problem, just add a single Line:
Set m = g

into your Form_Load() routines of Form2 and Form3
and you're done.

The line: Set m = g  does not create an instance -
it just sets an additional Reference-Variable 'm'
to the instance which is also *pointed-to* by the
globally reachable Reference-Variable 'g'.

Maybe to make that a little bit more clear, a VB-
Object-Instance (created either per 'New' or
per 'CreateObject') is thereby allocated on the
Process-Heap and available/accessable
throughout the whole VB-Process/Thread.

You can manage the accessibility of this
always "globally available by principle"
Object-Instance over the scope your
Object-*Variables* (which are only Pointers
to this Instance).

So, in other words, if you decide to *create*
a new Instance in the "least hidden Private-Class",
but then manage, to pass the referencing Variable of
this "alleged privately created Instance"  (by Parameter
in an Event or however) to a globally defined
VB-Object-Variable of the same (Class-)Type,
then this is in no way different from what you
currently do (creating the instance in Sub Main) -
so it does not matter *where* you create the instance -
accessibility of the instance is only determined by one
(or the other) current Variable which points to it -
and this current Variables scope.

Olaf
Author
2 Sep 2010 7:10 PM
Alexandros Peropulous
Jesus, thanks a lot!!
Author
3 Sep 2010 1:08 AM
Spence
Let that be a lesson to ya...   :-)


Show quoteHide quote
"Alexandros Peropulous" <perop***@gmail.com> wrote in message
news:OMHo2KtSLHA.2100@TK2MSFTNGP04.phx.gbl...
> Jesus, thanks a lot!!
Author
2 Sep 2010 1:49 PM
Larry Serflaten
"Alexandros Peropulous" <perop***@gmail.com> wrote
> I want to instantiate the class only ONCE, therefore I declare it in a
> module

Then you need to be sure the New command is only executed ONCE.

> Option Explicit
>
> Public g As Class1
>
> Public Sub Main()
>
>      Set g = New Class1
>
>      Form1.Show
>      Form2.Show
>      Form3.Show
>
> End Sub

That should do it!  At that point you have one instance each of
Class1, Form1, Form2, and Form3.

To begin listening for messages, you need to get access to that
one global instance:


> --------------------------------------
> Form2:
>
> Option Explicit
>
> Private WithEvents m As Class1
>
> Private Sub m_NewMessage(ByVal uString As String)
>
>      Me.Caption = uString
>
> End Sub

In forms 2 and 3, you need that WithEvents declaration AND
a live instance of Class1.  To get the live instance, add:

Private Sub Form_Load()
    Set m = g
End Sub

That does not create a new instance, it makes m and g point to
the very same object, which is what you want to happen.  Including
the same in form 3, you end up with 3 (Class1 type) variables all
pointing to the same (Class1 type) object.

Then, to follow 'best practices' guidelines, you'd want to release
all of your objects when you are done with them:

Private Sub Form_Unload(Cancel As Integer)
    Set m = Nothing    ' < Forms 2 & 3

    If Forms.Count = 1 Then   ' < All forms
        Set g = Nothing
    End if
End Sub


HTH
LFS