Solved

Array of "Private WithEvents" controls : How?

Posted on 2000-03-01
11
1,174 Views
Last Modified: 2008-03-10
    I need to create an array of controls declared as "Private WithEvents".
     How can I do this?

     Restriction: I cannot put my controls in a form. I must create then
manually with Form.Controls.Add.

     Thanks
0
Comment
Question by:Binder
  • 3
  • 3
  • 2
  • +3
11 Comments
 
LVL 9

Expert Comment

by:Dalin
ID: 2574322
I sort of remember you can't do that in vb5. I am not sure about vb6.
0
 
LVL 6

Expert Comment

by:Marine
ID: 2574454
You can't do that in VB6 as well. sorry.
0
 
LVL 2

Expert Comment

by:tylerd
ID: 2574504
i agree, its not possible
0
 
LVL 1

Author Comment

by:Binder
ID: 2577382
Ooops. So maybe I came to a dead end here.
Or maybe there is another solution for this.

    I will be able to do what I want if:
       a) I can handle a collection of such objects
easily (i.e. without have to create one variable
for each and handle them separetely) OR
       b) I can guarantee that the controls inside
a form are created in a certain order that I can
choose. If this is possible then I can put
my controls in a form and create an array.
0
 
LVL 1

Expert Comment

by:prozak
ID: 2588049
In order to create new controls on a form you must place at least one of each type of control on the form with an Index of 0. Then when you try to access controls in this control array with an index of > 0, VB will automatically add the controls for you. The only drawback is you have to have at least one of the controls on the form in order to implement dynamic control creation.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 1

Author Comment

by:Binder
ID: 2592222
 Yes, but I can't have any controls on the
form because I need the controls to be created
in a certain order.
0
 
LVL 1

Expert Comment

by:prozak
ID: 2592289
You could have the initial control of each type be Visible = False and Enabled = False. This would allow the control to essentially not exist to the user.

The fact remains that in order to do dynamic control creation in VB you MUST have at least one of each type of control on the form. If this is not an acceptable solution then you simply can't use VB to code you application.
0
 
LVL 6

Expert Comment

by:andyclap
ID: 2593292
Prozak, as I think Binder knows, seems to have the wrong end of the stick - it is possible to do dynamic control creation in VB6, and very useful it is too - just look up "what's new in controls" in the help.

What Binder's asking for is a way of sinking events generically from all the controls he's added.

hmmm, how many points is this question?

.... OK I'll be nice, let me go away for 20 mins or so, and create a couple of useful classes for you...

0
 
LVL 1

Expert Comment

by:prozak
ID: 2593342
Ahhh, It's all becoming clear now... Thanks for the info andyclap. I was not aware of the VBObjectExtender object. I stand corrected, my understanding was that dynamic control creation was implemented by have a control array for each type and simply loading the next control in the control array would add a new control to the form. This would probably still yield better performance than the late-bound implementation using the VBObjectExtender but if it is precluded by the requirement of no controls then so be it.
0
 
LVL 6

Accepted Solution

by:
andyclap earned 200 total points
ID: 2593439
And here it is in all its gory glory....

Turned out I needed to avoid circular references too.

One comment - I've expected the controls to be VB custom controls, not intrinsic ones these don't implement vbcontrolextender. But for arrays of other controls, it shouldn't be too difficult to create something similar.

------------------
Step one ... Parent callbacks - this is my little way of avoiding memory leaks without risking copymemory API:

Add a Class, call it ParentSink
------------------
Option Explicit

Public Event GetParent(cc As ControlCollection)
Public Function GetParent() As ControlCollection

    'this is a nicer way to avoid circular references
    'than the traditional copymemory
    'just use an event to ask the parent
    'who it is- event sinks don't increase the
    'object's reference count and allow it to terminate properly
   
    Dim cc As ControlCollection
    RaiseEvent GetParent(cc)
    Set GetParent = cc
   
End Function

--------------
step 2 - the control holder class

add a class, call it ControlHolder
--------------
Option Explicit

Private WithEvents mcx As VBControlExtender
Private mps As ParentSink
Public Event ControlEvent(cx As VBControlExtender, info As EventInfo)
Public Property Set ControlExtender(ByVal cx As VBControlExtender)

    'set the control to monitor
    Set mcx = cx
   
End Property
Public Property Set ParentSink(ByVal ps As ParentSink)

    'set the parent sink for circular referencing
    Set mps = ps
   
End Property

Private Sub Class_Terminate()

    'tidy up
    Set mcx = Nothing
    Set mps = Nothing
   
End Sub

Private Sub mcx_ObjectEvent(info As EventInfo)

    'raise the event through to the parent
    Dim cc As ControlCollection
    Set cc = mps.GetParent
    If Not cc Is Nothing Then
   
        'raise the event to the parent
        cc.RaiseControlEvent mcx, info
       
    End If
   
   
   
End Sub
------------
step 3 - the collection - note i've not implemented a real collection here - no _newenum etc, but you could do that if you want.
------------

Option Explicit
Public Event ControlEvent(cx As VBControlExtender, info As EventInfo)
Private mcolControls As Collection
Private WithEvents mps As ParentSink

Public Sub RaiseControlEvent(cx As VBControlExtender, info As EventInfo)

    'raise the event through
    RaiseEvent ControlEvent(cx, info)
   
End Sub
Public Sub Add(ByVal cx As VBControlExtender)

    'add control to be monitored to the collection
    Dim cs As ControlHolder
   
    'create the new control holder
    Set cs = New ControlHolder
    'set the control extender
    Set cs.ControlExtender = cx
    'set the parent sink for circular references
    Set cs.ParentSink = mps
   
    'and add it to the collection
    mcolControls.Add cs
   
End Sub

Private Sub Class_Initialize()

    'initialise the control collection and the parent sink
    Set mcolControls = New Collection
    Set mps = New ParentSink
   

End Sub

Private Sub Class_Terminate()

    'tidy up
    Set mps = Nothing
    Set mcolControls = Nothing
   
End Sub

Private Sub mps_GetParent(cc As ControlCollection)

    'let the parent sink know who's the parent
    Set cc = Me
   
End Sub

---------------------
OK the test harness

add a user control, leave it usercontrol1, make the background red so we can see it
----------------------

Option Explicit
Public Event Test(ByVal s As String)
Private Sub UserControl_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)

    RaiseEvent Test(CStr(Rnd))
   
End Sub
---------------------
and the test harness form

add a form. Note this presumes the project is called project1, you should naturally change this. Also if you're releasing onto a workstation which you have no control over, you should use the progId for the control.
-----------------------

Option Explicit
Private WithEvents mcc As ControlCollection

Private Sub Form_Load()

        'test the control collection
       
        Dim cx As VBControlExtender
       
        'create the control collection
        Set mcc = New ControlCollection
       
        'create some controls
        Set cx = Form1.Controls.Add("Project1.UserControl1", "c1")
        mcc.Add cx
        With cx
       
            .Top = 100
            .Left = 200
            .Height = 300
            .Width = 800
            .Visible = True
           
        End With
       
        'create some controls
        Set cx = Form1.Controls.Add("Project1.UserControl1", "c2")
        mcc.Add cx
        With cx
       
            .Top = 500
            .Left = 200
            .Height = 300
            .Width = 800
            .Visible = True
           
        End With
       
       
       
End Sub

Private Sub mcc_ControlEvent(cx As VBControlExtender, info As EventInfo)

    Dim ep As EventParameter
    Debug.Print cx.Name & " Raises " & info.Name
    For Each ep In info.EventParameters
       
        'dirty catch, because ep.value may be a variant object or array
        'but you should be handling specific event names anyway
        On Error Resume Next
        Debug.Print ep.Name & " = " & ep.Value
       
    Next
   
   
End Sub


---------------------
hey ho. that's my karma boosted.


0
 
LVL 1

Author Comment

by:Binder
ID: 2598475
What can I say?

Thank you!!! :)

May the Force be with you... No! wrong
speech!

Let's try again:
May your karma lead you to happiness.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now