devxlogo

Catching Events of Dynamically Added Controls

Catching Events of Dynamically Added Controls

VB now allows us to addcontrols to a Form at run time. In thisarticle I will try to explain a way in which you can dynamically add a control arrayto a Form at run time and then catch the events generated by these addedcontrols.

Basic Concepts

Suppose we have aForm, named FrmTest to which we want to add a Label Control at run time. We must make our intention clear from thebeginning, giving the Label Control a name, and letting FrmTest know aboutit. Lets call this Label Control mLblTaskLength,because with it we intend to display on FrmTest the time a certainmanufacturing operation takes. Therefore, in the declaration area of FrmTest we add:

Private WithEvents mLblTaskLength As Label

We use the prefix”m” as a convention to help us identify a variable which scope is only withinFrmTest. Having declared this variableWithEvents, we now find it displayed in the left dropdown list of our codewindow, where we can write code to handle the various events the Label Controlscan generate. When the need to show thelabel arises, we use the following code to make it appear on our Form:

SetmLblTaskLaskLength = Me.Controls.Add(“VB.Label”,”mLblTaskLength”)

The firstparameter “VB.Label” or ProgID identifies the Label Control, the secondparameter is the controls name.

This code willcreate the Label control for us, although it shall not be immediately visibleand still VB is not aware of the new Label property values. Therefore we continue with our code, settingthe Property values and telling VB where to display this new control:

WithmLblTaskLaskLength

.Appearance = 1

.AutoSize = False

.BackStyle = 1 ‘Opaque

.BorderStyle = 0 ‘None

…etc 

End With

We can use the”move” method to place the control on the Form.

       mLblTaskLaskLength.move  500,500,100,800

Were theparameters indicate: Top, Left, Height and Width properties of the Label. Finally we make the Label visible.

       mLblTaskLaskLength.Visible= True

After this codeis executed the Label will display nicely on our Form. This covers the basics.

Adding an Array of Controls

Now let usventure forward. We want to create anarray of Labels, because we have many manufacturing tasks, the duration ofwhich, we want to display with Labels. We soon discover that VB does not allow us to display an array ofcontrols in the manner we have just learnt. We need a workaround for this. One way to achieve this goal is to encapsulate a Label Control inside aClass Module. We then add to ourProject a new Class Module and name it CLabel. We set its instancing property to Private. In Clabel declaration area we add the following:

Option Explicit

PrivateWithEvents mLbl As Label

PrivatemCallingForm As Form

Let us take acloser look at what we have declared. With mLabel we are creating a variable to hold the Label Controlencapsulated in our Class Module. With mCallingForm we have a variable to hold a reference to the Form on which we wantthe Label displayed. Please note wehave declared mLbl WithEvents. As inthe previous case, you shall find in the left Dropdown list of your codeWindow, a place made available to handle the events mLbl generates. This is of course a minimum set ofdeclarations. When on your own, you candeclare other variables, one for Caption, another for BackStyle…

Now we need toadd the following property to our Class Module:

Public PropertyLet CallingForm(frm As Form)

SetmCallingForm = frm

End Property

We then need amethod to call and have it draw the Label on the Form for us. Lets call this method gDrawOnForm. Here is how to do it:

Public Sub gDrawOnForm(ByVal Name$,ByValTop%,ByVal Left%,ByVal Height%, ByVal Width%)

SetmLbl = mCallingForm.Controls.Add(“VB.Label”, fs_Name)

SetmCallingForm = Nothing ‘Important Line of Code

‘ we set the properties ‘

mLbl.Autosize= false

mLbl.BackStyle=1

…etc

‘then the position ‘

mLbl.Top= Top

mLbl.Left= Left

mLbl.Height=Height

mLbl.Width= Width

mLbl.Visible= True

End Sub

You can add otherparameters to the List, as you see fit.

Now lets go backto our Form, on which we want the array of Labels displayed. On the declaration area we declare the variableto hold the array and add a Collection to hold the array of Labels.

       PrivatemLblTaskLength As Clabel

PrivatemColTaskLength As Collection

When we are readyto create the array we do it in this manner:

Dim li%

Set mColTaskLength = New Collection

For li = 0 To NumberOf Labels

SetmLblTaskLength = New Clabel

‘Add Item to Collection ‘

mColTaskLength.AddmLblTaskLength

mLblTaskLength.gDrawOnForm “LblT” & li, other parameters

SetmLblTaskLength = Nothing

Next

Notice how we havenamed our Labels. This isimportant. They are named LblT0, LblT1, andLblT2… Once this code executes you shall find theLabels displayed on the Form. By nowyou might be thinking, “Wait………. you started talking about catching events. Where are the events now? You didn’t even declare mLblTaskLenghtWithEvents. You see, I still have somebunnies in my hat, I am not through yet.

Lets get the bigblack bunny out of the hat. There is aClass Module missing here! Lets callthis missing Class Module ” CGral “. As the name suggests this module is useful for general purposes. One of the purposes may well be to raisesome events. Sort of an eventPublisher. We create this Class Module,set it’s instancing to MultiUse., and add a public Event to it:

evLabelClicked(ByValIndex As Integer)

and also a publicmethod called gLabelClicked which raises the event evLabelClicked.

       Public SubgLabelCliked(ByVal Indx As Integer)

RaiseEventevLabelClicked(Indx)

EndSub

Remember we had aplace to handle the Label events in our CLabel Class Module. That is the placewe use to call the CGral method gLableClicked. Of course we need the Index identifying the Label being clicked on, andwe derive this Index from the Label Name Property. Here is one way to write this code:

Private Sub Lbl_Click()

Dim li_Len%

Dim li_Index%

li_Len = Len(mLbl.Name)

If li_Len = 6 Then li_Index =CInt(Right(mLbl.Name, 1))

If li_Len = 7 Then li_Index =CInt(Right(mLbl.Name, 2))

If li_Len = 8 Then li_Index =CInt(Right(mLbl.Name, 3))

‘raises the event ‘

gGRAL.gLabelCliked (li_Index)

End Sub

So now we haveClass Module CGral trumpeting the event within our application. But is our Form aware of it? Not yet. In the declaration area of our Form we must add

       PrivateWithEvents mLabelSelected As CGral

And with thisdeclaration VB will make a space available to us where we receive and handlethe Lable_Click event. This is

Private SubmLabelSelected_LabelClicked(ByVal Index As Integer)

Codeto handle event here…

End Sub

 Now thelast piece of the puzzle is in place.

Cleaning Up

Onceyou labels have appeared on your Form and you are through with clicking on themto your hearts content, its time to remove the Labels and clean up. Remember, the Labels “belong” to the Form onwhich they are drawn, that is, they are part of the Form.Controlscollection. On the other hand, the artists that have drawn the Labels on yourForm are the CLabel classes and they are independent of your Form. This code onyour Form does it:

Private Sub ClearLabels()

Dim ctl AsControl

Dim li%

‘ This removesthe Labels

For Each ctl InMe.Controls

‘ use this Filter to remove only the Labels added dymanically

‘ you may have other Labels on tour Form you dont want removed

If Left(ctl.Name, 4) = “LblT” Then Me.Controls.Removectl.Name

Next

‘ Then youdismiss the artists

Forli = mColTaskLength.Count To 1 Step -1

mColTaskLength.Remove li

Next

End Sub

You may not have yetnoticed but we have barely escaped being caught in a “circular reference”problem. The trap was nicely set for us from the beginning, because your Formhas a reference to the CLabel classes which in turn have a reference to theForm. How did we get away with this one? If you remember I highlighted one line of code as a very important line.That line read:

       SetmCallingForm = Nothing

and occurred immediatelyafter the line we used to draw our Labels on the Form. Once the Label is drawnwe do not need the reference to the Form any more, so we destroy it at once,and avoid the “circular reference”.

“A stitch in time….”applies here as well.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist