1

I'm working on a theme for a little app where I need to place some toggle buttons. Like showed in many place this site, I've done it using a checkbox and changing the apparance by a custom onpaint event ,(basically a draw it like a button). Then I realize that checkbox not grouping like radio buttons, so I've done the same with a radio buttons, but even if I place 2 of them in a groupbox, I still can "checked" them both; which is the best way to do that? here sample code that I used to make some test:

Class MyToggleButton
Inherits ThemeControl154
Private _Checked As Boolean
Private X As Integer



Public Property Checked As Boolean
    Get
        Return _Checked
    End Get
    Set(ByVal V As Boolean)
        _Checked = V
        Invalidate()
    End Set
End Property


Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
    MyBase.OnClick(e)
    _Checked = Not _Checked
End Sub

Protected Overrides Sub ColorHook()
    SetColor("Border", Color.FromArgb(255, 200, 200, 200))
End Sub

Protected Overrides Sub PaintHook()
    Dim Border As Color
    Border = Drawing.Color.FromArgb(160, GetColor("Border"))
    G.SmoothingMode = SmoothingMode.AntiAlias
    G.Clear(Drawing.Color.FromArgb(255, 60, 60, 60))

    Dim LGBNone As LinearGradientBrush
    Dim LGBOver As LinearGradientBrush
    Dim LGBDown As LinearGradientBrush

    If Checked Then ' use Blue-ish color
        LGBNone = New LinearGradientBrush(New Point(0, 0), New Point(0, Height - 1), Color.FromArgb(120, 0, 0, 255), Color.FromArgb(255, 25, 50, 255))
        LGBOver = New LinearGradientBrush(New Point(0, 0), New Point(0, Height - 1), Color.FromArgb(120, 0, 0, 255), Color.FromArgb(255, 25, 40, 255))
        LGBDown = New LinearGradientBrush(New Point(0, 0), New Point(0, Height - 1), Color.FromArgb(120, 0, 0, 255), Color.FromArgb(255, 25, 30, 255))
    Else ' use default colors
        LGBNone = New LinearGradientBrush(New Point(0, 0), New Point(0, Height - 1), Color.FromArgb(255, 65, 65, 65), Color.FromArgb(255, 50, 50, 50))
        LGBOver = New LinearGradientBrush(New Point(0, 0), New Point(0, Height - 1), Color.FromArgb(255, 65, 65, 65), Color.FromArgb(255, 40, 40, 40))
        LGBDown = New LinearGradientBrush(New Point(0, 0), New Point(0, Height - 1), Color.FromArgb(255, 65, 65, 65), Color.FromArgb(255, 30, 30, 30))
    End If

    Dim Polygon() As Point
    Dim Polygon2() As Point
    Polygon = New Point() {New Point(0, 0), New Point(Width - 1, 0), New Point(Width - 1, Height - 7), New Point(Width - 2, Height - 6), New Point(Width - 3, Height - 5), New Point(Width - 4, Height - 4), New Point(Width - 5, Height - 3), New Point(Width - 6, Height - 2), New Point(Width - 7, Height - 1), New Point(0, Height - 1)}
    Polygon2 = New Point() {New Point(1, 1), New Point(Width - 2, 1), New Point(Width - 2, Height - 7), New Point(Width - 8, Height - 2), New Point(1, Height - 2)}
    Select Case State
        Case MouseState.Down
            G.FillPolygon(LGBDown, Polygon)
        Case MouseState.None
            G.FillPolygon(LGBNone, Polygon)
        Case MouseState.Over
            G.FillPolygon(LGBOver, Polygon)
    End Select
    G.DrawPolygon(Pens.Black, Polygon)
    G.DrawPolygon(New Pen(Border), Polygon2)
    DrawText(New SolidBrush(GetColor("Border")), HorizontalAlignment.Center, -2, 0)
End Sub

End Class

  • 1
    That's not the normal behavior of a RadioButton. So, it must be something with your code (which you didn't include). Anyway, I think you'll like [this answer](https://stackoverflow.com/a/38432140/8967612). The code is in C# but can be easily translated (or compiled into a DLL as is). – 41686d6564 stands w. Palestine Jun 12 '21 at 19:15
  • As long as the `RadioButton`s belong to the same parent, then they will automatically toggle. If each `RadioButton` has a different parent then it won't toggle. – Loathing Jun 12 '21 at 19:19
  • Note, however, that toggle switches usually substitute CheckBoxes, not RadioButtons. So, having a toggle affects the state of others might be an unexpected behavior to the user. What's exactly do you not like about the universally recognized RadioButton? – 41686d6564 stands w. Palestine Jun 12 '21 at 19:24
  • basically Radiobuttons work for my goal but I prefer button apparance. –  Jun 12 '21 at 19:49
  • @Damien Did you try the `RadioButton.Appearance` property? E.g., `RadioButton1.Appearance = Appearance.Button`. – 41686d6564 stands w. Palestine Jun 12 '21 at 21:27
  • Tried, and work, but lose the customization. –  Jun 13 '21 at 06:27

1 Answers1

0

Yes you can imitate the behavior of a group of RadioButton controls in a container. Just find the controls of the same type in the Parent.Controls collection and uncheck them when the current instance is checked.

Example

Add this method to MyToggleButton class.

Private Sub InvalidateControls()
    If Not IsHandleCreated OrElse Not Checked Then Return

    For Each c In Parent.Controls.OfType(Of MyToggleButton)
        If c IsNot Me AndAlso c.Checked Then
            c.Checked = False
        End If
    Next
End Sub

Call the method from the setter of the Checked property:

Private _Checked As Boolean

Public Property Checked As Boolean
    Get
        Return _Checked
    End Get
    Set(ByVal V As Boolean)
        _Checked = V
        InvalidateControls()
        Invalidate()
    End Set
End Property

In the OnClick method, you shouldn't toggle the Checked property, its a RadioButton not a CheckBox. You should:

Protected Overrides Sub OnClick(ByVal e As EventArgs)
    MyBase.OnClick(e)

    ' Set the property not the variable to call the 
    ' setter's methods.
    If Not Checked Then Checked = True
End Sub

Also, it's important to dispose of the graphics objects when you finish drawing. You should call LGBNone.Dispose(), LGBDown.Dispose(), and LGBOver.Dispose() at the end of the PaintHook method.

dr.null
  • 4,032
  • 3
  • 9
  • 12