GUI doesn't move accordingly - vb.net

i'm trying to display pitch, roll and yaw indications in term of graphic so i build an GUI using user control in visual basic. this is my code for the GUI only.
Private g As Graphics
Private _roll_angle As Double
Public Property roll_angle() As Double
Get
Return _roll_angle
End Get
Set(ByVal value As Double)
_roll_angle = value
Invalidate()
End Set
End Property
Private _pitch_angle As Double
Public Property pitch_angle() As Double
Get
Return _pitch_angle
End Get
Set(ByVal value As Double)
_pitch_angle = value
Invalidate()
End Set
End Property
Private Sub ArtificialHorizon_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Function pitch_to_pix(ByVal pitch As Double) As Integer
Return pitch / 35.0 * Me.Height / 2
'Return pitch / 45.0 * Me.Height / 2
End Function
Private Sub ArtificialHorizon_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
g = e.Graphics
g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
g.Clear(Me.BackColor)
Dim sin As Double = Math.Sin(roll_angle / 180 * 3.14)
g.ResetTransform()
' g.FillRegion(Brushes.White, New Region(New Rectangle(0, 0, Me.Width, Me.Height)))
' rounded rectangle
Dim path As New Drawing2D.GraphicsPath()
Dim r As Single = 50
path.AddArc(0, 0, r, r, 180, 90)
path.AddArc(Me.Width - r, 0, r, r, 270, 90)
path.AddArc(Me.Width - r, Me.Height - r, r, r, 0, 90)
path.AddArc(0, Me.Height - r, r, r, 90, 90)
'path.AddEllipse(0, 0, Me.Width, Me.Height)
path.CloseFigure()
g.SetClip(path)
g.TranslateTransform(Me.Width / 2, Me.Height / 2)
g.RotateTransform(roll_angle)
g.TranslateTransform(0, pitch_to_pix(pitch_angle))
' chocolate
Dim b As New System.Drawing.Drawing2D.LinearGradientBrush(New RectangleF(-Me.Width, 0, Me.Height * 2, Me.Width * 2), Color.FromArgb(255, 219, 140, 21), Color.Brown, Drawing2D.LinearGradientMode.Vertical)
g.FillRectangle(b, New RectangleF(-Me.Width * 2, +1, Me.Height * 4, Me.Width * 4))
g.RotateTransform(180)
' color.aqua
b = New System.Drawing.Drawing2D.LinearGradientBrush(New RectangleF(-Me.Width, -1, Me.Height * 2, Me.Width * 2), Color.FromArgb(255, 28, 134, 186), Color.DarkBlue, Drawing2D.LinearGradientMode.Vertical)
g.FillRectangle(b, New RectangleF(-Me.Width * 2, 0, Me.Height * 4, Me.Width * 4))
g.ResetTransform()
Dim w2 As Single = Me.Width / 2
Dim s As Single = Me.Width / 38
g.TranslateTransform(Me.Width / 2, Me.Height / 2)
g.RotateTransform(45)
g.TranslateTransform(-w2 + s, 0)
g.DrawLine(New Pen(Color.White, 2), 0, 0, s * 2, 0)
g.TranslateTransform(+w2 - s, 0)
g.RotateTransform(15)
g.DrawLine(New Pen(Color.White, 2), -w2 + s, 0, -w2 + s * 2, 0)
g.RotateTransform(15)
g.DrawLine(New Pen(Color.White, 2), -w2 + s, 0, -w2 + s * 2, 0)
g.RotateTransform(15)
g.DrawLine(New Pen(Color.White, 2), -w2 + s, 0, -w2 + s * 3, 0)
'g.DrawString("0°", New System.Drawing.Font("sans-serif", 9), Brushes.White, -w2 + 40, -4)
g.RotateTransform(15)
g.DrawLine(New Pen(Color.White, 2), -w2 + s, 0, -w2 + s * 2, 0)
g.RotateTransform(15)
g.DrawLine(New Pen(Color.White, 2), -w2 + s, 0, -w2 + s * 2, 0)
g.RotateTransform(15)
g.DrawLine(New Pen(Color.White, 2), -w2 + s, 0, -w2 + s * 3, 0)
'g.DrawString("+45°", New System.Drawing.Font("sans-serif", 9), Brushes.White, -w2 + 40, -4)
g.ResetTransform()
Dim length As Single = Me.Width / 4
Dim notch As Single = Me.Width / 30
g.TranslateTransform(Me.Width / 2, Me.Height / 2)
g.DrawLine(New Pen(Color.White, 3), -length + notch * 2, 0, -notch, 0)
g.DrawLine(New Pen(Color.White, 3), notch, 0, length - notch * 2, 0)
g.DrawArc(New Pen(Color.White, 3), -notch, -notch, notch * 2, notch * 2, 180, -180)
g.ResetTransform()
' driehoekje
Dim ww As Single = Me.Width / 38
g.TranslateTransform(Me.Width / 2, Me.Height / 2)
g.RotateTransform(-90 + roll_angle)
path = New Drawing2D.GraphicsPath()
path.AddLine(w2 - ww * 3, 0, w2 - ww * 4, ww)
path.AddLine(w2 - ww * 4, -ww, w2 - ww * 4, ww)
path.AddLine(w2 - ww * 4, -ww, w2 - ww * 3, 0)
g.FillRegion(Brushes.White, New Region(path))
g.DrawLine(New Pen(Color.White, 1), w2 - ww * 3, 0, w2 - ww * 4, ww)
g.DrawLine(New Pen(Color.White, 1), w2 - ww * 4, -ww, w2 - ww * 4, ww)
g.DrawLine(New Pen(Color.White, 1), w2 - ww * 4, -ww, w2 - ww * 3, 0)
g.ResetTransform()
g.ResetClip()
path = New Drawing2D.GraphicsPath()
path.AddPie(New Rectangle(ww * 3, ww * 3, Me.Width - ww * 6, Me.Height - ww * 6), 0, 360)
g.SetClip(path)
g.TranslateTransform(Me.Width / 2, Me.Height / 2)
g.RotateTransform(roll_angle)
g.TranslateTransform(0, pitch_to_pix(pitch_angle))
For i As Integer = -80 To 80 Step 10
drawpitchline(g, i)
Next i
End Sub
Private Sub drawpitchline(ByVal g As Graphics, ByVal pitch As Double)
Dim w As Single = Me.Width / 8
g.DrawLine(Pens.White, -w, pitch_to_pix(-pitch + 5), w, pitch_to_pix(-pitch + 5))
g.DrawLine(Pens.White, -w * 5 / 3, pitch_to_pix(-pitch), w * 5 / 3, pitch_to_pix(-pitch))
g.DrawString(pitch, Me.Font, Brushes.White, -w * 75 / 30, pitch_to_pix(-pitch) - 5)
g.DrawString(pitch, Me.Font, Brushes.White, w * 2, pitch_to_pix(-pitch) - 5)
End Sub
Private Sub drawrollline(ByVal g As Graphics, ByVal a As Single)
Dim w2 As Single = Me.Width / 2
g.RotateTransform(a + 90)
g.TranslateTransform(-w2 + 10, 0)
g.DrawLine(Pens.White, 0, 0, 20, 0)
g.TranslateTransform(10, 5)
g.RotateTransform(-a - 90)
g.DrawString("" & (a) & "°", New System.Drawing.Font("sans-serif", 9), Brushes.White, 0, 0)
g.RotateTransform(+90 + a)
g.TranslateTransform(-10, -5)
g.TranslateTransform(+w2 - 10, 0)
g.RotateTransform(-a - 90)
End Sub
then i added in a button to give some testing readings. code below
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
AH.roll_angle = 45
AH.pitch_angle = 10
End Sub
when the button is clicked, the GUI is supposed to turn/rotate according to the inputs. however, it stays still (btw, code is able to debug thou and the graphic did show up). i believe it's because i did not refer to the AH variable in my painting. can someone pls give me a guide on this?
thanks in advance!

I might have something which can be used, I created this to display azimuth heading of parabolic antenna.
the heading is using simple pen
superimpose on top of circle image
the pen will rotate according to the degree movement
With 3 main functions
DrawAntenna() --> draw the pen/line
FindPointOnCircle() --> find end point of the pen (start point always center of circle)
RotateAntenna() --> this will rotate the pen and updating the image accordingly
call RotateAntenna from your function (e.g. TextChanged), and pass the change angle to RotateAntenna
One key thing is to do a refresh on the image whenever the angle change, this will provide rotate effect.
I suggest making this on a different thread, as not to bogged down your main thread, because usually this data acquisition for the azm/elv/roll will happen continuously.
Down to the code:
Private Function FindPointOnCircle(ByVal originPoint As Point, ByVal radius As Double, ByVal angleDegrees As Double) As Point
Dim x As Double = radius * Math.Cos(Math.PI * angleDegrees / 180.0) + originPoint.X
Dim y As Double = radius * Math.Sin(Math.PI * angleDegrees / 180.0) + originPoint.Y
Return New Point(x, y)
End Function
Private Sub DrawAntenna(ByVal originPoint As Point, ByVal endPoint As Point, ByVal g As Graphics, Optional ByVal aPen As Pen = Nothing)
If aPen Is Nothing Then
Using BluePen = New Pen(Color.Blue)
BluePen.Width = 2
g.DrawLine(BluePen, originPoint.X, originPoint.Y, endPoint.X, endPoint.Y)
End Using
Else
g.DrawLine(aPen, originPoint.X, originPoint.Y, endPoint.X, endPoint.Y)
End If
End Sub
Private Sub RotateAntenna(ByVal ang As Double, ByVal g As Graphics, ByVal typeOfDisplay As Integer)
' Radius of 95% of half the width of the panel
Dim radius As Double = (Me.picDestTop.Width / 2) * 0.95
' Origin half of width and height of panel
Dim origin As New Point(Me.picDestTop.Width / 2, Me.picDestTop.Height / 2)
Select Case typeOfDisplay
Case displayAntenna.DisplayTop
'rotate start at 270deg, pointing up
Dim antennaDegrees As Double = ang + 170
'find point
Dim secondsPoint As Point = FindPointOnCircle(origin, radius, antennaDegrees)
Using p As New Pen(Color.Red)
p.Width = 5
DrawAntenna(origin, secondsPoint, g, p)
End Using
Case displayAntenna.DisplaySide
'display elevation
Case displayAntenna.DisplayRoll
'display pitch
End Select
g.Dispose()
End Sub
'azimuth
Private Sub lblEncCurrent_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lblEncCurrent.TextChanged
Dim iint As Double
Me.picDestTop.Refresh()
iint = CDbl(lblEncCurrent.Text)
If iint >= 360 Then
iint = iint - 360
End If
RotateAntenna(iint, Me.picDestTop.CreateGraphics, displayAntenna.DisplayTop)
End Sub
Hope this help!!. Thanks.

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!

Graphing from a table VB

I am trying to graph from a table called totals(). The program itself is working okay, but i am having some issues. First, for each button press, it is adding the values and regraphing them. I do not want them to add to the previous values, i want them to overwrite the values.
Dim d1, d2, d3 As Single
Dim dieSumInt As Integer
Dim totals(17) as integer
For ptr = 1 To 10000
d1 = (Int((Rnd() * 6) + 1))
d2 = (Int((Rnd() * 6) + 1))
d3 = (Int((Rnd() * 6) + 1))
dieSumInt = CInt((d1 + d2 + d3))
totals(dieSumInt) += 1
Next
The whole code i have here, is supposed to take the sum of 3 dice and graph the totals into a picture box. I have all the graphing down, but each time i hit the "roll" button it keeps adding to the previous values. Im not sure how to clear out the values, to get a consistent value being graphed.
Dim totals(18) As Integer
Dim dashPen As New Pen(Color.Black, 1)
Public Function Max(ByVal arry() As Integer) As Integer
Max = arry(0)
For ptr As Integer = 0 To UBound(arry)
If arry(ptr) > Max Then Max = arry(ptr)
Next
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Randomize(DateAndTime.Timer)
End Sub
Private Sub rollButton_Click(sender As Object, e As EventArgs) Handles RollButton.Click
Dim d1, d2, d3 As Single
Dim dieSumInt As Integer
For ptr = 1 To 10000
d1 = (Int((Rnd() * 6) + 1))
d2 = (Int((Rnd() * 6) + 1))
d3 = (Int((Rnd() * 6) + 1))
dieSumInt = CInt((d1 + d2 + d3))
totals(dieSumInt) += 1
Next
Call Plot(totals)
Call LabelGraph(totals)
End Sub
Private Sub Plot(ByVal arry() As Integer)
Dim plotColor As Color
plotColor = Color.SkyBlue
Dim plotPen As New Pen(plotColor, 5)
Dim graph As Graphics = displayBox.CreateGraphics
Dim ymax, ptr As Integer
Dim xscale, yscale, x1, y1, Dwidth, Dheight As Single
Dim myfont As New Font("courier new", 5 + (displayBox.Width \ 100))
Dim percentArry(4) As Integer
Dwidth = displayBox.Width - 50
Dheight = displayBox.Height - 100
ymax = Max(arry)
displayBox.Refresh()
yscale = CSng(Dheight / ymax)
xscale = CSng(Dwidth / 17)
Dwidth = displayBox.Width - 50
Dheight = displayBox.Height - 70
For ptr = 0 To 4
percentArry(ptr) = CInt(arry.Max * (ptr + 1) * 0.2)
y1 = Dheight - CInt((arry.Max * (ptr + 1) / 5) * yscale)
graph.DrawLine(dashPen, displayBox.Left - 25, y1 + 4, displayBox.Right - 25, y1 + 4)
dashPen.DashStyle = Drawing2D.DashStyle.DashDotDot
graph.DrawString(CStr(percentArry(ptr)), myfont, Brushes.LightSlateGray, 'marking the sides
CSng(displayBox.Left - 10),
y1 + 3)
Next
For ptr = 3 To 18
x1 = (ptr - 2) * xscale
y1 = Dheight - (arry(ptr) * yscale)
graph.DrawRectangle(plotPen, x1 + 30, y1 + 4, xscale - 10, Dheight - y1) 'adjusting the size of the graph rectangles
Next
End Sub
Private Sub LabelGraph(ByVal arry() As Integer)
Dim graph As Graphics = displayBox.CreateGraphics
Dim myfont As New Font("courier new", 5 + (displayBox.Width \ 100))
For ptr As Integer = 1 To 16
graph.DrawString(CStr(ptr + 2), myfont, Brushes.LightSlateGray,
CSng(((displayBox.Width / 17) * ptr + 5) - (ptr * 3) + displayBox.Width / 35),
displayBox.Height - 60)
graph.DrawString(CStr(arry(ptr + 2)), myfont, Brushes.LightSlateGray,
CSng(((displayBox.Width / 17) * ptr) - (ptr * 3) + displayBox.Width / 28),
displayBox.Height - 30)
Next
End Sub
Private Sub exitButton_Click(sender As Object, e As EventArgs) Handles exitButton.Click
Me.Close()
End Sub
Private Sub Form1_ResizeEnd(sender As Object, e As EventArgs) Handles Me.ResizeEnd
Plot(totals)
LabelGraph(totals)
End Sub

How can I remove corners from a Button?

I'm trying to remove corners that are not included in the button border.
I draw my button border with this method:
Private Sub BTN_Connexion_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles BTN_Connexion.Paint
Me.DrawRectangle(e.Graphics, New Pen(Color.White), 0, 0, BTN_Connexion.Width - 1, BTN_Connexion.Height - 1, 10)
End Sub
Public Sub DrawRectangle(ByVal g As Graphics, ByVal pen As Pen, ByVal x As Int32, ByVal y As Int32, ByVal width As Int32, ByVal height As Int32, ByVal radius As Int32)
'Create a rectangle
Dim area As RectangleF = New RectangleF(x, y, width, height)
Dim path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath
'Add the corners
path.AddArc(area.Left, area.Top, radius * 2, radius * 2, 180, 90) 'Upper-Left
path.AddArc(area.Right - (radius * 2), area.Top, radius * 2, radius * 2, 270, 90) 'Upper-Right
path.AddArc(area.Right - (radius * 2), area.Bottom - (radius * 2), radius * 2, radius * 2, 0, 90) 'Lower-Right
path.AddArc(area.Left, area.Bottom - (radius * 2), radius * 2, radius * 2, 90, 90) 'Lower-Left
path.CloseAllFigures()
'Draw the rounded rectangle
g.DrawPath(pen, path)
End Sub
Corners can take the main form color. Like this they would not appear on the button. But I don't know if it's good practice and more I didn't know how to do this.
So could you tell me how can I remove these corners?
I have resolved my problem, here is the solution:
In the form that you want to implement your rounded button do:
Private Sub BTN_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles BTN_Connect.Paint, BTN_Disconnect.Paint
DirectCast(sender, Button).Region = New Region(SpecificDesign.DrawRoundRectangle(0, 0, BTN_Connect.Width - 1, BTN_Connect.Height - 1, 10))
End Sub
The class SpecificDesign contains:
Public Class SpecificDesign
''' <summary>
''' Create the path of a rounded rectangle.
''' </summary>
''' <param name="left">Ordinate of the left top corner</param>
''' <param name="Top">Abscissa of the left top corner</param>
''' <param name="width">Width of the rounded rectangle (Left and right lines)</param>
''' <param name="height">Height of the rounded rectangle(Top and bottom lines)</param>
''' <param name="radius">Radius of the rounded corner </param>
''' <returns></returns>
Public Shared Function DrawRoundRectangle(ByVal left As Int32, ByVal Top As Int32, ByVal width As Int32, ByVal height As Int32, ByVal radius As Int32) As Drawing2D.GraphicsPath
Dim path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath
path.AddArc(left, Top, radius * 2, radius * 2, 180, 90) 'Upper-Left
path.AddArc(left + width - (radius * 2), Top, radius * 2, radius * 2, 270, 90) 'Upper-Right
path.AddArc(left + width - (radius * 2), Top + height - (radius * 2), radius * 2, radius * 2, 0, 90) 'Lower-Right
path.AddArc(left, Top + height - (radius * 2), radius * 2, radius * 2, 90, 90) 'Lower-Left
path.CloseAllFigures()
Return path
End Function
End Class

Draw rectangle in circle with remains colored in different colours

I need to draw a circle in which I must place a square with corners touching circle line.
After that, four part that remains must be colored with different colors.
Colors of square is not important.
Try something like this out:
Public Class Form1
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
Dim radius As Integer = 100
Dim center As New Point(125, 125)
Dim Y As Integer = radius * Math.Sin(45 * Math.PI / 180)
Dim X As Integer = radius * Math.Cos(45 * Math.PI / 180)
Dim centerRC As New Rectangle(center.X - X, center.Y - Y, X * 2, Y * 2)
Dim ellipseRC As New Rectangle(center.X - radius, center.Y - radius, radius * 2, radius * 2)
e.Graphics.ExcludeClip(centerRC)
e.Graphics.FillPie(Brushes.Red, ellipseRC, 225, 90)
e.Graphics.FillPie(Brushes.Green, ellipseRC, -45, 90)
e.Graphics.FillPie(Brushes.Blue, ellipseRC, 45, 90)
e.Graphics.FillPie(Brushes.White, ellipseRC, 135, 90)
End Sub
End Class
Result:

3 way check box (toggle)

I have a custom 'toggle' (using ButterscotchTheme) and I am trying to add a 3rd option.
This is how it currently is: (cant post pictures due to being new, but here is links to the pictures)
I would like a third option. I have checked the theme code and it is done by Checkbox rules. And I know a Tricheckbox is a thing, I am just unsure how to get it to work. I did some research and was unable to figure it out in this situation.
Here is all the Themes toggle code:
Public Class ButterscotchToggle : Inherits Control
Private _check As Boolean
Public Property Checked As Boolean
Get
Return _check
End Get
Set(ByVal value As Boolean)
_check = value
Invalidate()
End Set
End Property
Sub New()
MyBase.New()
SetStyle(ControlStyles.UserPaint Or ControlStyles.ResizeRedraw Or ControlStyles.SupportsTransparentBackColor, True)
DoubleBuffered = True
BackColor = Color.Transparent
Size = New Size(80, 25)
End Sub
Protected Overrides Sub OnClick(ByVal e As EventArgs)
Checked = Not Checked
MyBase.OnClick(e)
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
Dim b As Bitmap = New Bitmap(Width, Height)
Dim g As Graphics = Graphics.FromImage(b)
Dim outerrect As Rectangle = New Rectangle(0, 0, Width - 1, Height - 1)
Dim maininnerrect As Rectangle = New Rectangle(7, 7, Width - 15, Height - 15)
Dim buttonrect As New LinearGradientBrush(outerrect, Color.FromArgb(100, 90, 80), Color.FromArgb(48, 43, 39), 90S)
MyBase.OnPaint(e)
g.Clear(BackColor)
g.SmoothingMode = SmoothingMode.HighQuality
g.InterpolationMode = InterpolationMode.HighQualityBicubic
g.FillPath(New SolidBrush(Color.FromArgb(40, 37, 33)), RoundRect(outerrect, 5))
g.DrawPath(New Pen(Color.FromArgb(0, 0, 0)), RoundRect(outerrect, 5))
g.FillPath(New SolidBrush(Color.FromArgb(26, 25, 21)), RoundRect(maininnerrect, 3))
g.DrawPath(New Pen(Color.FromArgb(0, 0, 0)), RoundRect(maininnerrect, 3))
If Checked Then
g.FillPath(buttonrect, RoundRect(New Rectangle(3, 3, CInt((Width / 2) - 3), Height - 7), 7))
g.DrawString("ON", New Font("Segoe UI", 10, FontStyle.Bold), New SolidBrush(Color.FromArgb(246, 180, 12)), New Rectangle(2, 2, CInt((Width / 2) - 1), Height - 5), New StringFormat() With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center})
Else
g.FillPath(buttonrect, RoundRect(New Rectangle(CInt((Width / 2) - 3), 3, CInt((Width / 2) - 3), Height - 7), 7))
g.DrawString("OFF", New Font("Segoe UI", 10, FontStyle.Bold), New SolidBrush(Color.FromArgb(246, 180, 12)), New Rectangle(CInt((Width / 2) - 2), 2, CInt((Width / 2) - 1), Height - 5), New StringFormat() With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center})
End If
e.Graphics.DrawImage(b, New Point(0, 0))
g.Dispose() : b.Dispose()
End Sub
End Class
Any help would be greatly appreciated!
Theme downloaded from Butterscotch Theme GDI+
You would have to change that boolean property to an integer (or even better, create an enum):
Private _check As Integer
Public Property Checked As Integer
Get
Return _check
End Get
Set(ByVal value As Integer)
_check = value
Invalidate()
End Set
End Property
Change the OnClick behavior:
Protected Overrides Sub OnClick(ByVal e As EventArgs)
If Checked + 1 > 2 Then
Checked = 0
Else
Checked += 1
End If
MyBase.OnClick(e)
End Sub
and then adjust the drawing accordingly (placing the third option in the middle I'm guessing):
Select Case Checked
Case 0
g.FillPath(buttonrect, RoundRect(New Rectangle(CInt((Width / 2) - 3), 3, CInt((Width / 2) - 3), Height - 7), 7))
g.DrawString("OFF", New Font("Segoe UI", 10, FontStyle.Bold), New SolidBrush(Color.FromArgb(246, 180, 12)), New Rectangle(CInt((Width / 2) - 2), 2, CInt((Width / 2) - 1), Height - 5), New StringFormat() With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center})
Case 1
g.FillPath(buttonrect, RoundRect(New Rectangle(3, 3, CInt((Width / 2) - 3), Height - 7), 7))
g.DrawString("ON", New Font("Segoe UI", 10, FontStyle.Bold), New SolidBrush(Color.FromArgb(246, 180, 12)), New Rectangle(2, 2, CInt((Width / 2) - 1), Height - 5), New StringFormat() With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center})
Case 2
g.FillPath(buttonrect, RoundRect(New Rectangle((Width / 2) - (Width / 4), 3, CInt((Width / 2) - 3), Height - 7), 7))
g.DrawString("???", New Font("Segoe UI", 10, FontStyle.Bold), New SolidBrush(Color.FromArgb(246, 180, 12)), New Rectangle((Width / 2) - (Width / 4), 2, CInt((Width / 2) - 1), Height - 5), New StringFormat() With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center})
End Select