Looking for specific label properties in VB.net - 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

Related

How to solve ArgumentException : The parameter is not valid for drawing Arcs

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!

Remove Large Spacing on a Graph Visual Basic

I am working on a program and one feature is to show a graph of accrued points by game. I have successfully created the graph but cannot work out how to get rid of the big gaps at either side. I have tried reducing padding and margins to 0 but to no avail. Any help would be greatly appreciated. :)
Image of graph:
Chart1.Series.Clear()
Chart1.Titles.Clear()
Chart1.ChartAreas.Clear()
Chart1.Show()
Chart1.AlignDataPointsByAxisLabel()
Chart1.Titles.Add(names(search))
Chart1.ChartAreas.Add("Default")
With Chart1.ChartAreas("Default")
.AxisX.Interval() = 5
.AxisY.Interval() = 1
.AxisY.Title = "Number of Wins"
.AxisX.Title = "Game"
.AxisX.CustomLabels.Add(0, 60, "low")
End With
Chart1.SetBounds(270, 200, 510, 250)
Dim ref As Integer = 0
For Each item As DictionaryEntry In gamespoints
If item.Value > 0 Then
ref = ref + 1
Chart1.Series.Add(item.Key)
If item.Value = max And ref Mod 2 = 0 Then
Chart1.Series(item.Key).Color = Color.Green
ElseIf item.Value = max Then
Chart1.Series(item.Key).Color = Color.LimeGreen
ElseIf ref Mod 2 = 0 Then
Chart1.Series(item.Key).Color = Color.Black
Else
Chart1.Series(item.Key).Color = Color.DarkGray
End If
Chart1.Series(item.Key).Points.AddXY(0, item.Value)
End If
Next

There must be a way to refresh the PowerPoint (2016) screen without DoEvents, GotoSlide, or .AddShape

My program constantly updates a shape's position, based on another manipulable shape. Without DoEvents, GotoSlide, .AddShape, or increasing slideshowwindow, the screen will not refresh, and will only show the end result of the shape's position. I can't use DoEvents because it slows down too much when the mouse is moved, and I can't use GotoSlide, .AddShape, or similar methods because they don't allow the user to click in the PowerPoint (will either ignore or crash the program).
Please note, the workarounds here How to refresh the active Slide in a slide show? cause the problems I noted above (.AddShape, GotoSlide, and increasing slideshowwindow all crash the program if the mouse clicks)
I have experimented with GetQueueStaus and GetInputState as a means to filter out certain events from DoEvents, but neither seem to apply. And using them to only DoEvents when necessary obviously isn't an option because it will always be necessary when the shape is moving, and the movement will always slow down based on mouse movement during DoEvents.
Finally, I have also experimented with charts because they are the only shape in PowerPoint that has .refresh functionality, but I both was unable to get this to work, and decided that it wasn't worth the time because the shape of the chart will always be restricted to a rectangle (too limited for what I want my program to do).
Here is my code: (I am currently using GotoSlide method)
Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Sub Aloop()
Dim Q As Shape
Dim B As Shape
Dim TotalTime As Long
Dim StartTime As Long
Dim TimerTextRange As TextRange
Dim A As Shape
Const PI = 3.14159265359
Set A = ActivePresentation.Slides(1).Shapes("A")
Set SldOne = ActivePresentation.Slides(1)
Set Q = ActivePresentation.Slides(1).Shapes("Q")
Set B = ActivePresentation.Slides(1).Shapes("B")
Set TimerTextRange = ActivePresentation.Slides(1).Shapes("TimerTextRange") _
.TextFrame.TextRange
TotalTime = 0
StartTime = Timer
With TimerTextRange
.Text = Int(TotalTime + (Timer - StartTime))
End With
Do While TimerTextRange.Text < 10
With TimerTextRange
.Text = Int(TotalTime + (Timer - StartTime))
End With
If Q.Left < A.Left Then
Q.Left = Q.Left + 1
ElseIf Q.Left > A.Left Then
Q.Left = Q.Left - 1
Else
End If
If Q.Top < A.Top Then
Q.Top = Q.Top + 1
ElseIf Q.Top > A.Top Then
Q.Top = Q.Top - 1
Else
End If
If GetAsyncKeyState(vbKeyD) Then
A.Left = A.Left + 4
Else
End If
If GetAsyncKeyState(vbKeyW) Then
A.Top = A.Top - 4
Else
End If
If GetAsyncKeyState(vbKeyS) Then
A.Top = A.Top + 4
Else
End If
If GetAsyncKeyState(vbKeyA) Then
A.Left = A.Left - 4
Else
End If
With Q
If (-A.Top + (.Top + .Width / 2)) > 0 Then
.Rotation = ((Atn(((A.Left + A.Width / 2) - ((.Left + .Width / 2))) / (-(A.Top + A.Height / 2) + ((.Top + .Width / 2))))) * 180 / PI)
ElseIf (-A.Top + (.Top + .Width / 2)) < 0 Then
.Rotation = ((Atn(((A.Left + A.Width / 2) - ((.Left + .Width / 2))) / (-(A.Top + A.Height / 2) + ((.Top + .Width / 2))))) * 180 / PI) + 180
Else
End If
End With
ActivePresentation.SlideShowWindow.View.GotoSlide (1)
Loop
End Sub
The code makes shape Q follow shape A around the screen, and the user can control shape a with W A S D keyboard inputs.
!!Be careful not to click the slide while the code is running, or the program will crash!!

Dynamic checkbox events through commandbutton

I am currently programming a sheet which visualizes data sets in graphs. Because the user of this sheet will not need all the graphs, I would like to let them choose the ones needed through a UserForm. Since the amount of data sets is variable, the UserForm will have the same amount of checkboxes as there are datasets.
The Userform code is as follows.
Private Sub UserForm_Initialize()
Dim chkBoxA As MSForms.CheckBox
Dim chkBoxB As MSForms.CheckBox
Dim lblBox As MSForms.Label
Dim cnt As Control
Amount = Sheet4.Range("C4").Value 'Amount of datasets
For i = 1 To Amount
Set lblBox = Me.Controls.Add("Forms.label.1", "Label" & i)
lblBox.Caption = "Set" & i
lblBox.Left = 5
lblBox.Top = 8 + ((i - 1) * 40)
Set chkBoxA = Me.Controls.Add("Forms.CheckBox.1", "A" & i)
chkBoxA.Caption = "Graph a"
chkBoxA.Left = 55
chkBoxA.Top = 5 + ((i - 1) * 40)
Set chkBoxB = Me.Controls.Add("Forms.CheckBox.1", "B" & i)
chkBoxB.Caption = "Graph b"
chkBoxB.Left = 55
chkBoxB.Top = 20 + ((i - 1) * 40)
Next
CommandButton1.Left = 20
CommandButton1.Top = 40 + ((Amount - 1) * 40)
CommandButton1.TabIndex = Amount * 3 + 1
Me.Height = 220
Me.ScrollBars = fmScrollBarsVertical
Me.ScrollWidth = Me.InsideWidth * 9
For Each cnt In Me.Controls
If cnt.Top + cnt.Height > Me.ScrollHeight Then
Me.ScrollHeight = cnt.Top + cnt.Height + 5
End If
Next
End Sub
When the UserForm is filled in (graphs are chosen by clicking on the options), the user will press CommandButton1. An event should then be run to show the correct graph, but for the simplicity I am first testing if a MsgBox will show up. Unfortunately the MsgBox does not show up.
Private Sub CommandButton1_Click()
'Will fix this with a loop
If A1 = True Then
MsgBox ("TestA1")
End If
If B1 = True then
MsgBox ("TestB1")
End If
If A2 = True then
MsgBox ("TestA2")
End If
Unload Me
End Sub
I am stuck on this part. The checkboxes do show up on the UserForm and they are clickable, but the commandbutton only shuts down the sub (Unload Me). I would like to see the MsgBox show up when I select the corresponding option and click the commandbutton. Any help on getting this to work is appreciated!
You are referencing 'A1' in the sub, but that variable does not exitst at compile time, because you add them dynamically. What you need to do is loop the controls, to check the names. Best practice is to put the checkboxes in a frame, to be able to group them.
Add a frame to the userform and name it 'checkboxframe'
And then instead of:
For i = 1 To Amount
Set lblBox = Me.Controls.Add("Forms.label.1", "Label" & i)
lblBox.Caption = "Set" & i
lblBox.Left = 5
lblBox.Top = 8 + ((i - 1) * 40)
Set chkBoxA = Me.Controls.Add("Forms.CheckBox.1", "A" & i)
chkBoxA.Caption = "Graph a"
chkBoxA.Left = 55
chkBoxA.Top = 5 + ((i - 1) * 40)
Set chkBoxB = Me.Controls.Add("Forms.CheckBox.1", "B" & i)
chkBoxB.Caption = "Graph b"
chkBoxB.Left = 55
chkBoxB.Top = 20 + ((i - 1) * 40)
Next
you would need to do:
With Me.checkboxframe
For i = 1 To Amount
Set lblBox = .Controls.Add("Forms.label.1", "Label" & i)
lblBox.Caption = "Set" & i
lblBox.Left = 5
lblBox.Top = 8 + ((i - 1) * 40)
Set chkBoxA = .Controls.Add("Forms.CheckBox.1", "A" & i)
chkBoxA.Caption = "Graph a"
chkBoxA.Left = 55
chkBoxA.Top = 5 + ((i - 1) * 40)
Set chkBoxB = .Controls.Add("Forms.CheckBox.1", "B" & i)
chkBoxB.Caption = "Graph b"
chkBoxB.Left = 55
chkBoxB.Top = 20 + ((i - 1) * 40)
Next
End With
And to add the checkboxes to the frame, use something like:
For Each ctr In UserForm1.frame("checkboxframe").Controls
If TypeName(ctr) = "CheckBox" Then
If ctr.Value = True Then
'do something usefull here
msgbox ctr.name
End If
End If
Next ctr
The reason nothing appears is because there is no object "A1" manually defined as a variable.
To get the value of the box you Dynamically named "A1" you would have to refer to it as such:
If Me.Controls.Item("A1").Value = True then
Hope this helps!

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.