By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,276 Members | 1,951 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,276 IT Pros & Developers. It's quick & easy.

Custom Collection Class woes

P: n/a
I'm in the process of expanding my knowledge and use of Class Modules.
I've perused MSDN and this and other sites, and I'm pretty comfortable
with my understanding of Class Modules with the exception of custom
Collection Classes.

Background: I'm developing an A2K .mdb to be deployed as an .mde at my
current job-site. It has several custom controls which utilize custom
classes to wrap built-in controls, and add additional functionality. In
my job, I'm only at this site for about another year, and I'd like for
the folks that follow me here to be able to add the same custom
controls with minimal effort on forms they may need to construct down
the road. Making them a custom class also reduces the repetition of
reinventing them for every form I construct.

Details on the controls:

Type1 is an image control that acts like a command/toggle button. The
control has three states and is used to call code to bring up the
Office Assistant to serve a WhatsThis type function. That functionality
doesn't require a compiled help file, but gets its display inputs from
the database itself. This control has three states. Initially it is
flat with a dimmed image. OnMouseMove it is raised with a clear image.
OnClick it is armed for Assistant calls, and the image is sunken with a
dark image. On subsequent Clicks, the Assistant goes away, and the
button returns to its raised state. OnMouseOut which is simulated using
ctl.Section.OnMouseMove, the button returns to its default, flat,
state.

Type2 is a label control that acts like a hyperlink. It has similar
OnMouseMove, OnMouseDown, and OnMouseUp functionality to Type1 and also
utilizes ctl.Section.OnMouseMove to simulate MouseOut behaviour.

Both types are associated with existing controls using this code in the
form that utilizes them:

************
' Declarations section
************
Public/Private mclsControlX as CustomClass
' Public for Type1 to allow the Assistant to
' change the state of the control when
' cancelled and Private for Type2.
************
' Form_Load code
************
Set mclsControlX = New CustomClass
Set mclsControlX.Control(x, y) = ctlControlOnForm

Problem 1: After reference to the aforementioned sources, I've been
able to create a custom Collection Class that wraps the built-in
Collection type. What I've been unable to do is assign all the
CustomClass objects to the same Collection. I've tried establishing a
reference to the collection in the CustomControl.Control Property Set
procedure, but this has failed. I use this code for that Property Set:

************
' CustomClass module
************
Public Property Set Control(x ..., y ..., img as Image)
....
Dim col as CustomCollection
Set col = New CustomCollection
col.ClsControls.Add img, img.Name

The Initialize and Terminate events for the CustomCollection fire every
time this Property Set code runs and the Collection is neither singular
(collecting every control of TypeX), nor persistant. How do I make the
Collection both singular and persistant?

I tried using:

If col.ClsControls.Count > 0

But, that throws object Error 91 every time because this instance of
the CustomCollection hasn't been created, yet.

How do I set this CustomCollection up to wrap a built-in Collection and
become a container for all CustomClass objects of Type1 or Type2,
respectively?

Problem 2: I can't really tell when the Terminate event for the
CustomClass objects is firing. Since I don't want to leave unassociated
or dormant Class objects laying around in memory, I have been setting
the module level object variable that contains the reference to these
objects to Nothing in the Terminate event. Do I need to remove that
reference with the Nothing keyword to the Form_Unload event where the
controls are instantiated or is the Terminate event of the Class
sufficient?

Hope that's descriptive enough. If not, I'll try to clear the fog
wherever there is any.

Thanks in advance.

Jamey Shuemaker

Feb 19 '06 #1
Share this Question
Share on Google+
19 Replies


P: n/a
"Jamey Shuemaker" <ca*********@yahoo.com> wrote:

************
' CustomClass module
************
Public Property Set Control(x ..., y ..., img as Image)
...
Dim col as CustomCollection
Set col = New CustomCollection
col.ClsControls.Add img, img.Name

The Initialize and Terminate events for the CustomCollection fire every
time this Property Set code runs and the Collection is neither singular
(collecting every control of TypeX), nor persistant. How do I make the
Collection both singular and persistant?


I'm not sure what "ClsControls" and "CustomCollection" are supposed
to be. I'll go out on a limb here and assume the following:

1. You intended to create a Collection called "col" (a custom collection.)
2. You want to populate your collection with objects of the type described
in ClsControls (the code for which you have not posted.)

Assuming I got that right, then I suggest the following:

'The collection must be at the module level, or else it will
'vanish as soon as your Property Set procedure exits.

Private col as new Collection 'Module-level declaration

Public Property Set Control(x ..., y ..., img as Image)
'...
dim objClsControls as new ClsControls 'Declare object

'Set object properties (x? y? img?)
set objClsControls.img = img
set objClsControls.x = x
set objClsControls.y = y

'Now add the object to the collection, using the image
name as the collection key. Explicitly coerce it to a
string, just for good measure.

col.add objClsControls, cstr(img.name)
'...
end property


Feb 19 '06 #2

P: n/a
Sorry about that, here's the old code from the Collection Class Module:

*********
' Class Module named CollectionClass
*********
Private mCol as Collection

Public Property Set ClsControls(col as Collection)
Set mCol = col
End Property

Public Property Get ClsControls as Collection
Set ClsControls = mCol
End Property

*********

The object props above are actually:

x = A long integer that accompanies an Enumeration at the beginning of
the module to set the Type of the Class. In this case, it's always zero
(0) because I've only begun working with one type of image control
(button). I've envisioned several other custom buttons (spinner
buttons, custom navigation buttons, etc.) that behave slightly
differently than this Case 0.

y = A Section object, in this case, the section in which the control
resides. This is used by a module level object variable "mSct" to
handle the MouseOut type events I mentioned above.

img = This is the reference to the actual control that will be
associated with the custom Class.

The first code snipet above is the code from the Form's module, in this
case just the Type1 custom Class:

*********
' Declarations
*********
Public mclsControlX as CustomClass

*********
' Form_Load
*********
Set mclsControlX = New CustomClass
Set mclsControlX(0, Me.Section(Me!ctlControlOnForm.Section)) = _
Me!ctlControlOnForm

*********

The second code snipet above is from the custom Class Module, where I
was instantiating this element of the collection:

*********
' Declarations
*********
Private WithEvents mImg as Image
Private WithEvents mSct as Section

Enum BtnType
sbCSH = 0
sbIncrement = 1
....
sbClose = 7
End Enum

*********
' Property Set and Get to wrap built-in Image control
*********
Public Property Get Control(lngType as BtnType, _
sct as Section, img as Image)
Set mImg = img
With mImg
.OnMouseMove = "[Event Procedure]"
.OnClick = "[Event Procedure]"
.SpecialEffect = 0
End With
....
Set mSct = sct
mSct.OnMouseMove = "[Event Procedure]"
....
' More code to set the three image paths
' so that mImg.Control.Picture can be
' changed later with state changes.
....
Dim col as New CustomCollection
col.ClsControls.Add img, img.Name
End Property

Public Property Get Control(lngType as BtnType, _
sct as Section) as Image
Set Control = mImg
End Property
*********

I've had something similar to what you suggested, but I'll try it
exactly like that. Whatever the case, I haven't been able to maintain
the persistance of the Collection Class, at least not where I can know
how to reference it.

As a side note, I know that my custom Class Objects are persisting
longer than I want them to, because once they are referenced to the
actual physical control on the form, if I try to delete that physical
control, the DB shuts down, abnormally. I'm not sure where my Scope
problems are, but I assume that I'll have to start removing those
references in Form_Unload.

Feb 20 '06 #3

P: n/a
Got it working by populating the collection in the Form's module. I
thought you could do the same by calling it in the Class Module for the
custom class, but I suppose that's not the case. Maybe if there were a
way to call it without using the New keyword, it could be done at Class
Module level, but I can't figure a way to do it.

Still have some Scope concerns. Any suggestions?

Feb 20 '06 #4

P: n/a
"Jamey Shuemaker" <ca*********@yahoo.com> wrote:

I've had something similar to what you suggested, but I'll try it
exactly like that.
Well, I only suggested that based on a wild guess about what
you are trying to do. Now that you have posted more code,
I must shamefully admit that I'm lost. I have enough trouble
figuring out my _own_ code sometimes, and even more so
when reviewing something online.
Whatever the case, I haven't been able to maintain
the persistance of the Collection Class, at least not where I can know
how to reference it.
All I can suggest is that you carefully review the scope on your
object declarations. If your CollectionClass objects are vanishing,
then they are almost certainly going out of scope.
As a side note, I know that my custom Class Objects are persisting
longer than I want them to, because once they are referenced to the
actual physical control on the form, if I try to delete that physical
control, the DB shuts down, abnormally. I'm not sure where my Scope
problems are, but I assume that I'll have to start removing those
references in Form_Unload.


Hmm. Good luck with that.
Feb 20 '06 #5

P: n/a
rkc
Jamey Shuemaker wrote:
Got it working by populating the collection in the Form's module. I
thought you could do the same by calling it in the Class Module for the
custom class, but I suppose that's not the case. Maybe if there were a
way to call it without using the New keyword, it could be done at Class
Module level, but I can't figure a way to do it.
Your collection was declared and instantiated within a property
procedure. It's scope begins and ends in the procedure.
Still have some Scope concerns. Any suggestions?


Explicitly set all object (controls in your case) variables set
in your class modules to nothing in the Class_Terminate procedure.

Explicitly set the collection in the Form's module to nothing in
Form's Close event.

One of the Terry's (or Trevor's) that posts here suggests actually
removing all objects from the collection. Whichever it was doesn't
do a lot of talking through his hat so I do that now also.

Don't edit wrapped controls after running code without doing a
Debug -> Break -> Reset first.

Feb 20 '06 #6

P: n/a
rkc
It was Terry Kreft.

In a nutshell:

Private m_MyBooks As Collection
' ************************************
'

Private Sub Class_Initialize()
Set m_MyBooks = New Collection
End Sub

Private Sub Class_Terminate()
Do Until m_MyBooks.Count = 0
Call m_MyBooks.Remove(1)
Loop
end sub
Feb 20 '06 #7

P: n/a
"Jamey Shuemaker" <ca*********@yahoo.com> wrote in
news:11**********************@z14g2000cwz.googlegr oups.com:
Got it working by populating the collection in the Form's module.
I thought you could do the same by calling it in the Class Module
for the custom class, but I suppose that's not the case. Maybe if
there were a way to call it without using the New keyword, it
could be done at Class Module level, but I can't figure a way to
do it.

Still have some Scope concerns. Any suggestions?


Well, I'm very confused by all the things you've posted. I don't
understand any number of things:

1. are you creating a new instance of the class for each instance of
your custom control? If so, then I must have misunderstood what
you're doing, since each instance of the class would have only one
member in its internal collection.

2. you originally said you were working with a class wrapper around
a custom collection. That would mean that you'd want to use the same
class instance for all the items you are adding to your collection.
As you know, a custom class cannot be a public member of a class
module, so you have to create a wrapper around the collection to
populate it and clear items from it.

3. for a class instance to be used in multiple forms, the variable
used to refer to that class instance has to be publicly available at
all times. That means you either make it a public member of class
omdule or as a public member of a form that is always open. I'd
think that the former is easier than the latter, but I could see
circumstances where you'd do that latter (a form is, after all, just
a class module with a user interface included along with it).

4. if you declare your class variable with the NEW keyword, any call
to the class instance will initialize it. If you *don't* declare it
with the NEW keyword, you must initialize the class module before
using it. This can be done in startup code, or it could be done in
the OnOpen events of each form that uses the class instance (by
checking if it's Nothing and initializing if it is; that could
easily be put in a public function somewhere).

Now, those are all things that have an effect on scope, and if I've
understood what you're trying to do, you're simply declaring the
variable for your class instance in the wrong place.

But, as I said, I was very confused by what you've posted, so all of
what I"ve written above may be useless to you.

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/
Feb 20 '06 #8

P: n/a

rkc wrote:
Private m_MyBooks As Collection
' ************************************
'

Private Sub Class_Initialize()
Set m_MyBooks = New Collection
End Sub

Private Sub Class_Terminate()
Do Until m_MyBooks.Count = 0
Call m_MyBooks.Remove(1)
Loop
end sub


Yeah, that's one of the resources I started with. See below for details
of where I stand now. Looks like I've got it solved.

Feb 21 '06 #9

P: n/a
UPDATE:

First off, thanks for the help and sorry for the confusion. I though I
described the problem fairly well, but looking back, I guess I jumped
around a bit.

*********
' CustomCollection Class Module
*********
Private mCol as Collection

Public Property Set ColControls(col as Collection)
Set mCol = col
End Property

Public Property Get ColControls as Collection
Set ColControls = mCol
End Property

Private Sub Class_Terminate()
Do Until mCol.Count = 0
mCol.Remove 1
Loop
Set mCol = Nothing
End Sub

*********
' CustomControl Class Module
*********
Private WithEvents mImg As Image
Private WithEvents mSct as Section
Private mlngType as BtnType

Enum BtnType
sbCSH = 0
sbIncrement = 1
...
sbClose = 7
End Enum

Public Property Set Control(lngType as BtnType, _
sct as Section, img as Image)
Set mImg = img
With mImg
.OnMouseMove = "[Event Procedure]"
' Other display settings
...
End With
Set mSct = sct
mSct.OnMouseMove = "[Event Procedure]"
mlngType = lngType
' Set other display attributes by Type
....
End Property

Public Property Get Control(lngType as BtnType, _
sct as Section) As Image
Set Control = mImg
End Property

Private Sub Class_Terminate()
Set mImg = Nothing
End Sub

Private Sub mImg_Click()
' Some code to execute OnClick
End Sub

Private Sub mSct_MouseMove(...)
With mImg
' Code to reset default display attributes
End With
End Sub

*********
' Form Module Declarations
*********
Private mclsCol as CustomCollection
Public mclsBtn0 as CustomClass
Private mclsBtn1 as CustomClass

*********
' Form Module Code
*********
Private Sub Form_Load()
With Me
Set mclsCol = New CustomCollection
Set mclsBtn0 = New CustomClass
Set mclsBtn0.Control(0, .Section(.ctlOnForm.Section)) = _
.ctlOnForm
mclsCol.ColControls.Add .ctlOnForm, _
.ctlOnForm.Name
Set mclsBtn1... ' Same as above
End With
End Sub

Private Sub Form_Unload(Cancel as Integer)
Set mclsCol = Nothing
Set mclsBtn0 = Nothing
Set mclsBtn1 = Nothing
End Sub

*********
' End Code
*********

Questions that remain:

Am I adequately killing off all the custom class objects with the
Terminate events and the Form_Unload procedure? Do I need to enumerate
through all elements of the Form module level "mclsCol" object variable
and use the Remove method to get them out of memory, as well?

Do I need something like this in the Initialize event for each custom
class?

*********
Private Sub Class_Initialize()
Set mCol = New Collection
End Sub
*********

Thanks again.

Feb 21 '06 #10

P: n/a

David W. Fenton wrote:
1. are you creating a new instance of the class for each instance of
your custom control? If so, then I must have misunderstood what
you're doing, since each instance of the class would have only one
member in its internal collection.
No. The intention was to have a single collection for all class objects
of a particular type.
2. you originally said you were working with a class wrapper around
a custom collection. That would mean that you'd want to use the same
class instance for all the items you are adding to your collection.
As you know, a custom class cannot be a public member of a class
module, so you have to create a wrapper around the collection to
populate it and clear items from it.
Got that. Didn't when we started this inquest.
3. for a class instance to be used in multiple forms, the variable
used to refer to that class instance has to be publicly available at
all times. That means you either make it a public member of class
omdule or as a public member of a form that is always open. I'd
think that the former is easier than the latter, but I could see
circumstances where you'd do that latter (a form is, after all, just
a class module with a user interface included along with it).
Wait a minute. Didn't you say in #2 above that custom classes cannot be
public members of a class module? I think you meant they can't be
public members of their own class module. Is that right?
4. if you declare your class variable with the NEW keyword, any call
to the class instance will initialize it. If you *don't* declare it
with the NEW keyword, you must initialize the class module before
using it. This can be done in startup code, or it could be done in
the OnOpen events of each form that uses the class instance (by
checking if it's Nothing and initializing if it is; that could
easily be put in a public function somewhere).
Once a custom class wrapping a collection is initialized, I can add to
it as long as it is open. It will stay open as long as the Form or
Module that initialized it is open, right?

On another note, if I don't set that reference to Nothing when the form
closes it stays in memory regardless of whether I can still reference
it, correct?
Now, those are all things that have an effect on scope, and if I've
understood what you're trying to do, you're simply declaring the
variable for your class instance in the wrong place.
I'm pretty sure that was the case. See below for current status on the
class modules.
But, as I said, I was very confused by what you've posted, so all of
what I"ve written above may be useless to you.


Not at all.

Feb 21 '06 #11

P: n/a
rkc
Jamey Shuemaker wrote:
Questions that remain:

Am I adequately killing off all the custom class objects with the
Terminate events and the Form_Unload procedure? Do I need to enumerate
through all elements of the Form module level "mclsCol" object variable
and use the Remove method to get them out of memory, as well?

Do I need something like this in the Initialize event for each custom
class?

*********
Private Sub Class_Initialize()
Set mCol = New Collection
End Sub
*********


Yes, you do need to do something like that in each CustomClass.
What you have now won't run without an error because the collection
is never actually created.

There is no collection created at form level so there is nothing to
unload. The unloading is handled in your CustomCollection class. As
far as I can see that is the only reason for the class as it you
have shown it.



Feb 21 '06 #12

P: n/a
rkc
rkc wrote:
Yes, you do need to do something like that in each CustomClass.
What you have now won't run without an error because the collection
is never actually created.


<edit>
CustomClass should read CustomCollection
</edit>
Feb 21 '06 #13

P: n/a
"Jamey Shuemaker" <ca*********@yahoo.com> wrote in
news:11**********************@g47g2000cwa.googlegr oups.com:
David W. Fenton wrote:
1. are you creating a new instance of the class for each instance
of your custom control? If so, then I must have misunderstood
what you're doing, since each instance of the class would have
only one member in its internal collection.
No. The intention was to have a single collection for all class
objects of a particular type.


On multiple forms? If so, then I don't know why you'd ever have
contemplated declaring the variable used for your class instance at
the form level.
2. you originally said you were working with a class wrapper
around a custom collection. That would mean that you'd want to
use the same class instance for all the items you are adding to
your collection. As you know, a custom class cannot be a public
member of a class module, so you have to create a wrapper around
the collection to populate it and clear items from it.


Got that. Didn't when we started this inquest.


Above, what I meant to write was:

A custom COLLECTION cannot be a public member. . .

Don't know why I typed that.
3. for a class instance to be used in multiple forms, the
variable used to refer to that class instance has to be publicly
available at all times. That means you either make it a public
member of class omdule or as a public member of a form that is
always open. I'd think that the former is easier than the latter,
but I could see circumstances where you'd do that latter (a form
is, after all, just a class module with a user interface included
along with it).


Wait a minute. Didn't you say in #2 above that custom classes
cannot be public members of a class module? . . .


No. Above I meant to write custom *collections*, which, like arrays,
cannot be public members of a class module. If you try declaring a
custom collection or an array as public in a class module, you'll
get a compile error, and a useful error message telling you that you
can't do it. This is why you have to wrap the private
collection/array in a function/method/property in order to use it.
. . . I think you meant they can't be
public members of their own class module. Is that right?
Collections, not classes. I don't know if class instances can be
public members of classes, but you can test it yourself and find
out.
4. if you declare your class variable with the NEW keyword, any
call to the class instance will initialize it. If you *don't*
declare it with the NEW keyword, you must initialize the class
module before using it. This can be done in startup code, or it
could be done in the OnOpen events of each form that uses the
class instance (by checking if it's Nothing and initializing if
it is; that could easily be put in a public function somewhere).


Once a custom class wrapping a collection is initialized, I can
add to it as long as it is open. It will stay open as long as the
Form or Module that initialized it is open, right?


Yes.

But if you want the class to be used by multiple forms, then you
really oughtn't be declaring it at the form module level.
On another note, if I don't set that reference to Nothing when the
form closes it stays in memory regardless of whether I can still
reference it, correct?


Well, that's a good question. Theoretically, if the variable you're
using for your class instance is declared in the form module, then
closing the form should destroy the class instance.

That's why I'd tend to declare such a variable in a public module,
instead of in a form module. But I"m also assuming you're using a
single class instance for multiple forms.

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/
Feb 21 '06 #14

P: n/a
"Jamey Shuemaker" <ca*********@yahoo.com> wrote in
news:11**********************@g44g2000cwa.googlegr oups.com:
Am I adequately killing off all the custom class objects with the
Terminate events and the Form_Unload procedure? Do I need to
enumerate through all elements of the Form module level "mclsCol"
object variable and use the Remove method to get them out of
memory, as well?

Do I need something like this in the Initialize event for each
custom class?

*********
Private Sub Class_Initialize()
Set mCol = New Collection
End Sub
*********
I would say yes to that, but I'm confused on the architecture of
your code. I thought the custom collection was defined in the class
wrapper, not in the custom control class module (you really ought to
use better names for your classes, since the names you've used here
are completely generic and have meanings of their own, independent
of their use as the names of your class modules).

On the other hand, if you've declared the collection in the class
module with the NEW keyword, you don't need to initialize it, as the
first use of it will automatically initialize the collection.

I still think you are confused.

I certainly am, but in attempting to define what's confused about
your code, I'm not sure I have answers to enough questions to be
helpful. Let me take one code snippet and suggest what I see as
wrong with it:
*********
' Form Module Declarations
*********
Private mclsCol as CustomCollection
Public mclsBtn0 as CustomClass
Private mclsBtn1 as CustomClass


If the CustomCollection class instance is supposed to be used by
more than one form, then the declaration for your class instance
should not be here. If you want it to be used by only the two
instances of CustomClass that you are declaring in this form, then
it's OK for the collection to be defined here.

I think there's something structurally wrong here. You are declaring
a class instance for your custom collection, but I don't see that
this class instance (named mclsCol) is used in the class instances
you create for the controls.

It would seem to me that you'd have a single global class instance
of your custom collection wrapper, and its variable would be global.
That instance would then by used by the control class modules, and
you'd create as many instances of the control class as you needed.

This would also mean that your terminate code in the control class
would need to check the number of controls in the public collection
class, and terminate it only if the collection is empty.

Also, you'd want to remove the reference to the control used by each
instance of the control class from the global collection class
instance.

But I may have completely misunderstood your code, so all of the
above may be more confusing than helpful.

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/
Feb 21 '06 #15

P: n/a
rkc
David W. Fenton wrote:
But I may have completely misunderstood your code, so all of the
above may be more confusing than helpful.

The "CustomCollection" is simply used here as a way to not
have to declare a form level "CustomClass" variable for each
individual image-button widget. It may be the foundation for
something more, but here it could just as well be an unwrapped
instance of a vba.collection.

Feb 22 '06 #16

P: n/a
rkc <rk*@rochester.yabba.dabba.do.rr.bomb> wrote in
news:H6******************@twister.nyroc.rr.com:
David W. Fenton wrote:
But I may have completely misunderstood your code, so all of the
above may be more confusing than helpful.
The "CustomCollection" is simply used here as a way to not
have to declare a form level "CustomClass" variable for each
individual image-button widget. It may be the foundation for
something more, but here it could just as well be an unwrapped
instance of a vba.collection.


Well, that would be exactly what I'd use it for, but he's declaring
a variable in each of his form modules, according to the code he
posted:
*********
' Form Module Declarations
*********
Private mclsCol as CustomCollection
Public mclsBtn0 as CustomClass
Private mclsBtn1 as CustomClass


That seemed to me to be a mistake, but that's the way he's doing it,
according to his code.

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/
Feb 22 '06 #17

P: n/a
rkc
David W. Fenton wrote:
rkc <rk*@rochester.yabba.dabba.do.rr.bomb> wrote in
news:H6******************@twister.nyroc.rr.com:

David W. Fenton wrote:

But I may have completely misunderstood your code, so all of the
above may be more confusing than helpful.


The "CustomCollection" is simply used here as a way to not
have to declare a form level "CustomClass" variable for each
individual image-button widget. It may be the foundation for
something more, but here it could just as well be an unwrapped
instance of a vba.collection.

Well, that would be exactly what I'd use it for, but he's declaring
a variable in each of his form modules, according to the code he
posted:

*********
' Form Module Declarations
*********
Private mclsCol as CustomCollection
Public mclsBtn0 as CustomClass
Private mclsBtn1 as CustomClass

That seemed to me to be a mistake, but that's the way he's doing it,
according to his code.


I don't see any point in making the scope of the collection anything
other than form level. The widgets only exist if the form is open.
Making the collection global would just increase the complexity of
managing the disposal of the class instances, if that is in fact
necessary. I am taking Terry Kreft's word that it is. Not doing it
in the past never caused me any problems.


Feb 22 '06 #18

P: n/a
rkc <rk*@rochester.yabba.dabba.do.rr.bomb> wrote in
news:jT*******************@twister.nyroc.rr.com:
David W. Fenton wrote:
rkc <rk*@rochester.yabba.dabba.do.rr.bomb> wrote in
news:H6******************@twister.nyroc.rr.com:

David W. Fenton wrote:
But I may have completely misunderstood your code, so all of the
above may be more confusing than helpful.

The "CustomCollection" is simply used here as a way to not
have to declare a form level "CustomClass" variable for each
individual image-button widget. It may be the foundation for
something more, but here it could just as well be an unwrapped
instance of a vba.collection.

Well, that would be exactly what I'd use it for, but he's
declaring a variable in each of his form modules, according to
the code he posted:

*********
' Form Module Declarations
*********
Private mclsCol as CustomCollection
Public mclsBtn0 as CustomClass
Private mclsBtn1 as CustomClass

That seemed to me to be a mistake, but that's the way he's doing
it, according to his code.


I don't see any point in making the scope of the collection
anything other than form level. The widgets only exist if the form
is open. Making the collection global would just increase the
complexity of managing the disposal of the class instances, if
that is in fact necessary. I am taking Terry Kreft's word that it
is. Not doing it in the past never caused me any problems.


Well, I'm just going on what I thought the original poster said he
wanted, which was a single collection for all instances of the
controls on all forms.

Maybe I misunderstood.

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/
Feb 22 '06 #19

P: n/a

David W. Fenton wrote:
Well, I'm just going on what I thought the original poster said he
wanted, which was a single collection for all instances of the
controls on all forms.


First off, sorry I haven't been able to check back and answer more of
your questions about the intent of the code, till now. Things at work
and school have been quite busy.

RKC is right, I didn't intend for the collection to have scope beyond
the form level or remain after the form was closed. As it is, I didn't
envision any use for it above the form level where the custom classes
are associated with the actual image objects on the form. The only use
I had for the collection itself was to control the MouseOut type
behavior I was using to change the state of the images back to their
flat perspective.

Here's the intention of the custom class objects as I originally
envisioned it.

1. The custom classes (wrapping an image object) were originally
intended to allow the image swapping behavior. I've used nested images
with code in each form to change their visibility on mouse events to
provide the same display potental. In their flat state, they should
remain flat with subdued coloring on the form. OnMouseMove, they should
become raised with clear coloration, and OnMouseDown they should either
go to an armed state or give the appearance of response to a mouse
click like a command button or toggle button does when depressed, then
reverting to their raised state OnMouseUp and flat when the mouse moves
away from the control. The type enumeration that I implemented allowed
various different images (and other display data like width and height)
to be assigned to similar but not identical buttons. Setting the
'Control' property on those objects and assigning a reference to a
physical image control allowed me to set events for the class module to
accomplish the above without having to replicate it with three nested
images in each form. It also allowed me to set the events of the
section in which the image is located to return the image to its
default state without having to implement code in every form to provide
the MouseOut functionality.

2. The custom collection, at first, was an experiment based on the MSDN
Class Object article to see if I could get it to work and collect all
of the custom class buttons for easy reference outside of that
particular module (form, class, or otherwise). Obviously, any use of
the custom collection will have to be of adequate scope to remain in
memory as long as I have a need to reference it. I don't presently have
a need for any external reference to the collection or its controls
beyond the level of the form that contains them, so I didn't declare
the collection (or the buttons for that matter) at module level, only
at Form level. I do have a use for the collection at form level,
however. When a group of these controls, say a pair of spinner (single
unit increment/decrement) buttons are placed next to one another with
little or no space between them, I need the individual buttons to
revert to their subdued or flat state when the mouse moves off of the
increment button and onto the decrement button. With no space between
them the OnMouseMove event created for the section defined by the class
element doesn't fire, because the mouse never moves over that section.
Again, I don't think I need to declare this custom collection beyond
the form level because I don't use it for anything fancier than
changing display attributes while the form in question has the focus.

I do have a custom Context Sensitive Help (CSH) button (Type 0 of the
enumerated types of this custom class) which relies on module level
functions and subs to control the Office Assistant and provide
information for the user based on user clicks following the "arming" of
the CSH button on the form. For that, the Assistant can be canceled in
the Assistant's Balloon object as well as on the form itself with a
subsequant click of the CSH button. Since the Assistant may also change
the display of the form's button when cancelled in the balloon, the
object variable that assigns a reference to the actual image control on
the form does have global scope.

The code I'm running now accurately reflects the appropriate mouse and
click events, though I am still working on the custom collection for
the functionality mentioned in #2 above for controls that are in near
proximity.

I also have to dig into the API references I have to try to find an
easy way to intercept clicks after the application is placed in
WhatsThisMode to circumvent the built-in WhatsThis functionality. I'd
still like to keep the "What's This" pointer, but I don't actually want
the help file resource referenced, rather preferring to do that with a
reference table with the necessary information because the point-click
behaviors of HTML Help Workshop are a pain in the ass.

Anybody know of an API to interrupt mouse and click behavior or
interupt calls to the help object?

Feb 23 '06 #20

This discussion thread is closed

Replies have been disabled for this discussion.