Array of Rectangles [duplicate] - arrays

This question already has answers here:
VS2010 does not show unhandled exception message in a WinForms Application on a 64-bit version of Windows
(5 answers)
Closed 8 years ago.
I'm having a hard time displaying rectangles from an array.
Here's the code:
Dim recs(9) As PowerPacks.RectangleShape
Dim canvas As New Microsoft.VisualBasic.PowerPacks.ShapeContainer
Private Sub Spi_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim sz As Integer = 350
canvas.Parent = Me
recs(0).Height = sz
recs(0).Width = sz
recs(0).Left = 20
recs(0).Top = 20
recs(0).Parent = canvas
recs(0).FillColor = Color.Green
recs(0).FillStyle = PowerPacks.FillStyle.Solid
End Sub
There are no syntax or runtime errors. I can't figure out what is going on.
If I try to make a rectangle alone it will show it but when I'm making an array of them, it shows nothing. If I debug it, when the next statement to be executed is any line of code that uses the array, it justs ignores it and moves on, meaning that it will ignore all my commands that use the "recs(0)". Why???
Any help is appreciated. Thanks.
EDIT: Ok guys. Thanks for your help.

As has been mentioned, your problem is, the array isn't initialized, and since you can't initialize an array with New you'll either have to initialize each element or switch to a different collection, like List:
Dim recs(9) As PowerPacks.RectangleShape
Dim canvas As New Microsoft.VisualBasic.PowerPacks.ShapeContainer
Private Sub Spi_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim sz As Integer = 350
canvas.Parent = Me
recs(0) = New PowerPacks.RectangleShape(20, 20, sz, sz)
recs(0).Parent = canvas
recs(0).FillColor = Color.Green
recs(0).FillStyle = PowerPacks.FillStyle.Solid
End Sub
Dim recs As New List(Of PowerPacks.RectangleShape)

Related

Getting exception while initializing the value in array dynamically [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
I am beginner in VB. I am trying to find the indexes of selected values of ListBox1 and print those indexes in ListBox2. I am not specifying the length of array. I want it to take the values dynamically. Here is the code..
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim a() As Integer
Dim b As Integer = 0
For x As Integer = 0 To ListBox1.Items.Count - 1
If ListBox1.GetSelected(x) = True Then
a(b) = x
b = b + 1
End If
Next
For x As Integer = 0 To a.Length - 1
ListBox2.Items.Add(a(x))
Next
End Sub
The exception I am getting at line a(b) = x is as follows
NullReferenceException was unhandled
Object reference not set to an instance of an object.
Can you kindly help me in this?
You either remove a() completely or else define a size for it:
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
ListBox2.Items.Clear()
For x As Integer = 0 To ListBox1.Items.Count - 1
If ListBox1.GetSelected(x) = True Then
ListBox2.Items.Add(x)
End If
Next
End Sub
You should set a like this:
Dim a As Integer()
And then do a ReDim to initialise:
ReDim a(0 to ListBox1.Items.Count - 1)
Or however long you think a should be.

NullReferenceException was unhandled VB.net Structure with Array

Public Class Form1
Structure Crap
Dim CrapA As Integer
Dim CrapB As Single
Dim CrapC() As Long
Private Sub Initialize()
ReDim CrapC(0 To 100)
End Sub
End Structure
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim Stuff(0 To 2) As Crap
Stuff(0).CrapA = 16
Stuff(1).CrapA = 32
Stuff(2).CrapA = 64
'This is the line where the NullReferenceException is thrown
Stuff(0).CrapC.Initialize()
For x = 0 To 100
Stuff(0).CrapC(x) = x ^ 2
Next x
MsgBox(Stuff(0).CrapA)
MsgBox(Stuff(1).CrapA)
MsgBox(Stuff(2).CrapA)
For x = 0 To 100
MsgBox(Stuff(0).CrapC(x))
Next x
End Sub
End Class
So this is a pretty simple program with a baffling error. All I want is an array in my user defined type. I'm moving from VB6 to .net and everything I've read, including What is a NullReferenceException, and how do I fix it? which is a hearty read, doesn't help. Seems I'm stuck in 1999, lol. I understand that the array CrapC is null, it's making it not null that's the problem.
The error happens here:
Stuff(0).CrapC.Initialize()
because the Crap() contains three instances of Crap but you never initialize the CrapC field which is a Long(). So you can call Initialize on Nothing(null). In most cases you don't need this method anyway: "This method is designed to help compilers support value-type arrays; most users do not need this method."
Instead use this array initializer to get a Long() with 100 longs:
Stuff(0).CrapC = New Long(99) {}

ProcessWindowStyle.Hidden in string array

In my VB.net project, I am trying to call up multiple programs using an array to help clean up my code.
Currently, I have this code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles StartServer.Click
Dim proc As New ProcessStartInfo()
Dim prochide As New ProcessStartInfo()
prochide.WindowStyle = ProcessWindowStyle.Hidden
If CheckBox1.CheckState = 1 Then
proc.WorkingDirectory = TextBox1.Text
proc.FileName = "xserver.exe"
Process.Start(proc)
proc.FileName = "yserver.exe"
Process.Start(proc)
proc.FileName = "zserver.exe"
Process.Start(proc)
Else
prochide.WorkingDirectory = TextBox1.Text
prochide.FileName = "xserver.exe"
Process.Start(prochide)
prochide.FileName = "yserver.exe"
Process.Start(prochide)
prochide.FileName = "zserver.exe"
Process.Start(prochide)
End If
End Sub
What this does is allows me to hide the windows so they show up in task manager but the windows don't actually show up.
However, I would prefer to switch with this code or something similar to clean it up:
Dim servers(0 To 2) As String
servers(0) = "xserver.exe"
servers(1) = "yserver.exe"
servers(2) = "zserver.exe"
Then I can simplify the code:
Dim directory As String = TextBox1.Text
For Each fileName As String In servers
Next
However, I cannot figure out how to hide the windows in an array, since the .WindowStyle = ProcessWindowStyle.Hidden does not seem to work with array strings. Is there another way I can do this?Changing the method is fine, I just want to try to clean up the code since it seems a bit bulky right now.
Okay so I've finally checked this out, and this works for me:
Public Class Form1
Dim servers() As String = New String() {"cmd.exe|1", "cmd.exe|1", "cmd.exe|1"}
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim directory As String = TextBox1.Text
Dim prochide As New ProcessStartInfo()
prochide.WorkingDirectory = directory
For Each fileName As String In servers
Dim FileOptions() As String = Split(fileName, "|")
prochide.FileName = FileOptions(0)
prochide.WindowStyle = CType(FileOptions(1), ProcessWindowStyle)
Process.Start(prochide)
Next
End Sub
End Class
When using New String() you cannot declare the array with a limit. So that was our problem. :)
So instead of Dim servers(3)... or Dim servers(0 To 2)... you have to use Dim servers()...

How to respond to events for objects in an array

I have made an array of tiles (pictureboxes) in an array and need them to all do something when clicked, but don't know how. Specifically, I want to be able to place some other object on them by clicking a tile and making that object go to that tile's location. I know you may suggest looking at the mouseposition variable and having some invisible box over all the tiles to register clicks, but I would like to know how to register any event for an object in an array for anything that comes up in the future. I do know how to register events for objects which aren't in an array by the way.
The object I want to move on top of the picturebox will also be from an object array, but a different one.
Here is my code:
Public Class Form1
Dim tiles(50) As PictureBox 'This is the object array of tiles
Dim plants() As String 'I haven't set this up yet, but this will be for the objects to be 'placed' on the pictureboxes.
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim tileWidth As Integer = 50
Dim tileHeight As Integer = 50
Dim xindent As Integer = 10
Dim yindent As Integer = 10
For x = 0 To 9
For y = 0 To 4
ReDim Preserve tiles(x * y)
tiles(x * y) = New PictureBox With {.Visible = True, .Size = New System.Drawing.Size(50, 50), .Parent = Me, .BackColor = Color.GreenYellow, .Image = Nothing}
tiles(x * y).Location = New System.Drawing.Point(x * tileWidth + xindent, y * tileHeight + yindent)
If (x Mod 2 = 0 And y Mod 2 = 0) Or (x Mod 2 <> 0 And y Mod 2 <> 0) Then
tiles(x * y).BackColor = Color.Green
End If
Next
Next
End Sub
End Class
I simply don't know how to set up the click event handler for the array of tiles so that's why its not in the code above.
Thanks in advance for your help.
AddHandler is there for that. After the New you just need to attach a function to the event
AddHandler tiles(x * y).Click, AddressOf Tile_Click
And have a function that handles the event
Private Sub Tile_Click(sender As Object, e As System.EventArgs)
' sender represent the reference to the picture box that was clicked
End Sub
If you already know the size of the array, you should ReDim your array just once instead of each time you loop (Move the ReDim out of the loops). Also, since y is 0 on the first loop, you are basically doing a ReDim of 0 elements (x*y = 0 when y = 0)
the_lotus has already given you a great answer.
Just wanted to share a trick I often use when wiring up events with AddHandler.
Declare a temporary variable using WithEvents in your class:
Public Class Form1
Private WithEvents Tile As PictureBox
...
Now, in the two DropDowns across the top of code editor, change Form1 to Tile, and (Declarations) to Click (or whatever event you want). This will enter a method for you that has the correct method signature:
Private Sub Tile_Click(sender As Object, e As EventArgs) Handles Tile.Click
End Sub
Delete the Handles Tile.Click portion that appears at the end of the first line:
Private Sub Tile_Click(sender As Object, e As EventArgs)
End Sub
Finally, remove your temporary declaration that used WithEvents.
Now you've got a method with the correct signature that you can use with AddHandler. This is very handy for events that don't have the standard signature.

Deleting Lines from Array

I have an array of lines and I want at some point to erase some of them.
Here's a sample of the code:
Dim canvas As New Microsoft.VisualBasic.PowerPacks.ShapeContainer
Dim lines(20) As PowerPacks.LineShape
Dim it As Integer = 0
Private Sub GoldenSpi_Load(sender As Object, e As EventArgs) Handles MyBase.Load
canvas.Parent = Me
lines.Initialize()
iter.Text = 0
End Sub
Private Sub iter_TextChanged(sender As Object, e As EventArgs) Handles iter.TextChanged
If (it > iter.Text And iter.Text <> 0) Then
ReDim Preserve lines(iter.Text - 1)
End If
If (it <> iter.Text) Then
it = iter.Text
End If
For i As Integer = 1 To iter.Text
lines(i - 1) = New PowerPacks.LineShape(canvas)
lines(i - 1).StartPoint = pA(i)
lines(i - 1).EndPoint = pB(i)
lines(i - 1).BringToFront()
Next
End Sub
After I execute the program, the lines are created. But when I give a value to my textbox that is smaller than the variable 'it', it justs delete the last line and not the rest. Also I saw while debugging that the size of array is reduced. So that means that the contents beyond the size are still kept? Why is that?. Any help is appreciated. Thanks.
EDIT: I tried to create the List like this:
Dim lines As New Generic.List(Of PowerPacks.LineShape)
Private Sub iter_ValueChanged(blabla) Handles iter.ValueChanged
If (it > iter.Value And iter.Value <> 0) Then
lines.RemoveRange(iter.Value - 1, lines.Count - iter.Value)
End If
For i As Integer = 1 To iter.Value
InitPoints()
If i - 1 = lines.Count Then
Dim line As New PowerPacks.LineShape
With line
.StartPoint = pA(i)
.EndPoint = pB(i)
.BringToFront()
.Parent = canvas
End With
lines.Add(line)
End If
Next
End Sub
But still the lines are visible in the form. I debugged it and saw that the list size decreased. The same problem when I had an array. What is going?...
I recommend changing iter.Text to cint(iter.Text), as there is a chance it's comparing both values as text (which is compared differently).
I'd also recommend changing Dim lines(20) As PowerPacks.LineShape to Dim lines As new generic.list(of PowerPacks.LineShape)
That way you don't have to worry about ReDim Preserve (which can be slow when you do it in a loop), and you can easily insert items into any index if you whish
You should use Option Strict On in your project, in order to avoid implicit conversion between types which can give you errors or, worse, unexpected behaviors.
On the other hand, you should not have a TextBox to store numbers unless there is a need. Use a NumericUpDown, for example. Take a look at the MSDN Documentation.
And now, for the array, I recommend using a List, which has all the methods implemented that you need to handle the elements, and has a .ToArray() method that will give you the array if needed.
Try something like this:
Dim it As Integer = 0
Dim lines As New List(Of PowerPacks.LineShape)()
Sub iter_TextChanged(sender As Object, e As EventArgs) Handles iter.TextChanged
Dim iTxt As Integer
Try
iTxt = Integer.Parse(iter.Text)
If it > iTxt AndAlso iTxt <> 0 Then
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
I was going to write to you an example, but I realized that I don't know exactly what you're trying to do. Could you explain?

Resources