What i am looking for is how to add another control(say a textbox directly under another textbox) that is added through code rather than the designer. I can get it to work using the .height property of the control then adding another 10-20 to it
dim space as integer
space += textbox1.height + 10
however, is there a way to do this on the location rather than the height? In this case, if I want to add a textbox at the very end of the frame or groupbox without having to add additional in between. Since the location takes two parameters(x,y), is it possible to place controls based on another controls location?
Does this help? (not clear what you are after, but yes, you can set the Location or Size all at once):
Dim thisTB as new TextBox
thisTB.Location = new Point(xSpot, ySpot)
thisTB.Size = otherTB.Size
Me.Controls.Add(thisTB)
Related
What I am doing
I am developing a VisualBasic application where the GUI is separated from the data manipulation (frontend and backend). This particular piece of code keeps track of the Serial Numbers already measured and displays them in the Form as a DGV with the serial number and an image or not.
My code
In a class that the GUI Form instantiates, my data is stored in a DataTable with a BindingSource, with the second column displaying an Image when I tell it to in the program (Nothing in the beginning):
Public SerialNumbersBindingSource As New BindingSource
Public SerialNumbersDataTable As New DataTable
(...)
SerialNumbersBindingSource.DataSource = SerialNumbersDataTable
SerialNumbersDataTable.Columns.Add("Serial", Type.GetType("System.String"))
SerialNumbersDataTable.Columns.Add("Pass", MyImage.GetType)
In my GUI Form code, a DataGridView has its DataSource set to the former DataTable:
DataGridViewSerialNumber.DataSource = MyObject.SerialNumbersDataTable
By just updating the DataTable in my class, the DataGridView updates automatically to reflect the current state of it. I do it like:
SerialNumbersDataTable.Add(CurrentSerial, MyImage)
The results I get
The code works, so I can modify and access the DataTable and the DataGridView autoupdates. But the images are not stretching, so I can only see a small part of them.
What I need
I need the second column named "Pass" in DataGridView to stretch the images.
What have I tried
If I access the column, it is treated like a DGVColumn and not a DGVImageColumn, so the Layout operation fails.
DataGridViewSerialNumber.Columns("Pass").DataGridViewImageCellLayout.Stretch
Microsoft's Docs page tells me to do this, which treats the columns like DGVImageColumn as I need "Pass" to. It fails because the first column is a Text one, not image.
For Each column As DataGridViewImageColumn In DataGridViewSerialNumber.Columns("Pass")
column.ImageLayout = DataGridViewImageCellLayout.Stretch
Next
Also I have tried creating a local DGVImageColumn, modify it and write it onto the original column, but it is read-only.
Dim imageColumn As DataGridViewImageColumn
imageColumn = DataGridViewSerialNumber.Columns("Pass")
imageColumn.ImageLayout = DataGridViewImageCellLayout.Stretch
DataGridViewSerialNumber.Columns("Pass") = imageColumn
I have also tried to do it from the designer. If I click the DGV, arrow to the right and 'Edit Column', I can create the two columns and setup Pass as ImageColumn with Stretched Layout. But when I set up DGVSerialNumbers.Datasource to my DataTable, it adds the DataTable's columns to the DGV's.
Failed DGV with columns added in designer
It's time for you to learn how to cast. If you want to access one column then don't use a loop. Simply access the column you want and then cast it as the type you want to use it as. You also need to actually assign the appropriate value to the appropriate property.
DirectCast(DataGridViewSerialNumber.Columns("Pass"), DataGridViewImageColumn).ImageLayout = DataGridViewImageCellLayout.Stretch
If you want to break that up for clarity:
Dim imageColumn = DirectCast(DataGridViewSerialNumber.Columns("Pass"), DataGridViewImageColumn)
imageColumn.ImageLayout = DataGridViewImageCellLayout.Stretch
Also, be aware that Stretch will not retain the original aspect ratio, so you might want to use Zoom instead.
I'm programming in Visual Basic.
I have one form.
Form 1 contains:
nameTextBox
addNameButton
namesListBox
generateButton
week1TextBox
week2TextBox
week3TextBox
week4TextBox
The user needs to go to Form 1 and type a name in the text box, then add the name to the List Box. The user will add 4 names to the List Box. So, the ListBox will contain the names: Adam, Brenda and Carol.
When the generateButton is clicked, the 3 names have to be written to the text boxes in that order. So week1TextBox should contain "Adam", week2TextBox should contain "Brenda", etc... but once the last name (in this case "Carol") is written into the text box, the loop should start over. Ultimately, there may be up to 50 week text boxes (so week50TextBox). So the loop needs to repeat over and over.
As there is a lack of source code in your question, I'm really not sure exactly how the layout should look, I can only offer some advice/suggestions.
I would recommend creating your listbox control, input textbox, and button to add names to the listbox. In addition to these, though, also add a scrollable panel. (Not sure what the exact term for that control is in VB.net; it's been a long time since I've worked with that language.) Because it sounds like there might be a variable number of items on the panel, when the user goes to generate the list of names, I would use the following rough pseudocode:
Dim OutputTexts As New ArrayList ' This is only here if you want to work with these textboxes later
Private Sub CreateOutput() Handles btnGenerate.Click
pOutputPanel.Controls.Clear()
OutputTexts.Clear()
Dim NextX As Integer = 0 ' Pretty much unnecessary value, but included in case you want to mess with this
Dim NextY As Integer = 0
For i As Integer = 0 To Convert.ToInt32(txtWeekCount.Text)
Dim txtName As New TextBox
txtName.Text = lbNameList.Item(i Mod lbNameList.Items.Count)
txtName.Location = new Point(NextX, NextY) ' Play with this as necessary
NextY += 50 ' Play with this as necessary
OutputTexts.Add(txtName)
pOutputPanel.Controls.Add(txtName)
Next
End Sub
Again, this is very much pseudocode, so I would not encourage copying and pasting, but give it a read, make sure you understand all of it, and then try implementing something similar. There might be an easier way to do it, but I have not programmed in VB.NET in probably over 2 years (at least). Nonetheless, the most important thing in here is the following line: lbNameList.Item(i Mod lbNameList.Items.Count). By Mod-ing your indexing variable, you will be accessing items sequentially, and then repeating from the start of the ListBox items collection once i is out of range.
I would also encourage you to dynamically generate your TextBox controls as needed rather than manually adding in 50 or more TextBox controls.
I have a program that grabs product data and adds a custom control for each record to a FlowLayoutPanel.
I would like to add a control to the beginning of the FlowLayoutPanel, as opposed to the end, to appear as the first item.
Does anyone have an idea how this is done? I would like to avoid having to repopulate it every time I add an item to the beginning.
You can use the SetChildIndex method of the FlowLayoutPanel's Control collection:
Dim newButton As New Button With {.Text = flp.Controls.Count.ToString}
flp.SuspendLayout()
flp.Controls.Add(newButton)
flp.Controls.SetChildIndex(newButton, 0)
flp.ResumeLayout()
We have developed windows application which is including many forms and controls with default small display size and it is working fine.
but in client systems,displays are not consistent. so when the same code runs with medium/large screen size, the controls are overlapping
It would be great help if anyone gives solution for dynamic re-size/fit the form & controls for any display (small-100%, medium-125%, large-150%)
and also Is there any way to find the Display size (small-100%, medium-125%, large-150%) in vb.net
You can change display size in control-Panel.
You can use the Anchor property to automatically adjust the control size according to its form size. You can anchor any side of the control to that side of the form. For example, if I anchor all four sides of a picturebox to the form, the picturebox will mimic the shape of the form when the form is resized. If you anchor only the top and the bottom of the picturebox, for example, it will change height with the form, but the width and horizontal position will remain constant.
Finally found a solution by doing R&D
call the below function in the Form_Load like ScaleForm(me)
Public Sub ScaleForm(WindowsForm As System.Windows.Forms.Form)
Using g As System.Drawing.Graphics = WindowsForm.CreateGraphics
Dim sngScaleFactor As Single
Dim sngFontFactor As Single = 1
If g.DpiX > 96 Then
sngScaleFactor = g.DpiX / 96
'sngFontFactor = 96 / g.DpiY
End If
If WindowsForm.AutoScaleDimensions = WindowsForm.CurrentAutoScaleDimensions Then
'ucWindowsFormHost.ScaleControl(WindowsForm, sngFontFactor)
WindowsForm.Scale(sngScaleFactor)
End If
End Using
End Sub
I have a project that creates several buttons dynamically along with a slider (two splitters in a panel).
For the purpose of this lets call the slider "slider9001" and the label "label9001". Each set of control's last 4 digits are different.
Currently I'm looping through all of the controls and looking for a label with the last 4 digits of the slider. This seems incredibly inefficient, especially considering there will be over 100 labels and 40-50 sliders on the form.
Does anyone know of a simple and more efficient way of accessing a dynamically created label
I should mention the slider will be used to update the label
If you know the name of the control you can get a reference to it
Dim lbl as label =
ctype(me. Controls("label9001"),label)
As the labels are generated, store a reference to each one in a dictionary. Use the digits as the key. When you need a label, simply retrieve it from the dictionary. The same approach will work for the sliders as well.
dim labels as new Dictionary(of string, Label)
' add generated labels to dictionary
dim lbl = labels("9001")
Outstanding! Since I already know the name
Dim lbl as label = ctype(me. Controls("label9001"),label)
Worked perfectly. Thanks Much!!!