Reputation: 91
In the code below I am attempting to change the tag of an existing control that was created in the array 'pictureboxes(9, 9)'. When I try to do this, I get the error 'Object reference not set to an instance of an object.'. This is done in the checkdata sub, near the bottom of the code with the comment 'Object reference not set to an instance of an object.'.
The string that is passed through to the sub is a long string of numbers, and the pictureboxes are placed into a layoutpanel if that is helpful.
I understand what this error means, I am aware that pictureboxes(i, j) is = nothing when breakpointed; I just don't know how to fix it :s
Any help is greatly appreciated and hopefully I will be quick to answer any comments/answers.
Thank you
Imports System.Net.Sockets
Imports System.Threading
Imports System.Text
Imports System.Net
Public Class Form1
'0 as default tile, 1 as clicked, 3 as set mine (host perspective)
Dim tiles() As Integer = {0}
Public pictureboxes(9, 9) As PictureBox
Dim flagged() As Integer
Dim clicked As Integer()
Dim columns As Integer = 10
Dim rows As Integer = 10
Dim placedMinesCount As Integer = 0
Dim formattedTag As String()
Public turn As Boolean = False
Dim stringToSend As String
Public Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For i As Byte = 0 To 9
For j As Byte = 0 To 9
pictureboxes(i, j) = New PictureBox
pictureboxes(i, j).Height = 60
pictureboxes(i, j).Width = 60
pictureboxes(i, j).ImageLocation = "0.png"
pictureboxes(i, j).Tag = "0|" & i & ", " & j
AddHandler pictureboxes(i, j).Click, AddressOf Tile_Click
Dim column As Integer = j
Dim row As Integer = i
Panel.Controls.Add(pictureboxes(i, j), column, row)
Next
Next
If Login.isHost = True Then
Me.Text = "Set your mines (10)"
turn = True
ElseIf Login.isHost = False Then
Me.Text = "Await your turn"
btnEndTurn.Visible = False
btnEndTurn.Enabled = False
End If
End Sub
Protected Sub Tile_Click(ByVal sender As Object, ByVal e As EventArgs)
formatSenderTag(sender.tag)
If Login.isHost = True Then
Dim clickAction As String = formattedTag(0)
Select Case clickAction
Case "0"
If placedMinesCount < 10 Then
placedMinesCount = placedMinesCount + 1
sender.imagelocation = "3.png"
sender.tag = "3"
Me.Text = "Set your mines (" & 10 - placedMinesCount & ")"
ElseIf placedMinesCount >= 10 Then
MsgBox("You have placed all of your 10 Mines")
End If
Case "2"
MsgBox("You cannot set a mine here")
Case "3"
placedMinesCount = placedMinesCount - 1
Me.Text = "Set your mines (" & 10 - placedMinesCount & ")"
sender.imagelocation = "0.png"
sender.tag = "0"
End Select
ElseIf Login.isHost = False Then
Dim clickAction As String = formattedTag(0)
Select Case clickAction
Case "0"
sender.tag = "1"
sender.imagelocation = "1.png"
Case "3"
MsgBox("Game Over")
Case "2"
MsgBox("Already Clicked")
End Select
End If
End Sub
Private Sub formatSenderTag(ByVal sender As String)
'split into array
'element 0 as TILE TYPE
'element 1 as TILE LOCATION
formattedTag = sender.Split(New String() {"|"}, StringSplitOptions.None)
End Sub
Private Sub Form_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
End
End Sub
Private Sub btnEndTurn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEndTurn.Click
turn = False
gridtostring()
senddata()
End Sub
Private Sub gridtostring()
For i As Byte = 0 To 9
For j As Byte = 0 To 9
formatSenderTag(pictureboxes(i, j).Tag & "|")
stringToSend = stringToSend & formattedTag(0)
Next
Next
End Sub
Private Sub senddata()
'***SEND STUFF
'Assuming you have a textbox with the data you want to send
If (Not String.IsNullOrEmpty(stringToSend)) Then
Dim data() As Byte = Encoding.ASCII.GetBytes(stringToSend)
Login.sendingClient.Send(data, data.Length)
End If
End Sub
Public Sub checkdata(ByVal data As String)
If Not data = stringToSend Then
'Dim loopcount As Integer = 0
For i As Byte = 0 To 9
For j As Byte = 0 To 9
Dim loopcount As Integer = (i.ToString & j.ToString) + 1
'Dim pineapple As String = pictureboxes(i, j).Tag
'pictureboxes(i, j).Tag = GetChar(data, 3)
pictureboxes(i, j).Tag = GetChar(data, loopcount) & "|" & i & ", " & j '***Object reference not set to an instance of an object.***
formatSenderTag(pictureboxes(i, j).Tag)
pictureboxes(i, j).ImageLocation = formattedTag(0)
pictureboxes(i, j).ImageLocation = "0.png"
'Panel.Controls(pictureboxes(i, j).Tag) = GetChar(data, 3) '.Tag = GetChar(data, 3)
Next
Next
End If
End Sub
End Class
***AND BELOW IS THE OTHER FORM WHICH CALLS CHECKDATA()
Imports System.Net.Sockets
Imports System.Threading
Imports System.Text
Imports System.Net
Public Class Login
Dim Port As Integer = 8123
Private Const broadcastAddress As String = "255.255.255.255"
Public receivingClient As UdpClient
Public sendingClient As UdpClient
Dim sendAddress As String
Dim ServerMode As Boolean = False
Public isHost As Boolean = true
Dim returndata As String
Private Sub Login_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub ComboWANLAN_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboWANLAN.SelectedIndexChanged
If ComboWANLAN.Text = "Online (WAN)" Then
txtSendAddress.Enabled = True
ElseIf ComboWANLAN.Text = "Offline (LAN)" Then
txtSendAddress.Enabled = False
End If
End Sub
Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
'***START PORT LISTENING/SENDING AND NETWORKING STUFFS
Port = txtPort.Text
InitializeSender()
InitializeReceiver()
End Sub
Private Sub btnHost_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnHost.Click
'***START PORT LISTENING/SENDING AND NETWORKING STUFFS
Port = txtPort.Text
InitializeSender()
InitializeReceiver()
isHost = True
Me.Hide()
Form1.Show()
End Sub
Private Sub InitializeSender()
If ComboWANLAN.Text = "Offline (LAN)" Then
sendingClient = New UdpClient(broadcastAddress, Port)
'Use broadcastAddress for sending data locally (on LAN), otherwise you'll need the public (or global) IP address of the machine that you want to send your data to
ElseIf ComboWANLAN.Text = "Online (WAN)" Then
sendAddress = txtSendAddress.Text
sendingClient = New UdpClient(sendAddress, Port)
'Use broadcastAddress for sending data locally (on LAN), otherwise you'll need the public (or global) IP address of the machine that you want to send your data to
End If
sendingClient.EnableBroadcast = True
End Sub
Private Sub InitializeReceiver()
receivingClient = New UdpClient(Port)
ThreadPool.QueueUserWorkItem(AddressOf Receiver) 'Start listener on another thread
End Sub
Private Sub Receiver()
Dim endPoint As IPEndPoint = New IPEndPoint(IPAddress.Any, port) 'Listen for incoming data from any IP on the specified port
Do While True 'Notice that i've setup an infinite loop to continually listen for incoming data
Dim data() As Byte
data = receivingClient.Receive(endPoint)
If Form1.turn = False Then
returndata = Encoding.ASCII.GetString(data) 'Recived data as string
Form1.checkdata(returndata)
End If
Loop
End Sub
Private Sub Form_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
End
End Sub
End Class
***STACK TRACE
at Minesweeper.Form1.checkdata(String data) in c:\users\harry\documents\visual studio 2010\Projects\Minesweeper\Minesweeper\Form1.vb:line 139
at Minesweeper.Login.Receiver() in C:\Users\Harry\Documents\Visual Studio 2010\Projects\Minesweeper\Minesweeper\Login.vb:line 71
at Minesweeper.Login._Lambda$__1(Object a0) in C:\Users\Harry\Documents\Visual Studio 2010\Projects\Minesweeper\Minesweeper\Login.vb:line 61
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
Note: Screwed up with the spacings in some places
Upvotes: 2
Views: 460
Reputation: 2568
This code does not give an error with the data you gave:
checkdata("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
Public Sub checkdata(ByVal data As String)
If Not data = stringToSend Then
'Dim loopcount As Integer = 0
For i As Byte = 0 To 9
For j As Byte = 0 To 9
Dim loopcount As Integer = (i.ToString & j.ToString) + 1
'Dim pineapple As String = pictureboxes(i, j).Tag
'pictureboxes(i, j).Tag = GetChar(data, 3)
pictureboxes(i, j).Tag = GetChar(data, loopcount) & "|" & i & ", " & j '***Object reference not set to an instance of an object.***
formatSenderTag(pictureboxes(i, j).Tag)
pictureboxes(i, j).ImageLocation = formattedTag(0)
pictureboxes(i, j).ImageLocation = "0.png"
'Panel.Controls(pictureboxes(i, j).Tag) = GetChar(data, 3) '.Tag = GetChar(data, 3)
Next
Next
End If
End Sub
Looking at your stack trace and code, you are missing the instantiation of Form1 in your login class. I think this can be the problem.
Try adding this to the beginning of your Login class:
Dim Form1 as New Form1
Upvotes: 1