Using listbox to display an excel file? - vb.net

So after some changes, I have used this code:
Dim XlApp = New Microsoft.Office.Interop.Excel.Application
Dim oBook As Object = XlApp.Workbooks.Open("C:\file.xlsx")
Dim oSheet As Object = oBook.Worksheets(1)
Private Sub form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim StartedRow As Integer
Dim TotalRows As Integer
TotalRows = XlApp.ActiveWorkbook.Sheets(1).Range("a1").CurrentRegion.Rows.Count
For StartedRow = 1 To TotalRows
Me.ListBox1.Items.Add(oSheet.Cells(StartedRow, 1).text)
Me.ListBox1.Items.Add(oSheet.Cells(StartedRow, 2).text)
Next
MessageBox.Show("Succesful")
This one works but only shows two rows which is not in proper order, I need to show the whole file.
Sorry, since I'm new to Stack Overflow I find it kinda confusing for now :)

You need to declare your variables as specific types so you can use the properties and methods of that type. In general, don't let variables flap about as Object unless absolutely necessary.
I used .UsedRange to get row count. It seemed a bit simpler.
I used an interpolated string, indicated by the $, to get the range. In versions of Visual Studio prior to 2015 you will have to use
String.Format("A{0}", RowNum)
Excel is hard to get rid of. Therefore, put the Excel stuff in a separate method and add the two GC calls when the method returns.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DoExcelThing()
GC.Collect()
GC.WaitForPendingFinalizers()
'Even doing this will still leave a Zoombie Excel in Task Manager when debugging. (Hopefully not release)
MessageBox.Show("Succesful")
End Sub
Private Sub DoExcelThing()
Dim XlApp As New Microsoft.Office.Interop.Excel.Application
Dim oBook As Workbook = XlApp.Workbooks.Open("C:\file.xlsx")
Dim oSheet As Worksheet = CType(oBook.Worksheets(1), Worksheet)
Dim TotalRows = oSheet.UsedRange.Rows.Count
For RowNum = 1 To TotalRows
ListBox1.Items.Add(oSheet.Range($"A{RowNum}").Value)
ListBox1.Items.Add(oSheet.Range($"B{RowNum}").Value)
Next
End Sub

#Wakashio1234
This Will loop through all the cells..
TotalRows = XlApp.ActiveWorkbook.Sheets(1).Range("a1").CurrentRegion.Rows.Count
Totalcolumns = XlApp.ActiveWorkbook.Sheets(1).Range("a1").CurrentRegion.columns.Count
For StartedRow = 1 To TotalRows
For Startedcolumn = 1 To Totalcolumns
Me.ListBox1.Items.Add(oSheet.Cells(StartedRow, Startedcolumn).text)
Next
Next
MessageBox.Show("Successful")

The following code shows how to take out the data in Excel and put it into 'List(Of String())', then bind listbox control to the List and draw aligned columns of data in listbox.
Dim XlApp = New Microsoft.Office.Interop.Excel.Application
Dim oBook As Excel.Workbook = XlApp.Workbooks.Open("your file path")
Dim oSheet As Excel.Worksheet = oBook.Worksheets(1)
Dim lst As List(Of String()) = New List(Of String())()
Private RowHeight, RowWidth As Single
Private ColWidths As Single() = Nothing
Private Const RowMargin As Single = 10
Private Const ColumnMargin As Single = 10
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ListBox1.DrawMode = DrawMode.OwnerDrawVariable
ListBox1.DataSource = GetList()
End Sub
Private Function GetList() As List(Of String())
Dim rows As Integer = oSheet.UsedRange.Rows.Count
'If you want to display only two columns, set the value of 'cols' to 2
Dim cols As Integer = oSheet.UsedRange.Columns.Count
For r As Integer = 1 To rows
Dim Value As String() = New String(cols - 1) {}
For c As Integer = 1 To cols
Value(c - 1) = oSheet.Cells(r, c).Text
Next
lst.Add(Value)
Next
oBook.Close()
XlApp.Quit()
Return lst
End Function
Private Sub ListBox1_MeasureItem(sender As Object, e As MeasureItemEventArgs) Handles ListBox1.MeasureItem
If ColWidths Is Nothing Then
GetRowColumnSizes(e.Graphics, ListBox1.Font, lst, RowHeight, ColWidths)
For i As Integer = 0 To ColWidths.Length - 1
ColWidths(i) += ColumnMargin
Next
RowHeight += RowMargin
RowWidth = ColWidths.Sum()
End If
e.ItemHeight = CInt(RowHeight)
e.ItemWidth = CInt(RowWidth)
End Sub
Private Sub ListBox1_DrawItem(sender As Object, e As DrawItemEventArgs) Handles ListBox1.DrawItem
Dim values As String() = CType(ListBox1.Items(e.Index), String())
e.DrawBackground()
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
DrawRow(e.Graphics, ListBox1.Font, SystemBrushes.HighlightText, Nothing, e.Bounds.X, e.Bounds.Y, RowHeight, ColWidths, values, False)
Else
DrawRow(e.Graphics, ListBox1.Font, Brushes.Black, Nothing, e.Bounds.X, e.Bounds.Y, RowHeight, ColWidths, values, False)
End If
End Sub
Private Sub GetRowColumnSizes(ByVal gr As Graphics, ByVal font As Font, ByVal values As List(Of String()), ByRef max_height As Single, ByRef col_widths As Single())
Dim num_cols As Integer = values(0).Length
col_widths = New Single(num_cols - 1) {}
max_height = 0
For Each row As String() In values
For col_num As Integer = 0 To num_cols - 1
Dim col_size As SizeF = gr.MeasureString(row(col_num), font)
If col_widths(col_num) < col_size.Width Then col_widths(col_num) = col_size.Width
If max_height < col_size.Height Then max_height = col_size.Height
Next
Next
End Sub
Private Sub DrawRow(ByVal gr As Graphics, ByVal font As Font, ByVal brush As Brush, ByVal box_pen As Pen, ByVal x0 As Single, ByVal y0 As Single, ByVal row_height As Single, ByVal col_widths As Single(), ByVal values As String(), ByVal draw_box As Boolean)
Dim rect As RectangleF = New RectangleF()
rect.Height = row_height
Using sf As StringFormat = New StringFormat()
Dim x As Single = x0
For col_num As Integer = 0 To values.Length - 1
sf.Alignment = StringAlignment.Near
sf.LineAlignment = StringAlignment.Center
rect.X = x
rect.Y = y0
rect.Width = col_widths(col_num)
gr.DrawString(values(col_num), font, brush, rect, sf)
If draw_box Then gr.DrawRectangle(box_pen, rect.X, rect.Y, rect.Width, rect.Height)
x += col_widths(col_num)
Next
End Using
End Sub
Result of my test:
For more details you can see: Make an owner-drawn ListBox that justifies columns in C#

Related

Call a Sub in a Textbox VB.Net

Get all combinations which declares an established amount sum
I managed to convert the code written to C #, and I would need some help. I don't know how to let them display the appropriate values in my Textbox.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Call (Main) - How to call in a Textbox1.Text
End Sub
Code:
Class SurroundingClass
Private Sub Main()
Dim numbers As Integer() = {3, 9, 8, 4, 5, 7, 10}
Dim target As Integer = 15
sum_up(New List(Of Integer)(numbers.ToList()), target)
End Sub
Private Shared Sub sum_up_recursive(ByVal numbers As List(Of Integer), ByVal target As Integer, ByVal part As List(Of Integer))
Dim s As Integer = 0
For Each x As Integer In part
s += x
Next
If s = target Then
Console.WriteLine("sum(" & String.Join(",", part.[Select](Function(n) n.ToString()).ToArray()) & ")=" + target)
End If
If s >= target Then
Return
End If
For i As Integer = 0 To numbers.Count - 1
Dim remaining = New List(Of Integer)()
Dim n As Integer = numbers(i)
For j As Integer = i + 1 To numbers.Count - 1
remaining.Add(numbers(j))
Next
Dim part_rec = New List(Of Integer)(part)
part_rec.Add(n)
sum_up_recursive(remaining, target, part_rec)
Next
End Sub
Private Shared Sub sum_up(ByVal numbers As List(Of Integer), ByVal target As Integer)
sum_up_recursive(numbers, target, New List(Of Integer)())
End Sub
End Class
When you run the code you will see that it outputs the sets of results one set at a time in the line Console.WriteLine("sum(" & String.Join(",", part.[Select](Function(n) n.ToString()).ToArray()) & ")=" + target).
As you want to get the result sets in one go, you will need to accumulate them at that point instead of writing to the console, and the Sub will need to be a Function with another parameter for the accumulator.
Making those modifications:
Public Class Form1
' Derived from the code at https://stackoverflow.com/questions/4632322/finding-all-possible-combinations-of-numbers-to-reach-a-given-sum
Function SumUpRecursive(numbers As List(Of Integer), target As Integer, part As List(Of Integer), solutions As List(Of List(Of Integer))) As List(Of List(Of Integer))
Dim s = part.Sum()
If s = target Then
' MsgBox("sum(" & String.Join(",", part.[Select](Function(n) n.ToString()).ToArray()) & ")=" & target)
solutions.Add(part)
End If
If s >= target Then
Return Nothing
End If
For i As Integer = 0 To numbers.Count - 1
Dim remaining = New List(Of Integer)()
Dim n As Integer = numbers(i)
For j As Integer = i + 1 To numbers.Count - 1
remaining.Add(numbers(j))
Next
Dim part_rec = New List(Of Integer)(part)
part_rec.Add(n)
SumUpRecursive(remaining, target, part_rec, solutions)
Next
Return solutions
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim numbers As Integer() = {3, 9, 8, 4, 5, 7, 10}
Dim target As Integer = 15
Dim nums = SumUpRecursive((numbers.ToList()), target, New List(Of Integer), New List(Of List(Of Integer)))
If nums Is Nothing Then
MsgBox("Failure :(")
Else
MsgBox(String.Join(vbCrLf, nums.Select(Function(b) String.Join(", ", b))))
' TextBox1.Lines = nums.Select(Function(b) String.Join(", ", b)).ToArray()
End If
End Sub
End Class
I'm sure there's a neater way of writing it.

function that runs when dynamically generated control is interacted with

I've been Having trouble with making a sub that runs when my datagridview cell is doubleclicked. It is caused because the datagridview is programmatically created, rather than created by the designer. I have found a help website i will include that appears to be related to the issue.
Public Class seattemplatecreator
Dim alphabet() As Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()
Private WithEvents dgv_flightTemplate As DataGridView
'help from https://it.toolbox.com/question/event-for-dynamically-created-command-button-043008
Public Sub init(ByVal dgv01 As DataGridView)
dgv_flightTemplate = dgv01
End Sub
Private Sub dgv_flightTemplate_CellMouseDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles dgv_flightTemplate.CellMouseDoubleClick
MsgBox("workwd")
End Sub
Private Sub btn_createflight_Click(sender As Object, e As EventArgs) Handles btn_createflight.Click
'used https://social.msdn.microsoft.com/Forums/vstudio/en-US/e222f438-f060-4e61-ab28-523d02db91b2/how-to-programmatically-create-datagridview-with-empty-columns-and-rows?forum=vbgeneral
'to help with this part for automatically generating the datagridview
MsgBox(alphabet(0))
Dim dgv_flightTemplate As New DataGridView
Dim c As Integer = txb_columns.Text
Dim r As Integer = txb_rows.Text
For colcount As Integer = 0 To c - 1
Dim nc As New DataGridViewTextBoxColumn
nc.Name = "Seating Column"
dgv_flightTemplate.Columns.Add(nc)
Next
dgv_flightTemplate.Rows.Add(r)
For x = 0 To r - 1
dgv_flightTemplate.Rows(x).HeaderCell.Value = alphabet(x).ToString
Next
Me.Controls.Add(dgv_flightTemplate)
dgv_flightTemplate.Location = New Point(400, 400)
dgv_flightTemplate.AllowUserToAddRows = False
dgv_flightTemplate.AllowUserToDeleteRows = False
dgv_flightTemplate.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders
dgv_flightTemplate.AutoResizeRows()
dgv_flightTemplate.AutoSize = True
End Sub
End Class
https://it.toolbox.com/question/event-for-dynamically-created-command-button-043008
Edit: Olivier Jacot-Descombes response was perfect all that was needed was run the "Init" sub.
Public Class seattemplatecreator
Dim alphabet() As Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()
Private WithEvents dgv_flightTemplate As DataGridView
'help from https://it.toolbox.com/question/event-for-dynamically-created-command-button-043008
Public Sub init(ByVal dgv01 As DataGridView)
dgv_flightTemplate = dgv01
End Sub
Private Sub dgv_flightTemplate_CellMouseDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles dgv_flightTemplate.CellMouseDoubleClick
MsgBox("workwd")
End Sub
Private Sub btn_createflight_Click(sender As Object, e As EventArgs) Handles btn_createflight.Click
'used https://social.msdn.microsoft.com/Forums/vstudio/en-US/e222f438-f060-4e61-ab28-523d02db91b2/how-to-programmatically-create-datagridview-with-empty-columns-and-rows?forum=vbgeneral
'to help with this part for automatically generating the datagridview
MsgBox(alphabet(0))
Dim dgv_flightTemplate As New DataGridView
Dim c As Integer = txb_columns.Text
Dim r As Integer = txb_rows.Text
For colcount As Integer = 0 To c - 1
Dim nc As New DataGridViewTextBoxColumn
nc.Name = "Seating Column"
dgv_flightTemplate.Columns.Add(nc)
Next
dgv_flightTemplate.Rows.Add(r)
For x = 0 To r - 1
dgv_flightTemplate.Rows(x).HeaderCell.Value = alphabet(x).ToString
Next
Me.Controls.Add(dgv_flightTemplate)
dgv_flightTemplate.Location = New Point(400, 400)
dgv_flightTemplate.AllowUserToAddRows = False
dgv_flightTemplate.AllowUserToDeleteRows = False
dgv_flightTemplate.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders
dgv_flightTemplate.AutoResizeRows()
dgv_flightTemplate.AutoSize = True
init(dgv_flightTemplate)
End Sub
End Class
Any help would be greatly appreciated
Thanks, Taine
You are not calling Init. But instead, you could as well directly assign to the field
dgv_flightTemplate = New DataGridView 'Note: No Dim here.
But even if you are creating the columns dynamically, you could add a grid with the designer. Just call
dgv_flightTemplate.Columns.Clear()
before adding columns.

Datagridview Horizontal to vertical button

The following code isn't working when exporting the datagridview data when trying to make it vertical with headers along the left side along with text beside each one. Once this is flipped the user would click on button1 to export to excel.
Imports System.Data.DataTable
Imports System.IO
Imports Microsoft.Office.Interop
Public Class Form1
Dim table As New DataTable(0)
Public checkBoxList As List(Of CheckBox)
Private ds As DataSet = Nothing
Private dt As DataTable = Nothing
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ds = New DataSet()
dt = New DataTable()
ds.Tables.Add("Table")
Dim my_DataView As DataView = ds.Tables(0).DefaultView
DataGridView1.DataSource = my_DataView
table.Columns.Add("Forename", Type.GetType("System.String"))
table.Columns.Add("Surname", Type.GetType("System.String"))
table.Columns.Add("Food", Type.GetType("System.String"))
checkBoxList = New List(Of CheckBox) From {CheckBox1, CheckBox2, CheckBox3, CheckBox4}
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim currentDataSet As DataSet = FlipDataSet(ds) ' Flip the DataSet
Dim values As String = "" &
String.Join(" & ", checkBoxList _
.Where(Function(cb) cb.Checked).Select(Function(cb) cb.Text))
' use values for placing into your DataGridView
CheckBox1.Text = values
CheckBox2.Text = values
CheckBox3.Text = values
CheckBox4.Text = values
table.Rows.Add(TextBox1.Text, TextBox2.Text, values.ToString)
DataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
DataGridView1.RowTemplate.Height = 100
DataGridView1.AllowUserToAddRows = False
DataGridView1.DataSource = table
'Save to excel with headers
Dim ExcelApp As Object, ExcelBook As Object
Dim ExcelSheet As Object
Dim i As Integer
Dim j As Integer
'create object of excel
ExcelApp = CreateObject("Excel.Application")
ExcelBook = ExcelApp.WorkBooks.Add
ExcelSheet = ExcelBook.WorkSheets(1)
With ExcelSheet
For Each column As DataGridViewColumn In DataGridView1.Columns
.cells(1, column.Index + 1) = column.HeaderText
Next
For i = 1 To Me.DataGridView1.RowCount
.cells(i + 1, 1) = Me.DataGridView1.Rows(i - 1).Cells("Forename").Value
For j = 1 To DataGridView1.Columns.Count - 1
.cells(i + 1, j + 1) = DataGridView1.Rows(i - 1).Cells(j).Value
Next
Next
End With
ExcelApp.Visible = True
'
ExcelSheet = Nothing
ExcelBook = Nothing
ExcelApp = Nothing
End Sub
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
End Sub
Public Function FlipDataSet(ByVal my_DataSet As DataSet) As DataSet
Dim ds As New DataSet()
For Each dt As DataTable In my_DataSet.Tables
Dim table As New DataTable()
For i As Integer = 0 To dt.Rows.Count
table.Columns.Add(Convert.ToString(i))
Next
Dim r As DataRow
For k As Integer = 0 To dt.Columns.Count - 1
r = table.NewRow()
r(0) = dt.Columns(k).ToString()
For j As Integer = 1 To dt.Rows.Count
r(j) = dt.Rows(j - 1)(k)
Next
table.Rows.Add(r)
Next
ds.Tables.Add(table)
Next
Return ds
End Function
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim currentDataSet As DataSet = FlipDataSet(ds) ' Flip the DataSet
Dim currentDataView As DataView = currentDataSet.Tables(0).DefaultView
DataGridView1.DataSource = currentDataView
Button2.Enabled = False
End Sub
End Class
When clicking button2 it should flip the data with the following;
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles
Button2.Click
Dim currentDataSet As DataSet = FlipDataSet(ds) ' Flip the DataSet
Dim currentDataView As DataView = currentDataSet.Tables(0).DefaultView
DataGridView1.DataSource = currentDataView
Button2.Enabled = False
End Sub
End Class
I've tried debugging but it i can't seem to find anything wrong? It will allow me to insert data in the textbox's whilst selecting checkbox's and when clicking button 1 to export it works fine, but it doesn't flip the data.
Please can anyone suggest how to fix this as i have a presentation on the 8th June and this data needs to automatically be flipped
Sourcecode: Download Myproject
Image of target
Answered:
Imports Microsoft.Office.Interop
Imports System.Runtime.InteropServices
Public Class Form1
Private ds As DataSet = Nothing
Private dt As DataTable = Nothing
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DataGridView1.AllowUserToAddRows = False
dt = New DataTable("MyTable")
dt.Columns.Add("Forename", Type.GetType("System.String"))
dt.Columns.Add("Surname", Type.GetType("System.String"))
dt.Columns.Add("Food", Type.GetType("System.String"))
ds = New DataSet
ds.Tables.Add(dt)
Dim my_DataView As DataView = ds.Tables("MyTable").DefaultView
DataGridView1.DataSource = my_DataView
End Sub
Private Sub Button_AddRowData_Click(sender As Object, e As EventArgs) Handles Button_AddRowData.Click
Dim foods As String = String.Join(" & ", CheckedListBox1.CheckedItems.Cast(Of String))
dt.Rows.Add(New Object() {TextBox_Forename.Text, TextBox_Surname.Text, foods})
End Sub
Private Sub Button_FlipAndSave_Click(sender As Object, e As EventArgs) Handles Button_FlipAndSave.Click
FlipAndSave(ds.Tables("MyTable"))
End Sub
Private Sub FlipAndSave(table As DataTable)
Dim ExcelApp As New Excel.Application
Dim WrkBk As Excel.Workbook = ExcelApp.Workbooks.Add()
Dim WrkSht As Excel.Worksheet = CType(WrkBk.Worksheets(1), Excel.Worksheet)
With WrkSht
For ci As Integer = 0 To table.Columns.Count - 1
.Cells(ci + 1, 1) = table.Columns(ci).ColumnName
Next
For ri As Integer = 0 To table.Rows.Count - 1
For ci As Integer = 0 To table.Columns.Count - 1
.Cells(ci + 1, ri + 2) = table.Rows(ri).Item(ci).ToString
Next
Next
End With
ExcelApp.Visible = True
'use this lines if you want to automatically save the WorkBook
'WrkBk.SaveAs("C:\Some Folder\My Workbook.xlsx") '(.xls) if you have an old version of Excel
'ExcelApp.Quit() 'use this line if you want to close the Excel Application
ReleaseObject(ExcelApp)
ReleaseObject(WrkBk)
ReleaseObject(WrkSht)
End Sub
Private Sub ReleaseObject(obj As Object)
Marshal.ReleaseComObject(obj)
obj = Nothing
End Sub
End Class

VB.Net Process.CloseMainWindow and Process.Close not working

I've used a background worker to launch an application, wait for cancellation and then close the application. But for some reason the application never closes. I've tried with and without notificationPreview.WaitForExit()
Private Sub bgWorker_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgWorker.DoWork
'Extract the executable to the applications directory path and execute it
Dim notificationPreview As New Process
Dim monitorExe As Byte() = My.Resources.ITSupportMonitoring
My.Computer.FileSystem.WriteAllBytes(My.Application.Info.DirectoryPath & "ITSupportMonitoring.exe", monitorExe, False)
notificationPreview = Process.Start(My.Application.Info.DirectoryPath & "ITSupportMonitoring.exe")
notificationPreview.WaitForInputIdle()
'Wait until the worker is sent a cancellation request
Do Until bgWorker.CancellationPending = True
System.Threading.Thread.Sleep(500)
Loop
'If the process hasn't been closed by the user close it
If Not notificationPreview.HasExited Then 'If the process is still running
notificationPreview.CloseMainWindow() 'Tell the main window of the notification process to close
notificationPreview.WaitForExit()
notificationPreview.Close() 'Free all resources used by the notification process
End If
My.Computer.FileSystem.DeleteFile(My.Application.Info.DirectoryPath & "ITSupportMonitoring.exe") 'Delete the executable file
e.Cancel = True
End Sub
Here is the FULL code for the process which will not close:
Public Class frmMonitoring
Dim noticeText As String
Private Sub frmMonitoring_Load(sender As Object, e As EventArgs) Handles Me.Load
'Set the notice text
If My.Application.CommandLineArgs.Count > 0 Then
noticeText = My.Application.CommandLineArgs(0)
Else
noticeText = "Example String"
End If
Me.ForeColor = Color.Black
tmrFlash.Interval = 1000
tmrFlash.Start()
Me.Top = 0
Me.Left = 0
Me.TopMost = True
End Sub
Private Sub tmrFlash_Tick(sender As Object, e As EventArgs) Handles tmrFlash.Tick
If Me.ForeColor = Color.Black Then
Me.ForeColor = Color.Red
Else
Me.ForeColor = Color.Black
End If
End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
Dim drawFont As New System.Drawing.Font(SystemFonts.DefaultFont.Name, 16)
Dim drawBrush As New System.Drawing.SolidBrush(Me.ForeColor)
Dim drawFormat As New System.Drawing.StringFormat
Dim drawRect As New RectangleF(e.ClipRectangle.Location, e.ClipRectangle.Size)
drawRect.Height = drawRect.Height * 0.65 'The bottom line of text was getting partially clipped, so reduced the height of the drawing area to 65%
drawFont = GetAdjustedFont(e.Graphics, noticeText, drawFont, drawRect, 40, 4, True)
Dim stringFormat As New StringFormat(StringFormatFlags.NoClip)
stringFormat.Alignment = StringAlignment.Center
stringFormat.LineAlignment = StringAlignment.Center
e.Graphics.DrawString(noticeText, drawFont, drawBrush, RectangleF.op_Implicit(ClientRectangle), stringFormat)
drawFont.Dispose()
drawBrush.Dispose()
End Sub
Public Function GetAdjustedFont(ByRef GraphicRef As Graphics, ByVal GraphicString As String, ByVal OriginalFont As Font, ByVal ContainerSize As RectangleF, ByVal MaxFontSize As Integer, ByVal MinFontSize As Integer, ByVal SmallestOnFail As Boolean) As Font
'Loop through font sizes and MeasureString to find the largest font which can be used
For AdjustedSize As Integer = MaxFontSize To MinFontSize Step -1
Dim TestFont = New Font(OriginalFont.Name, AdjustedSize, OriginalFont.Style)
Dim charsFitted As Integer
Dim linesFilled As Integer
' Test the string with the new size
Dim AdjustedSizeNew = GraphicRef.MeasureString(GraphicString, TestFont, ContainerSize.Size, New StringFormat, charsFitted, linesFilled)
If charsFitted = GraphicString.Length Then 'If every characted in the string was printed
'Good font, return it
Return TestFont 'New Font(TestFont.Name, TestFont.Size - 1, TestFont.Style)
End If
Next
' If you get here there was no fontsize that worked
' return MinimumSize or Original?
If SmallestOnFail Then
Return New Font(OriginalFont.Name, MinFontSize, OriginalFont.Style)
Else
Return OriginalFont
End If
End Function
End Class

Unable to start multiple thread

I'm trying to run this code, but when running only the first n listbox looping , the others remain empty. I would like to run the subroutine code (an infinite loop) for each listbox in the form at the same time
This is the Main Form:
Public Class Form1
Private listSettings As New List(Of ListBox)
Private nameSettings As New List(Of Label)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Variabili Grafiche
Dim lSettings As ListBox
Dim i As Integer
i = 0
Dim n As Integer
Dim width As Integer
Dim height As Integer
'Variabili Lettura File
Dim path As New IO.DirectoryInfo("C:\BatchDomoLake\config\")
Dim diar1 As IO.FileInfo() = path.GetFiles()
Dim dra As IO.FileInfo
'Lettura File e Grafica
For Each dra In diar1
n = n + 1
Next
Dim T(n) As Thread
width = (Me.Size.Width() / n)
height = (Me.Size.Height() / 2)
For Each dra In diar1
lSettings = New ListBox
With lSettings
.Location = New Point(10 + (width * i), 40)
.Name = "lst" & dra.Name.Replace(".conf", "")
.Size = New Size(width - 35, height - 40)
.Visible = True
End With
Me.listSettings.Add(lSettings)
Me.Controls.Add(lSettings)
Dim reader As StreamReader = My.Computer.FileSystem.OpenTextFileReader(dra.FullName)
Dim a As String
Do
a = reader.ReadLine
If a IsNot Nothing Then
lSettings.Items.Add(a)
End If
Loop Until a Is Nothing
'Thread
T(i) = New Threading.Thread(AddressOf snmpThread)
T(i).Start(lSettings)
i = i + 1
Next
End Sub
This is the subroutine i would like to use for each created listbox:
Private Delegate Sub snmpThreadDelegate(ByVal list As ListBox)
Private Sub snmpThread(ByVal list As ListBox)
If list.InvokeRequired Then
list.Invoke(New snmpThreadDelegate(AddressOf snmpThread), New Object() {list})
Else
Dim count As Integer
Dim i As Integer
count = list.Items.Count - 1
Do
For i = 0 To count Step 1
list.SetSelected(i, True)
Thread.Sleep(100)
Next
Loop
End If
End Sub
You cannot access/update your UI elements from background threads. Only main UI thread can do operations on your UI objects. This applies to both WinForms and WPF.
For WinForms, you can use BeginInvoke method and pass in a delegate that would be invoked in your UI thread. For WPF, you can use Dispatcher object.