How to solve ArgumentException : The parameter is not valid for drawing Arcs - vb.net

I'm making a custom winforms button in VB.Net with rounded edges and other features. I create a path using various inputs defined by the user and draw and fill it using pens and brushes.
When I call e.Graphics.FillEllipse(Brush1, Rect1) and e.Graphics.DrawEllips(Pen1, Rect1) it just works fine without any problems, but when I try e.Graphics.FillPath(Brush1, OuterPath) and e.Graphics.DrawPath(Pen1, OuterPath) it doesn't work at all. I get this error:
ArgumentException: The parameter is not valid
I tried giving the right types of each variable used in the process and not letting the compiler decide, creating more variables to calculate and manage the inputs individually to not make all the calculations in the inputs of each function, which makes my work easier honestly, and even using the CType function in the inputs of each function to make sure that the function understands what I want as inputs. But everything failed and I don't know what to do next to fix the issue.
Here is the code:
Private Sub MetaniumButton_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Dim PathWidth As Integer = Width - BorderSize / 2
Dim PathHeight As Integer = Height - BorderSize / 2
_Roundnes = RoundnesMemory
If PathHeight < Roundenes.Height Then
_Roundnes.Height = PathHeight - 1
End If
If PathWidth < Roundenes.Width Then
_Roundnes.Width = PathWidth - 1
End If
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
Dim OuterPath As New GraphicsPath
Dim Rec1 As Rectangle = New Rectangle(CType(BorderSize / 2, Int32), CType(BorderSize / 2, Int32), CType(_Roundnes.Width, Int32), CType(_Roundnes.Height, Int32))
Dim Rec2 As Rectangle = New Rectangle(PathWidth - _Roundnes.Width, BorderSize / 2, _Roundnes.Width, _Roundnes.Height)
Dim Rec3 As Rectangle = New Rectangle(PathWidth - _Roundnes.Width, PathHeight - _Roundnes.Height, _Roundnes.Width, _Roundnes.Height)
Dim Rec4 As Rectangle = New Rectangle(BorderSize / 2, PathHeight - _Roundnes.Height, _Roundnes.Width, _Roundnes.Height)
OuterPath.StartFigure()
OuterPath.AddLine(CInt(_Roundnes.Width / 2 + BorderSize / 2), CInt(BorderSize / 2), CInt(PathWidth - _Roundnes.Width / 2), CInt(BorderSize / 2))
OuterPath.AddArc(Rec1, 180.0, 90.0) ' Here is the problem and it could probably in any AddArc Function i used
OuterPath.AddLine(PathWidth, CInt(_Roundnes.Height / 2 + BorderSize / 2), PathWidth, CInt(PathHeight - _Roundnes.Height / 2))
OuterPath.AddArc(Rec2, -90, 90)
OuterPath.AddLine(CInt(_Roundnes.Width / 2 + BorderSize / 2), PathHeight, CInt(PathWidth - _Roundnes.Width / 2), PathHeight)
OuterPath.AddArc(Rec3, 0, 90)
OuterPath.AddLine(CInt(BorderSize / 2), CInt(_Roundnes.Height / 2), CInt(BorderSize / 2), CInt(PathHeight - _Roundnes.Height / 2))
OuterPath.AddArc(Rec4, 90, 90)
OuterPath.CloseFigure()
e.Graphics.FillPath(Brush1, OuterPath)
e.Graphics.DrawPath(Pen1, OuterPath)
Dim LabelCount As Integer = 0
For Each l As Label In Controls
LabelCount += 1
Next
Dim TextPlace As New Label With {.Name = "TextLabel",
.Text = Text,
.AutoEllipsis = True,
.Size = New Size(Width -
Margin.Left + Margin.Right + 2 * _Roundnes.Width) / 2, Height - (Margin.Top + Margin.Bottom + 2 * _Roundnes.Height) / 2),
.TextAlign = _TextAlign,
.ForeColor = _FontColor,
.BackColor = _MetaniumBackColor,
.Location = New Point((Width - .Width) / 2, (Height - .Height) / 2)}
AddHandler TextPlace.TextChanged, AddressOf MetaniumButton_TextChanged
AddHandler Me.TextChanged, AddressOf MetaniumButton_TextChanged
Controls.Add(TextPlace)
T += 1
If LabelCount <= 0 Then
0: For Each l As Label In Controls
If l.Name = "TextLabel" Then
l.Text = Text
l.AutoEllipsis = True
l.Size = New Size(Width - (Margin.Left + Margin.Right + 2 * _Roundnes.Width) / 2, Height - (Margin.Top + Margin.Bottom + 2 * _Roundnes.Height) / 2)
l.TextAlign = _TextAlign
l.ForeColor = _FontColor
l.BackColor = _MetaniumBackColor
l.Location = New Point((Width - l.Width) / 2, (Height - l.Height) / 2)
End If
Next
ElseIf LabelCount = 1 Then
For Each l As Label In Controls
If l.Name <> "TextLabel" Then
Controls.Remove(l)
Else
GoTo 1
End If
1: GoTo 0
Next
Else
End If
End Sub
When I track down the bug it seems the problem is in the AddArc() function, and I really don't know why it doesn't work. Any help appreciated.
BTW, I use VB.Net Express 2010 with .Net Framework 4.8.
PS: you can post an answer using either VB.Net or C# I can translate the code from both of them.

I solved My problem, and the answer was to initialize the value or Roundnes to (1,1) at least because my code creates the arcs of the edges using Roundnes to know how wide and long the curving edge
so the solution is to add this line of code before the code responsible for creating the arc.
If _Roundnes = New Size(0, 0) Then _Roundnes = New Size(1, 1)
And that's pretty much it! Thank you for helping me out!

Related

Looking to solve an infinite loop

I have a piece of code that generates a dungeon in Java and Python but seems to create an infinite loop in visual basic. There might be a slight problem that I'm overlooking.
Dim Touching As Boolean = True
While Touching = True
Touching = False
'Run through all the rooms and check if they overlap
For i = 0 To numRooms
Dim aPos As Point = RoomXY(i)
Dim aDime As Point = RoomWH(i)
For j = 0 To numRooms
Dim bPos As Point = RoomXY(j)
Dim bDime As Point = RoomWH(j)
If (aPos = bPos) And (aDime = bDime) Then
Continue For
Else
'Check for overlapping
Dim H_Overlaps As Boolean = (aPos.X <= bPos.X + bDime.X) And (bPos.X <= aPos.X + aDime.X)
Dim V_Overlaps As Boolean = (aPos.Y <= bPos.Y + bDime.Y) And (bPos.Y <= aPos.Y + aDime.Y)
If H_Overlaps AndAlso V_Overlaps Then
Touching = True
'Find the minimum amount of movment that stops the squares from touching
Dim dx = Math.Min(Math.Abs((aPos.X + aDime.X) - (bPos.X + 2)), Math.Abs(aPos.X - (bPos.X + bDime.X + 2)))
Dim dy = Math.Min(Math.Abs((aPos.Y + aDime.Y) - (bPos.Y + 2)), Math.Abs(aPos.Y - (bPos.Y + bDime.Y + 2)))
If dx <= dy Then
dy = 0
Else
dx = 0
End If
If aPos.X >= bPos.X Then
RoomXY(i) = New Point(RoomXY(i).X + (dx / 2), RoomXY(i).Y)
RoomXY(j) = New Point(RoomXY(j).X - (dx / 2), RoomXY(j).Y)
Else
RoomXY(i) = New Point(RoomXY(i).X - (dx / 2), RoomXY(i).Y)
RoomXY(j) = New Point(RoomXY(j).X + (dx / 2), RoomXY(j).Y)
End If
If aPos.Y >= bPos.Y Then
RoomXY(i) = New Point(RoomXY(i).X, RoomXY(i).Y + (dy / 2))
RoomXY(j) = New Point(RoomXY(j).X, RoomXY(j).Y - (dy / 2))
Else
RoomXY(i) = New Point(RoomXY(i).X, RoomXY(i).Y - (dy / 2))
RoomXY(j) = New Point(RoomXY(j).X, RoomXY(j).Y + (dy / 2))
End If
End If
End If
Next
Next
End While
This piece is of code is given room dimensions, checks if they overlap and then shifts them away from each other. I've tried everything, but I can't seem to break the infinite loop.

Error bar not showing all the values in mschart

I am using VB.NET with mschart. I am using ErroBar chartype but i am not able to label all the values (medium, upper and lower). When i set chart.Series("ErrorBar").IsValueShownAsLabel = True, only upper value is shown.
I want to show the center, upper and lower values.
Thanks in advance
The solution adopted by me was a simpler one using annotations as can be seen in the code below
Dim Media1 As New RectangleAnnotation()
Media1.BackColor = Color.Yellow
Media1.Text = FormatNumber(D20, 4)
Dim point As PointF = New PointF(chart.ChartAreas(0).AxisX.ValueToPosition(1), chart.ChartAreas(0).AxisY.ValueToPosition(D20))
Media1.AnchorX = point.X + 10
Media1.AnchorY = point.Y + 2
Media1.AllowMoving = True
Dim L1 As New RectangleAnnotation()
L1.BackColor = Color.Yellow
L1.Text = FormatNumber(D20 - result * My.Settings("IncertezaDensidade20") / 2, 4)
point = New PointF(chart.ChartAreas(0).AxisX.ValueToPosition(1), chart.ChartAreas(0).AxisY.ValueToPosition(D20 - result * My.Settings("IncertezaDensidade20") / 2))
L1.AnchorX = point.X
L1.AnchorY = point.Y + 10
L1.AllowMoving = True
Dim L2 As New RectangleAnnotation()
L2.BackColor = Color.Yellow
L2.Text = FormatNumber(D20 + result * My.Settings("IncertezaDensidade20") / 2, 4)
point = New PointF(chart.ChartAreas(0).AxisX.ValueToPosition(1), chart.ChartAreas(0).AxisY.ValueToPosition(D20 + result * My.Settings("IncertezaDensidade20") / 2))
L2.AnchorX = point.X
L2.AnchorY = point.Y - 5
L2.AllowMoving = True
The chart now, can be seen below

Looking for specific label properties in VB.net

Image of the problem
Sub DrawGraph()
'Used to draw the current state.
G = Me.CreateGraphics
'G.Clear(Color.White) 'Sets entire background to white
G.clear(transparent)
Dim placeholder As Integer = 0 'Used to store the current point being checked.
If UsedLocations > 0 Then 'This part will only run if any points have been made
For i = 0 To 19
If Locations(i).Name <> "unused" Then 'only draws points that aren't unused.
If Locations(i).StartPoint = True Then 'only draws light blue outline if the point is selected as the start.
'the -3 on the end is to correct positions.
G.FillEllipse(Brushes.LightBlue, Locations(i).Xcoord - 3, Locations(i).Ycoord - 3, 16, 16)
End If
If Locations(i).Selected = True Then 'only draws the light green outline if the point is currently selected.
G.FillEllipse(Brushes.LightGreen, Locations(i).Xcoord - 3, Locations(i).Ycoord - 3, 16, 16)
End If
G.FillEllipse(Brushes.Black, Locations(i).Xcoord, Locations(i).Ycoord, 10, 10)
End If
Next
For i = 0 To UsedConnections - 1
'draws connections
If Connections(i).PartOfSolution = True Then
G.DrawLine(Pens.Red, Locations(Connections(i).PointOne).Xcoord + 5, Locations(Connections(i).PointOne).Ycoord + 5, Locations(Connections(i).PointTwo).Xcoord + 5, Locations(Connections(i).PointTwo).Ycoord + 5)
Else
G.DrawLine(Pens.Black, Locations(Connections(i).PointOne).Xcoord + 5, Locations(Connections(i).PointOne).Ycoord + 5, Locations(Connections(i).PointTwo).Xcoord + 5, Locations(Connections(i).PointTwo).Ycoord + 5)
End If
Next
'creating labels
Controls.Clear()
Dim NumberToMake As Integer = (39 + UsedConnections)
Dim infolabels(NumberToMake) As Label
For i = 0 To NumberToMake
infolabels(i) = New Label
infolabels(i).Height = 13
infolabels(i).BackColor = Color.Red
If i < 20 Then
infolabels(i).Text = Locations(i).Name
infolabels(i).Top = Locations(i).Ycoord - 15
infolabels(i).Left = Locations(i).Xcoord
If Locations(i).Name <> "unused" Then
Me.Controls.Add(infolabels(i))
End If
ElseIf i > 19 And i < 40 Then
'dijkstra labels
Else
Console.WriteLine(i)
Console.WriteLine(Connections(i - 40).Length)
infolabels(i).Text = CStr(Connections(i - 40).Length)
infolabels(i).Top = 0
infolabels(i).Top = (Locations(Connections(i - 40).PointOne).Ycoord + Locations(Connections(i - 40).PointTwo).Ycoord) * 0.5
'infolabels(i).Left = (Locations(Connections(i - 40).PointOne).Xcoord + Locations(Connections(i - 40).PointTwo).Xcoord) * 0.5
Me.Controls.Add(infolabels(i))
End If
infolabels(i).Width = infolabels(i).Text.Length * 15
Next
End If
End Sub
So while trying to add labels to a form to display information above points & connections, i found that they were covering them. I've already set width & height to proper conenctions, without changing anything.
I've tried setting the backcolour to red to find the problem, that did nothing.
After playing with the background colour of the form, I've found that the label has some white part added on to the sides (as pictured above), and i can't find any way to control it so that it doesn't cover up the draw objects.
Thanks in advance for help.
Edit: after investigating a little more, it seems the white space is the space the labels would normally take up before i resize them.
I had to resize the labels before adding controls to the form, like so:
If i < 20 Then
infolabels(i).Text = Locations(i).Name
infolabels(i).Top = Locations(i).Ycoord - 15
infolabels(i).Left = Locations(i).Xcoord
If Locations(i).Name <> "unused" Then
infolabels(i).Width = infolabels(i).Text.Length * 10
Me.Controls.Add(infolabels(i))
End If
ElseIf i > 19 And i < 40 Then
'dijkstra labels
Else
Console.WriteLine(i)
Console.WriteLine(Connections(i - 40).Length)
infolabels(i).Text = CStr(Connections(i - 40).Length)
'infolabels(i).Top = 0
infolabels(i).Top = (Locations(Connections(i - 40).PointOne).Ycoord + Locations(Connections(i - 40).PointTwo).Ycoord) * 0.5
infolabels(i).Left = (Locations(Connections(i - 40).PointOne).Xcoord + Locations(Connections(i - 40).PointTwo).Xcoord) * 0.5
infolabels(i).Width = infolabels(i).Text.Length * 10
Me.Controls.Add(infolabels(i))
End If

Drawing clickable boxes in VB.net

I am currently making a Chess game as a side project, but i'm struggling to figure out how to make the different tiles clickable. Searching only yielded a C# answer which didn't work.
I've used the creategraphics command to draw on my form, if that's of any help.
Sub DrawBoard()
Dim Board As Graphics = Me.CreateGraphics
Dim BlackPen As New Pen(Color.Black, 3)
Board.Clear(Color.White)
For i = 0 To 3
For j = 0 To 6 Step 2
Board.FillRectangle(Brushes.Gray, j * 60, 120 * i, 60, 60)
Next
For j = 1 To 7 Step 2
Board.FillRectangle(Brushes.Gray, j * 60, (120 * i) + 60, 60, 60)
Next
Next
For i = 0 To 7
For f = 0 To 7
Board.DrawRectangle(BlackPen, i * 60, (f * 60), 60, 60)
Next
Next
BlackPen.Dispose()
End Sub
This is the code I'm using to draw the chess board at the moment.

.net equivalent to form.print

I am attempting to upgrade some old vb6 projects to .net. My plan is to use the vs2005 upgrade wizard, to get to .net 2.0, fix all the bugs and then move up to vs2008, etc. One of my projects allows users to format data, on the fly, by changing x and y positions, view the new output on a form and if they like what they see, print the database to a printer with the new format.
I am having a problem with some "form properites", namely .CurrentX, .CurrentY and .Print.
In vb6 we were able to use the me.CurrentX, me.CurrentY and me.Print to format and print directly onto the form. How is this done in .net
Code example:
xpos = txtStartLeft
YPos = txtStartTop
'center and print Name
xpos = (WW - Me.TextWidth(rs!name)) / 2
Me.CurrentY = YPos
Me.CurrentX = xpos
Me.Print rs!name
YPos = YPos + LineSize
If IsNull(rs!Desc1) = True Then Exit Sub
'format and print Desc1
'left(temp,11) are for formatting purposes only
Temp = rs!Desc1
Me.Font.Bold = Mid(Temp, 9, 1)
Me.Font.Italic = Mid(Temp, 10, 1)
Me.Font.Underline = Mid(Temp, 11, 1)
Me.Font.name = cboToFontName.List(CInt(Mid(Temp, 5, 2)))
Me.Font.Size = CInt(Mid(Temp, 7, 2))
If Left(Temp, 2) = "C " Then 'Align Center
xpos = (WW - Me.TextWidth(Right(Temp, Len(Temp) - 11))) / 2
ElseIf Left(Temp, 2) = "L " Then 'Align Left
YPos = HH / 3
xpos = txtToStartLeft + 100
End If
Me.CurrentY = YPos
Me.CurrentX = xpos
Me.Print Right(Temp, Len(Temp) - 11)
YPos = YPos + LineSize