Adding labels and other controls to a groupbox dynamically in vb.net not working? - vb.net

So I've been having problems adding labels from a record structure into a groupbox that stack below each other vertically. I could use a Flow Layout Panel but I have multiple labels I need to add from data in a record structure which I want to be able to scroll later with a vertical scrollbar as the autoscroll will only work with one panel only, and not all of them.
For some reason the program puts only one label in, and the others don't seem to be visible even though they have been created (I used a messagebox to check). Could someone please help me to put them in, as I am fairly new to programming and need help.
For context, the program loads 'materials' from an xml file and stores it in a record structure, then this bit of the program creates labels and radio buttons dynamically and puts it in a groupbox, so that it can be arranged manually on a pretty grid that will all become scrollable by using a scrollbar later.. Because the data I am working with is all related, and can have strings of multiple sizes (names and suppliers of materials for example) I didn't want to attempt to add whitespace to make the grid work but with a single label (not that the others would show beneath the first for some reason)
CODE:
'sets up Labels for editing materials
prgFunctions.loadMat()
Dim counter As Integer
Dim newMatIDLabel(numMatFile) As Label
Dim newMatRdb(numMatFile) As RadioButton
Dim lastPos As Integer
'testing to see if materials load GET RID OF LATER
' For counter = 1 To numMatFile
'ListBox1.Items.Add(materials(counter).matName)
' Next
'create the labels with information
For counter = 1 To numMatFile
'ID
newMatIDLabel(counter) = New Label
newMatIDLabel(counter).Name = "lblMatIDNum" & counter
newMatIDLabel(counter).Text = materials(counter).matID
newMatIDLabel(counter).Parent = gbxMaterials
' MsgBox(newMatIDLabel(counter).Name & " " & newMatIDLabel(counter).Text)
Next
'create the checkboxes NOW RADIO BUTTONS
For counter = 1 To numMatFile
newMatRdb(counter) = New RadioButton
newMatRdb(counter).Name = "chkMatSelectNum" & counter
newMatRdb(counter).Text = ""
newMatRdb(counter).Parent = gbxMaterials
Next
'matID locations
lastPos = 10
For counter = 1 To numMatFile
'SOMEHOW MOVE IT INTO THE GROUPBOX INSTEAD, as issues arise everywhere
newMatIDLabel(counter).Location = New Point(7, lastPos + 10)
lastPos = lastPos + 10
Next

Why not just:
lastPos = 10
For counter = 1 To numMatFile
Dim label As New Label
label.Name = "chkMatSelectNum" & counter
label.Text = materials(counter).matID
label.Location = New Point(7, lastPos)
label.Visible = True
gbxMaterials.Controls.Add(label)
lastPos += label.Height
Next

Based on F0r3v3r-A-N00b's answer:
The label has a height of 23, so it seems it is hiding the others.
This works for me:
Dim lastPos As Integer = 20
For counter As Integer = 1 To numMatFile
Dim label As New Label
label.Name = "chkMatSelectNum" & counter
label.Text = materials(counter).matId
label.AutoSize = True
label.Visible = True
label.Location = New Point(7, lastPos)
gbxMaterials.Controls.Add(label)
lastPos += 17
Next

Related

Fitting runtime buttons inside a form

I have a number of buttons between 5-20 and it's variable each time the form loads based on the user settings. I am trying to fit all these buttons on my form no matter what the size of the form is. The buttons are generated during runtime. I would like the first button to be 20 points from the top bar (at any size) and the rest of the buttons simply to fit in the form. This is what I have now but I have to maximize the form to view them all and also while I'm expanding the form the space between the buttons decreases and they overlap with each other whereas they should keep a relative distance. Any ideas?
Dim iButtonWidth, iButtonHeight, iVerticalSpace As Integer
If UserButtons.Count > 0 Then
iButtonHeight = Me.Size.Height - (Me.Size.Height * 0.85)
iButtonWidth = Me.Size.Width - (Me.Size.Width * 0.5)
iVerticalSpace = iButtonHeight / 3
For Each btn In UserButtons
btn.Size = New System.Drawing.Size(iButtonWidth, iButtonHeight)
btn.Location = New Point(20, 20 + btn.TabIndex * iVerticalSpace * 3)
Next
End If
Here's a quick example using the TableLayoutPanel to play with:
Public Class Form1
Private UserButtons As New List(Of Button)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Static R As New Random
Dim NumButtons As Integer = R.Next(5, 21) ' "a number of buttons between 5-20 and it's variable each time"
UserButtons.Clear()
For i As Integer = 1 To NumButtons
Dim btn As New Button()
btn.Text = i.ToString("00")
btn.Dock = DockStyle.Fill ' Optional: See how you like it with this on vs. off
UserButtons.Add(btn)
Next
DisplayButtons()
End Sub
Private Sub DisplayButtons()
TableLayoutPanel1.SuspendLayout()
TableLayoutPanel1.Controls.Clear()
TableLayoutPanel1.ColumnStyles.Clear()
TableLayoutPanel1.ColumnCount = 5 ' Fixed Number of Columns
For i As Integer = 1 To TableLayoutPanel1.ColumnCount
TableLayoutPanel1.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 911)) ' the size doesn't matter here, as long as they are all the same
Next
' Variable Number of Rows:
Dim RowsRequired As Integer = ((UserButtons.Count - 1) \ TableLayoutPanel1.ColumnCount) + 1 ' Integer Division
TableLayoutPanel1.RowStyles.Clear()
TableLayoutPanel1.RowCount = RowsRequired
For i As Integer = 1 To TableLayoutPanel1.RowCount
TableLayoutPanel1.RowStyles.Add(New RowStyle(SizeType.Percent, 911)) ' the size doesn't matter here, as long as they are all the same
Next
TableLayoutPanel1.Controls.AddRange(UserButtons.ToArray)
TableLayoutPanel1.ResumeLayout()
End Sub
End Class
First of all what kind of container are the buttons in? You should be able to set the container's AutoScroll property to true - then when controls within it spill out of the visible bounds you will get a scroll bar.
Then also what you could do is draw each button in more of a table with a certain number next to each other before dropping down to the next line (instead of just 1 button on each line). If that is an option that works for you then you could get more buttons within the visible space.
I happen to have an example to do the same thing with picture boxes (and text boxes under each picture box). Hope this helps:
Dim point As New Point(0, 0)
'create 11 picture and text boxes-you can make this number the number your user selects.
Dim box(11) As PictureBox
Dim text(11) As TextBox
Dim i As UInt16
For i = 0 To 11 'or whatever your number is
box(i) = New PictureBox
box(i).Width = 250 'your button width
box(i).Height = 170 'your button height
box(i).BorderStyle = BorderStyle.FixedSingle
box(i).Location = point
layoutsPanel.Controls.Add(box(i)) 'my container is a panel
text(i) = New TextBox
text(i).Height = 50
text(i).Width = 250
point.Y += box(i).Height
text(i).Location = (point)
layoutsPanel.Controls.Add(text(i))
point.Y -= box(i).Height 'reset Y for next picture box
'Put 4 picture boxes in a row, then move down to next row
If i Mod 4 = 3 Then
point.X = 0
point.Y += box(i).Height + text(i).Height + 4
Else
point.X += box(i).Width + 4
End If
Next

label doesn't appear on dynamically created form vb.net

I'm staring at my code for hours now and I don't understand what's going on. I'm creating a form with a number of checkboxes and labels, based on a textbox value from another form.
This is the code:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim lb As Label
Dim cb1 As CheckBox
Dim cb As CheckBox
Dim i As Integer
Dim j As Integer
For i = 1 To CInt(Aantal.Text) - 1
indivwoningen.Width = indivwoningen.Size.Width + 21
indivwoningen.Button1.Location = New Point(indivwoningen.Button1.Location.X + 21, indivwoningen.Button1.Location.Y)
lb = New Label
indivwoningen.Controls.Add(lb)
lb.Text = i + 1
lb.Font = indivwoningen.Label23.Font
lb.Location = New Point(indivwoningen.Label23.Location.X + 21 * i, indivwoningen.Label23.Location.Y)
For j = 1 To 18
cb1 = New CheckBox
indivwoningen.Controls.Add(cb1)
cb = indivwoningen.Controls.Find("CheckBox" & j & "00", False)(0)
cb1.Location = New Point(cb.Location.X + 21 * i, cb.Location.Y)
cb1.Width = cb.Width
cb1.Text = cb.Text
If i < 10 Then
cb1.Name = "CheckBox" & j & "0" & i
Else
cb1.Name = "CheckBox" & j & i
End If
Next
Next
indivwoningen.Show()
End Sub
The created form has got two flaws:
Only the first created label is visible
The checkboxes aren't properly aligned.
I don't understand what's going on. Can someone help me?
EDIT: Here are pictures before I create extra controls and after
Set the Autosize property to True for the labels and set the Height of the checkboxes to the same height of your reference checkbox
For i = 1 To CInt(Aantal.Text) - 1
....
lb = New Label
indivwoningen.Controls.Add(lb)
lb.Text = i + 1
lb.Font = indivwoningen.Label23.Font
lb.Autosize = True
lb.Location = New Point(indivwoningen.Label23.Location.X + 21 * i, indivwoningen.Label23.Location.Y)
For j = 1 To 18
cb1 = New CheckBox
indivwoningen.Controls.Add(cb1)
cb = indivwoningen.Controls.Find("CheckBox" & j & "00", False)(0)
cb1.Location = New Point(cb.Location.X + 21 * i, cb.Location.Y)
cb1.Width = cb.Width
cb1.Height = cb.Height
cb1.Text = cb.Text
If i < 10 Then
cb1.Name = "CheckBox" & j & "0" & i
Else
cb1.Name = "CheckBox" & j & i
End If
Next
Next
Well, for the checkbox the explanation seems to be easy. The new checkbox has, by default, an Heigth of 24 pixels while the one drawn on the form as a smaller Height. So, because the check square is centered inside the Height of the Checkbox it appears to be not aligned to the reference checkbox.
For the labels the problem is of the same kind. Without setting the Autosize, the labels are created with a default size of 100x23 pixels. This means that the label with text "2" extends its size to cover the position of the labels with text "3","4","5","6", while the label with text "3" covers the label with text "7" and so on.
In any case setting AutoSize seems to be the default behavior, followed also in the Form.Designer.vb file where the controls are created following your design time instructions.
You could also try to set the Size of the dynamically created labels to the same size of the reference label and the effect is the same.

Print multiple images in vb.net

In VB.NET, I need to print multiple Images of bar codes by arranging them in tabular format. For now what I am doing is, Creating the bar codes and adding them in new picture box. These Picture boxes are added on a panel which I am creating on form at run time and print that panel (with picture boxes in 4x9 table).
But, when I need to print more that 36 bar codes, this idea doesn't work.
So, Please suggest me some improvements in my code or any other way to do this job.
I am sorry, here is the code for generating images and adding them to the panel..
''' Method for create bar code images with a loop and adding them to the panel by picture box...
Private Function GetBarcodeText(RowId As Guid)
Dim BarcodeValue As StringBuilder = New StringBuilder(96)
Dim temp As New StringBuilder
Dim data As String
Dim param = New SqlParameter()
Dim imageNo As Integer = 0
Dim colorValue As String = ""
Dim scaleValue As String = ""
'' Adding the panel on the form which is dynamically created
Me.Controls.Add(outputPanel)
'' Setting the Initial size for the panel
outputPanel.Size = New Point(794, 112)
outputPanel.Name = "outputPanel"
outputPanel.BackColor = Drawing.Color.White
param.ParameterName = "#RowId"
param.Value = RowId
param.SqlDbType = SqlDbType.UniqueIdentifier
' Get the particular row of data from database
dt = objStockProvider.GetBarcodeDetails(param)
' GET colour code
Dim color As String = dt.Rows(0)("COLOUR").ToString()
Dim countColors As Integer = 0
' Get the color code numbers
param.ParameterName = "#Dscale"
param.Value = dgvViewTickets.CurrentRow.Cells("SCALE").Value.ToString()
countColors = objStockProvider.CountColorCodes(param)
For i = 1 To countColors
For j As Integer = 1 + ((12 / countColors) * (i - 1)) To (12 / countColors) * i
If dt.Rows(0)("S" + j.ToString()) <> 0 Then
Dim totalTicketsForASize As Integer
totalTicketsForASize = dt.Rows(0)("S" + j.ToString())
For k As Integer = 1 To totalTicketsForASize
' Set Bar code value which has to create
BarcodeValue = "123456789012"
' Create Barcode Image for given value
Dim image = GetBarcodeImage(BarcodeValue, colorValue, scaleValue)
If image IsNot Nothing Then
'' Create picture box to contain generated Image.
Dim pcbImage As New PictureBox
pcbImage.Width = W
pcbImage.Height = H
pcbImage.Image = image
pcbImage.Location = New Point(X, Y)
imageNo += 1
If imageNo Mod 4 = 0 Then
X = 15
Y += H
outputPanel.Height += H
Else
X += W
Y = Y
End If
pcbImage.Visible = True
'' Adding picture box to panel
outputPanel.Controls.Add(pcbImage)
End If
Next
End If
Next
color = color.Substring(color.IndexOf(",") + 1, color.Length - color.IndexOf(",") - 1)
Next
PrintGeneratedTickets()
End Function
Now, I am printing the panel by following method:
Private Sub PrintGeneratedTickets()
bmp = New Bitmap(outputPanel.DisplayRectangle.Width, outputPanel.DisplayRectangle.Height)
Dim G As Graphics = Graphics.FromImage(bmp)
G.DrawRectangle(Pens.White, New Rectangle(0, 0, Me.outputPanel.DisplayRectangle.Width, Me.outputPanel.DisplayRectangle.Height))
Dim Hdc As IntPtr = G.GetHdc()
SendMessage(outputPanel.Handle, WM_PRINT, Hdc, DrawingOptions.PRF_OWNED Or DrawingOptions.PRF_CHILDREN Or DrawingOptions.PRF_CLIENT Or DrawingOptions.PRF_NONCLIENT)
G.ReleaseHdc(Hdc)
pndocument.DocumentName = bmp.ToString()
Dim previewmode As New PrintPreviewDialog
previewmode.Document = pndocument
previewmode.WindowState = FormWindowState.Maximized
previewmode.PrintPreviewControl.Zoom = 1
pndocument.DefaultPageSettings.Margins.Top = 10
pndocument.DefaultPageSettings.Margins.Bottom = 30
pndocument.DefaultPageSettings.Margins.Left = 16
pndocument.DefaultPageSettings.Margins.Right = 16
pndocument.DefaultPageSettings.Landscape = False
' Set other properties.
previewmode.PrintPreviewControl.Columns = 4
previewmode.PrintPreviewControl.Rows = 9
previewmode.ShowDialog()
Dim file As String = DateTime.Now.ToString()
file = Path.GetFullPath("D:\Bar Codes\" + file.Replace("/", "-").Replace(":", ".") + ".bmp")
bmp.Save(file)
G.Dispose()
outputPanel.Controls.Clear()
End Sub
This code is working fine but what I need to do, is to fix the number of images (4x9) per page. But when I am trying to create more than it, that all are printing on a single page with compressed size.
Also when trying to re-run the code, It shows nothing in preview..
Some body please suggest the correction in code so that I can reprint the tickets and use paging for more than 36 images.
Well, Printing the Images on a panel was not a good idea.. I replaced the panel and created an array of images and used the print document directly and print after arranging images on it.
Thanks.

How can I create a loop that reveals a certain number of labels?

I want to be able to reveal and then populate a certain number of labels. The inefficient way would be to SELECT CASE on the number of labels required and then populate these in turn. I am looking for something like this:
For i = 1 to RequiredNumOfLabels
Label & i.visible = true
Label & i.text = DataTable.Rows(i).Item(2)
Next
Thank you.
EDIT:
For i = 1 To NumberOfItems
Dim lbl = Controls("lbl" & i)
lbl.Visible = True
lbl.Text = CStr(DataTable.Rows(i).Item(2))
Next
I think the line
Dim lbl = Controls("lbl" & i)
is the problem as after the line is executed, lbl still equals nothing.
The reasoning behind it is that I was trying to create an invoice generator in vb.net and I was hoping that this would be a simple way to do it - count the amount of items in the order, populate the labels with the names of the items, reveal that many labels.
If your label controls are really in order like that, you can try just referencing them from a list:
Dim myLabels As New List(Of Label)
myLabels.Add(Label1)
myLabels.Add(Label2)
Then just update them:
For i as Integer = 1 to myLabels.Count
myLabels(i - 1).Visible = True
myLabels(i - 1).Text = DataTable.Rows(i).Item(2).ToString
Next
You can get controls by name through the forms Controls property
For i = 1 To RequiredNumOfLabels
Dim lbl = TryCast(Controls("Label" & i), Label)
If lbl IsNot Nothing Then
lbl.Visible = True
lbl.Text = CStr(DataTable.Rows(i).Item(2))
End If
Next
Since you get an object of type Control, you have to cast it to Label.
UPDATE
It seems that you only use properties that are defined in Control anyway. Therfore you can simplify the code to
For i = 1 To RequiredNumOfLabels
Dim lbl = Controls("Label" & i)
lbl.Visible = True
lbl.Text = CStr(DataTable.Rows(i).Item(2))
Next

Dynamically adding Panel and RadioButtons in Visual Basic

Guys I'm trying to dynamically create panels which are filled with seven radio buttons each.
I get the panels but they are only filled with 1 radio button each. What am I doing wrong here? QuestionQuantity is an Integer and is the variable that determines how many panels I will be creating. The code is in the form load function located.
Thanks,
Dim Pan As Panel
Dim RButton As RadioButton
For x As Integer = 1 To QuestionsQuantity Step 1
Pan = New Panel
Pan.Name = "Panel" & Convert.ToString(x)
Pan.Left = 300
Pan.Top = 100 + 52 * (x - 1)
Pan.Height = 48
Pan.Width = 280
Pan.BackColor = Color.Coral
Controls.Add(Pan)
For y As Integer = 1 To 7 Step 1
RButton = New RadioButton
RButton.Name = "RadioButton" & Convert.ToString(x) & Convert.ToString(y)
RButton.Left = 1 + 30 * (y - 1)
RButton.Top = 10
RButton.Text = Convert.ToString(y)
RButton.CheckAlign = System.Drawing.ContentAlignment.BottomCenter
RButton.TextAlign = System.Drawing.ContentAlignment.TopCenter
RButton.UseVisualStyleBackColor = True
Controls.Add(RButton)
Pan.Controls.Add(RButton)
Next
Next
I messed with it and took out the Panel section and just used the RadioButtons in order to see if i get seven of these. I can get seven if i ofset them in the y direction (.top) but it does not work for some reason in the x (.left) direction
For y As Integer = 1 To 7 Step 1
RButton = New RadioButton
RButton.Name = "RadioButton1" & Convert.ToString(y)
RButton.Left = 20 + (y * 30)
RButton.Top = 10
RButton.Text = Convert.ToString(y)
RButton.CheckAlign = System.Drawing.ContentAlignment.BottomCenter
RButton.TextAlign = System.Drawing.ContentAlignment.TopCenter
RButton.UseVisualStyleBackColor = True
Controls.Add(RButton)
Next
Please help me!
I finally got it. The problem was declaring the size of the RadioButton. It will be too big if not declared even if i make the spacing bigger.
RButton.Size = New System.Drawing.Size(17, 30)
That solved the problem.
You should be using a UserControl that contains your seven radio buttons.
For x As Integer = 1 To QuestionsQuantity
Dim pan As New QuestionUserControl
Pan.Name = "Panel" & Convert.ToString(x)
Pan.Left = 300
Pan.Top = 100 + 52 * (x - 1)
Pan.Height = 48
Pan.Width = 280
Pan.BackColor = Color.Coral
Me.Controls.Add(Pan)
Next
If sticking with your current code, remove this (you should be only adding it to the panel):
For y As Integer = 1 To 7
'// Controls.Add(RButton)
Pan.Controls.Add(RButton)
Next
As far as seeing the control, I'm guessing you aren't going "right" enough:
Dim leftMark As Integer = 20
For y As Integer = 1 To 7
'// code
RButton.Left = leftMark
'//code
leftMark += rButton.Width + 4
Next
with a Pan.Height = 48 there's not going to be much controls inside.
You add the button both to the panel an to Controls ?
Put the radiobuttons in a gridbox. You can dynamically add rows of radiobuttons as you wish. If this will work for you, I'll send a sample code when I get home.