adding controls to a container programmatically - vb.net

I have made a user control that contains a panel and i want to add another control that i made to it. All of this i want it to be realised programmatically.
Actualy i wanted to create a Calandar, sizable columns, and cells.
I Want to add my cells to my columns. then add my columns to my Calendar object.
Here is the code i created for the momment..
Creating the columns:
Private Sub CreateColumns()
For i = 0 To Calendar.GetUpperBound(0)
ASFColumns(i) = New ASFcolumn
With ASFColumns(i)
.Width = 252
.Visible = True
.Left = 250 * i + i + 2
.Top = 35
End With
Me.Controls.Add(ASFColumns(i))
'AddHandler Calendar(i, j).Click, AddressOf ClickOnCells
Next
End Sub
Adding my cells to it
For i = 0 To Calendar.GetUpperBound(0)
For j = 0 To Calendar.GetUpperBound(1)
Calendar(i, j) = New ASFmultiTaskCell
With Calendar(i, j)
.Width = 250
.Visible = True
.Left = 250 * j + j + 2
.Top = 33 * i + i + 70
.BringToFront()
End With
'Me.Controls.Add(Calendar(i, j))
ASFColumns(i).Controls.Add(Calendar(i, j))
AddHandler Calendar(i, j).Click, AddressOf ClickOnCells
Next
Next
Thank you

I'm not quite sure what you are trying to do, so I assumed some things. I created Calendar as a 2d array of ASFmultiTaskCell, which is a user control. The follow code sucessfully add the user controls to either a Form or a Panel/Group Box. The event works too.
Dim Calendar(2, 3) As ASFmultiTaskCell
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For i = 0 To Calendar.GetUpperBound(0)
For j = 0 To Calendar.GetUpperBound(1)
Calendar(i, j) = New ASFmultiTaskCell
With Calendar(i, j)
.Width = 250
.Visible = True
.Left = 250 * j + j + 2
.Top = 33 * i + i + 70
.BringToFront()
End With
Me.Controls.Add(Calendar(i, j))
GroupBox1.Controls.Add(Calendar(i, j))
AddHandler Calendar(i, j).Click, AddressOf ClickOnCells
Next
Next
End Sub
Private Sub ClickOnCells()
End Sub

Related

How to capture event of multiple Dynamic control in VBA

From a previous post I learned a way to populate a userform with a grid of textboxes:
Dim Grid(1 To 10, 1 To 5) As MSForms.TextBox
Private Sub UserForm_Initialize()
Dim x As Long
Dim y As Long
For x = 1 To 10
For y = 1 To 5
Set Grid(x, y) = Me.Controls.Add("Forms.Textbox.1")
With Grid(x, y)
.Name = "TextBox_" & x & "_" & y
.Width = 50
.Height = 20
.Left = y * .Width
.Top = x * .Height
.SpecialEffect = fmSpecialEffectFlat
.BorderStyle = fmBorderStyleSingle
End With
Next y
Next x
End Sub
Now, I need to run certain code when I change the contents of any textbox in columns 5 and 6. But since the textbox won't exist until after Initialize is run, their Change events don't exist either.
So I need to either:
Write the change events in advance, since I know the names of the textboxes in advance.
Use an event that will trigger whenever I click any textbox, and be able to identify the textbox in question.
If the only way to do this is by using a class module, please explain it carefully, since I've never actually used one.
EDIT: The answers from #TinMan and #Storax work a little too well. The code reacts to every keystroke in the textbox, but I really need to wait until the user is finished typing. There's no "Exit" event for the textbox when it's in the class module. Any thoughts?
You'll need to create a class to listen for the changes.
Class: TextBoxListener
Public WithEvents TextBox As MSForms.TextBox
Public UserForm As Object
Private Sub TextBox_Change()
UserForm.TextBoxGridChange TextBox
End Sub
Userform
With a few modifications you can use the Grid() to hold the TextBoxListeners references.
Option Explicit
Private Grid(1 To 10, 1 To 5) As New TextBoxListener
Public Sub TextBoxGridChange(TextBox As MSForms.TextBox)
Debug.Print TextBox.Value
End Sub
Private Sub UserForm_Initialize()
Dim x As Long
Dim y As Long
For x = 1 To 10
For y = 1 To 5
With Grid(x, y)
Set .TextBox = Me.Controls.Add("Forms.Textbox.1")
Set .UserForm = Me
With .TextBox
.Name = "TextBox_" & x & "_" & y
.Width = 50
.Height = 20
.Left = y * .Width
.Top = x * .Height
.SpecialEffect = fmSpecialEffectFlat
.BorderStyle = fmBorderStyleSingle
End With
End With
Next y
Next x
End Sub
Just a simple example how the class could look like for the textboxes. I named the class clsTextBoxes
Option Explicit
Public WithEvents tb As MSForms.TextBox
' just to keep track of the box in the grid
Public x As Long
Public y As Long
' Just a simple example for the change event.
' you could use x and y to tell the different textboxes apart
Private Sub tb_Change()
Debug.Print tb.Text, x, y
End Sub
You have to adjust your code in the userform like that
Option Explicit
Dim Grid(1 To 10, 1 To 5) As MSForms.TextBox
' Collection to save all the textboxes in the grid
Dim colTxt As New Collection
Private Sub UserForm_Initialize()
Dim x As Long
Dim y As Long
Dim cTxt As clsTextBoxes
For x = 1 To 10
For y = 1 To 5
Set Grid(x, y) = Me.Controls.Add("Forms.Textbox.1")
' create an new clsTextBoxes
Set cTxt = New clsTextBoxes
' save a pointer to the just created textbox
Set cTxt.tb = Grid(x, y)
' store the postion
cTxt.x = x
cTxt.y = y
' add it to the collection
colTxt.Add cTxt
With Grid(x, y)
.Name = "TextBox_" & x & "_" & y
.Width = 50
.Height = 20
.Left = y * .Width
.Top = x * .Height
.SpecialEffect = fmSpecialEffectFlat
.BorderStyle = fmBorderStyleSingle
End With
Next y
Next x
End Sub
Look at the comments for a short explanation

VB.Net: Space between dynamically added controls on form increases if you pause

Purpose:
Create textboxes and labels dynamically and place them on the form. I've enabled the AutoScroll setting on the form so as to be able to see all the controls.
Problem:
Clicking the 'add' button without more than a seconds pause creates no problem. However, at some (random) point the space between the controls become arbitrarily large. It seems to have something to do with the amount of time I wait to click the button for some reason.
More Details:
There is no timer on the form, so I don't see how the factor 'time' could have any effect on the spacing
The only variable affecting the position of the controls is the number of controls added (which I've checked during run-time - it checks out). The rest are constants.
I've tried to do exactly the same on a panel. The same problem occurrs.
It is never the same unwanted distance that is added, but it seems to be increasing the longer you wait.
My form:
Public Class Form1
'Public
Public MyTextBox, boxes(0), minboxes(0), maxboxes(0), cusboxes(0) As TextBox
Public lngTextboxCount, lngCusboxCount As Long
Public MyLabel As Label
'Local
'Settings
Public lngAntalTests As Long = 10000
Public Const lngTextboxHeight As Long = 20
Public Const lngTextboxLength As Long = 100
Public Const lngTextboxCusLength = 300
Public Const lngTextboxLeft As Long = 20
Public Const lngTextboxSpace As Long = 40
Public Const lngTextboxVerticalSpace As Long = 30
Public Const lngLabelIndent As Long = 3
'Enums
Public Enum BoxType
IntMin
IntMax
Label
Custom
End Enum
Public Enum VariableType
Numeric
Custom
End Enum
'BUTTONS
Private Sub btnAddSingleNumeric_Click(sender As Object, e As EventArgs) Handles btnAddSingleNumeric.Click
Call mdlAddControl.AddSingleControl(VariableType.Numeric)
End Sub
Private Sub btnAddSingleCustom_Click(sender As Object, e As EventArgs) Handles btnAddSingleCustom.Click
Call mdlAddControl.AddSingleControl(VariableType.Custom)
End Sub
'Load Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Call InitialScript()
txtAntal.Text = CStr(lngAntalTests)
End Sub
Private Sub InitialScript()
lngTextboxCount = 0
lngCusboxCount = 0
End Sub
End Class
My module:
Module mdlAddControl
Public Sub AddSingleControl(ByVal vartype As Form1.VariableType)
Form1.lngTextboxCount += 1
Select Case vartype
Case Form1.VariableType.Numeric
Call AddTextbox(Form1.BoxType.Label, Form1.VariableType.Numeric)
Call AddTextbox(Form1.BoxType.IntMin, Form1.VariableType.Numeric)
Call AddTextbox(Form1.BoxType.IntMax, Form1.VariableType.Numeric)
Case Form1.VariableType.Custom
Call AddTextbox(Form1.BoxType.Custom, Form1.VariableType.Custom)
End Select
End Sub
'TOOLS
Public Sub AddTextbox(ByVal boxtype As Form1.BoxType, ByVal vartype As Form1.VariableType)
Form1.MyTextBox = New TextBox
With Form1.MyTextBox
.Height = Form1.lngTextboxHeight
.Width = Form1.lngTextboxLength
.Left = Form1.lngTextboxLeft
.Top = (Form1.lngTextboxHeight + Form1.lngTextboxSpace) * Form1.lngTextboxCount
Select Case vartype
Case vartype.Custom
Form1.lngCusboxCount += 1
.Width = Form1.lngTextboxCusLength
ReDim Preserve Form1.cusboxes(Form1.lngCusboxCount - 1)
Form1.cusboxes(Form1.lngCusboxCount - 1) = Form1.MyTextBox
Case vartype.Numeric
.Width = Form1.lngTextboxLength
Select Case boxtype
Case Form1.BoxType.Label
.Left = Form1.lngTextboxLeft
ReDim Preserve Form1.boxes(Form1.lngTextboxCount - 1)
Form1.boxes(Form1.lngTextboxCount - 1) = Form1.MyTextBox
Case Form1.BoxType.IntMin
.Left = .Width + Form1.lngTextboxVerticalSpace + Form1.lngTextboxLeft
ReDim Preserve Form1.minboxes(Form1.lngTextboxCount - 1)
Form1.minboxes(Form1.lngTextboxCount - 1) = Form1.MyTextBox
Case Form1.BoxType.IntMax
.Left = .Width * 2 + Form1.lngTextboxVerticalSpace * 2 + Form1.lngTextboxLeft
ReDim Preserve Form1.maxboxes(Form1.lngTextboxCount - 1)
Form1.maxboxes(Form1.lngTextboxCount - 1) = Form1.MyTextBox
End Select
End Select
Call PlaceLabel(Form1.lngTextboxCount, boxtype, vartype)
End With
Form1.Controls.Add(Form1.MyTextBox)
End Sub
Public Sub PlaceLabel(ByVal lngTextboxNumber As Long, ByVal boxtype As Form1.BoxType, ByVal vartype As Form1.VariableType)
Form1.MyLabel = New Label
With Form1.MyLabel
.Top = (Form1.lngTextboxHeight + Form1.lngTextboxSpace) * lngTextboxNumber - 24
Select Case boxtype
Case Form1.BoxType.Label
.Text = "Variable Label" & lngTextboxNumber - Form1.lngCusboxCount
.Left = Form1.lngTextboxLeft - Form1.lngLabelIndent
Case Form1.BoxType.IntMin
.Text = "Minimum Interval"
.Left = Form1.lngTextboxLength + Form1.lngTextboxVerticalSpace + Form1.lngTextboxLeft - Form1.lngLabelIndent
Case Form1.BoxType.IntMax
.Text = "Maximum Interval"
.Left = Form1.lngTextboxLength * 2 + Form1.lngTextboxVerticalSpace * 2 + Form1.lngTextboxLeft - Form1.lngLabelIndent
Case Form1.BoxType.Custom
.Text = "Custom Code " & Form1.lngCusboxCount
.Left = Form1.lngTextboxLeft - Form1.lngLabelIndent
End Select
End With
Form1.Controls.Add(Form1.MyLabel)
End Sub
End Module
Thanks in advance for any help!

add multiple dynamic controls to userform and assign different event handlers to them

I am trying to add multiple spin button with each of them linked to different sets of cells that have some values assigned to them. i have tried adding the controls and use a class module to add the event handler procedure to them but to no avail. any help would be appreciated.
Dim spinArray() As New Class1
Private Sub UserForm_Initialize()
Dim i As Long
Dim quantspin As MSForms.SpinButton
subassy_break.Height = pnum1 * 70
subassy_break.Width = 500
With Label_Var
.Top = 15
.Left = subassy_break.Width - (Label_Var.Width + 15)
.Caption = msg
.AutoSize = True
.Font.Bold = True
End With
With UserForm
For i = 1 To pnum1
Set quantspin = Me.Controls.Add("Forms.spinbutton.1", "Quantity_Count_" & i)
With quantspin
.Min = 0
.SmallChange = 1
.Max = 1
.Left = 200
.Top = subassy_break.height- pnum1*20
End With
Next i
End With
End Sub
also the new class module that i have added is
Public WithEvents spinevents As MSForms.SpinButton
Private Sub spinevents_change()
For i = 1 To pnum1
Cells(userow + i, usecol).Value = spinevents.Value
Next i
End Sub
This should help you figure it out:
clsSpin
Public WithEvents spinevents As MSForms.SpinButton
Public TargetCell As Range '<<the cell to operate on
Private Sub spinevents_change()
TargetCell.Value = spinevents.Value
End Sub
UserForm (simplified to show the relevant parts)
Dim spinners As Collection '<<< holds your clsSpin objects
Private Sub UserForm_Initialize()
Dim i As Long, s As clsSpin, quantspin
Set spinners = New Collection
For i = 1 To 5
Set quantspin = Me.Controls.Add("Forms.spinbutton.1", "Quantity_Count_" & i)
With quantspin
.Min = 0
.SmallChange = 1
.Max = 100
.Left = 20 * i
.Top = 50
End With
'create a new instance of the class, set some properties
' and add it to the collection
Set s = New clsSpin
Set s.spinevents = quantspin
Set s.TargetCell = ThisWorkbook.Sheets(1).Cells(i, 1)
spinners.Add s
Next i
End Sub

I couldn't change color of diagonal line in 16*16 label matrix. What's my issue here?

16*16 matrix is coming to my screen when I start the program. But when I click diagonal button, diagonal line isn't red. That does not change.
my code :
Public Class Form1
Dim etk As New Label 'i define the matrix as etk
Public Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For i = 0 To 15
For j = 0 To 15
Dim etk As New Label
Me.Panel.Controls.Add(etk)
etk.Name = i
etk.Tag = j
etk.Size = New Size(26, 26)
etk.BackColor = Color.Black
etk.Location = New Point(30 * i + 10, 30 * j + 10)
Next
Next
End Sub
Private Sub diagonal_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Timer1.Enabled = True
For i = 0 To 15
For j = 0 To 15
etk.Name = i
etk.Tag = j
If i = j Then
etk.BackColor = Color.Red
End If
Next
Next
End Sub
End Class
thanks for your interests..
First, the names of your dynamically loaded labels are not unique. You need to concatenate the x and the y to make it unique:
For i = 0 To 15
For j = 0 To 15
Dim etk As New Label
Me.Panel.Controls.Add(etk)
etk.Name = i & "," & j
etk.Tag = j
etk.Size = New Size(26, 26)
etk.BackColor = Color.Black
etk.Location = New Point(30 * i + 10, 30 * j + 10)
Next
Next
Then, when you are looping through in the click event, you need to find the existing label by name. Simply setting the name property on an existing label doesn't do anything to find a control. All that does is alter the one that's already there. To find a control by name, you can look it up using the name as the key value of the Controls property:
For i = 0 To 15
For j = 0 To 15
If i = j Then
Dim etk As Control = Me.Panel.Controls(i & "," & j)
etk.BackColor = Color.Red
End If
Next
Next
Or, more simply:
For i = 0 To 15
Dim etk As Control = Me.Panel.Controls(i & "," & i)
etk.BackColor = Color.Red
Next

How to pass control values between userform events?

I'm struggling with a userform (called Label_Select) that I created.
I'm initializing the userform with some text boxes and check boxes and assigning some values in them.
Then I have a OK button on the userform that was created at design mode (I can create this button at runtime if that helps).
I need to use the text boxes and check boxes values in the code of the OK_Click, refer below.
Currently I get a "Sub or Function not defined" for the OK_Click sub.
How can I pass the text boxes and check boxes values between the userform initialize code and other click events of the userform?
Thank you for your responses
Private Sub UserForm_Initialize()
Dim LotBox(500) As MSForms.TextBox
Dim SensorCheckBox(500) As MSForms.CheckBox
For i = 1 To 4
For j = 1 To 4
k = i + (4 * j)
Set LotBox(k - 4) = Label_Select.Controls.Add("Forms.TextBox.1")
Set SensorCheckBox(k - 4) = Label_Select.Controls.Add("Forms.CheckBox.1")
With LotBox(k - 4)
.Top = 250 + i * 25
.Left = (j * 80) - 50
.Width = 40
.Height = 30
.Font.Size = 14
.Font.Name = "Calibri"
.SpecialEffect = fmSpecialEffectSunken
.Value = k
.AutoSize = True
End With
With SensorCheckBox(k - 4)
.Top = 246 + i * 25
.Left = (j * 80) - 8
.Height = 30
End With
If LotBox(k - 4).Value = " " Then
Label_Select.Controls.Remove LotBox(k - 4).Name
Label_Select.Controls.Remove SensorCheckBox(k - 4).Name
End If
Next j
Next i
End Sub
Private Sub OK_Click()
Worksheets("Sheet1").Cells(1,1)=LotBox(1).Value
Worksheets("Sheet1").Cells(2,1)=SensorCheckBox(1).Value
End Sub
Try making LotBox and SensorCheckBox public variables
You've declared LotBox and SensorCheckBox within UserForm_Initialize, so as soon as that sub ends they will both go out of scope.
Move them up to the top of the module as Global variables.