Note

Access to this page requires authorization. You can try signing in or .

Access to this page requires authorization. You can try .

How to: Display Option Buttons in a MenuStrip (Windows Forms)

Option buttons, also known as radio buttons, are similar to check boxes except that users can select only one at a time. Although by default the ToolStripMenuItem class does not provide option-button behavior, the class does provide check-box behavior that you can customize to implement option-button behavior for menu items in a MenuStrip control.

When the CheckOnClick property of a menu item is true, users can click the item to toggle the display of a check mark. The Checked property indicates the current state of the item. To implement basic option-button behavior, you must ensure that when an item is selected, you set the Checked property for the previously selected item to false.

The following procedures describe how to implement this and additional functionality in a class that inherits the ToolStripMenuItem class. The ToolStripRadioButtonMenuItem class overrides members such as OnCheckedChanged and OnPaint to provide the selection behavior and appearance of option buttons. Additionally, this class overrides the Enabled property so that options on a submenu are disabled unless the parent item is selected.

To implement option-button selection behavior

  1. Initialize the CheckOnClick property to true to enable item selection.

    // Called by all constructors to initialize CheckOnClick.
    private void Initialize()
    {
     CheckOnClick = true;
    }
    
    ' Called by all constructors to initialize CheckOnClick.
    Private Sub Initialize()
     CheckOnClick = True
    End Sub
    
  2. Override the OnCheckedChanged method to clear the selection of the previously selected item when a new item is selected.

    protected override void OnCheckedChanged(EventArgs e)
    {
     base.OnCheckedChanged(e);
    
     // If this item is no longer in the checked state or if its
     // parent has not yet been initialized, do nothing.
     if (!Checked || this.Parent == null) return;
    
     // Clear the checked state for all siblings.
     foreach (ToolStripItem item in Parent.Items)
     {
     ToolStripRadioButtonMenuItem radioItem =
     item as ToolStripRadioButtonMenuItem;
     if (radioItem != null && radioItem != this && radioItem.Checked)
     {
     radioItem.Checked = false;
    
     // Only one item can be selected at a time,
     // so there is no need to continue.
     return;
     }
     }
    }
    
    Protected Overrides Sub OnCheckedChanged(ByVal e As EventArgs)
    
     MyBase.OnCheckedChanged(e)
    
     ' If this item is no longer in the checked state or if its 
     ' parent has not yet been initialized, do nothing.
     If Not Checked OrElse Me.Parent Is Nothing Then Return
    
     ' Clear the checked state for all siblings. 
     For Each item As ToolStripItem In Parent.Items
    
     Dim radioItem As ToolStripRadioButtonMenuItem = _
     TryCast(item, ToolStripRadioButtonMenuItem)
     If radioItem IsNot Nothing AndAlso _
     radioItem IsNot Me AndAlso _
     radioItem.Checked Then
    
     radioItem.Checked = False
    
     ' Only one item can be selected at a time, 
     ' so there is no need to continue.
     Return
    
     End If
     Next
    
    End Sub
    
  3. Override the OnClick method to ensure that clicking an item that has already been selected will not clear the selection.

    protected override void OnClick(EventArgs e)
    {
     // If the item is already in the checked state, do not call
     // the base method, which would toggle the value.
     if (Checked) return;
    
     base.OnClick(e);
    }
    
    Protected Overrides Sub OnClick(ByVal e As EventArgs)
    
     ' If the item is already in the checked state, do not call 
     ' the base method, which would toggle the value. 
     If Checked Then Return
    
     MyBase.OnClick(e)
    End Sub
    

To modify the appearance of the option-button items

  1. Override the OnPaint method to replace the default check-mark with an option button by using the RadioButtonRenderer class.

    // Let the item paint itself, and then paint the RadioButton
    // where the check mark is normally displayed.
    protected override void OnPaint(PaintEventArgs e)
    {
     if (Image != null)
     {
     // If the client sets the Image property, the selection behavior
     // remains unchanged, but the RadioButton is not displayed and the
     // selection is indicated only by the selection rectangle.
     base.OnPaint(e);
     return;
     }
     else
     {
     // If the Image property is not set, call the base OnPaint method
     // with the CheckState property temporarily cleared to prevent
     // the check mark from being painted.
     CheckState currentState = this.CheckState;
     this.CheckState = CheckState.Unchecked;
     base.OnPaint(e);
     this.CheckState = currentState;
     }
    
     // Determine the correct state of the RadioButton.
     RadioButtonState buttonState = RadioButtonState.UncheckedNormal;
     if (Enabled)
     {
     if (mouseDownState)
     {
     if (Checked) buttonState = RadioButtonState.CheckedPressed;
     else buttonState = RadioButtonState.UncheckedPressed;
     }
     else if (mouseHoverState)
     {
     if (Checked) buttonState = RadioButtonState.CheckedHot;
     else buttonState = RadioButtonState.UncheckedHot;
     }
     else
     {
     if (Checked) buttonState = RadioButtonState.CheckedNormal;
     }
     }
     else
     {
     if (Checked) buttonState = RadioButtonState.CheckedDisabled;
     else buttonState = RadioButtonState.UncheckedDisabled;
     }
    
     // Calculate the position at which to display the RadioButton.
     Int32 offset = (ContentRectangle.Height -
     RadioButtonRenderer.GetGlyphSize(
     e.Graphics, buttonState).Height) / 2;
     Point imageLocation = new Point(
     ContentRectangle.Location.X + 4,
     ContentRectangle.Location.Y + offset);
    
     // Paint the RadioButton.
     RadioButtonRenderer.DrawRadioButton(
     e.Graphics, imageLocation, buttonState);
    }
    
    ' Let the item paint itself, and then paint the RadioButton
    ' where the check mark is normally displayed.
    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    
     If Image IsNot Nothing Then
     ' If the client sets the Image property, the selection behavior
     ' remains unchanged, but the RadioButton is not displayed and the
     ' selection is indicated only by the selection rectangle. 
     MyBase.OnPaint(e)
     Return
     Else
     ' If the Image property is not set, call the base OnPaint method 
     ' with the CheckState property temporarily cleared to prevent
     ' the check mark from being painted.
     Dim currentState As CheckState = Me.CheckState
     Me.CheckState = CheckState.Unchecked
     MyBase.OnPaint(e)
     Me.CheckState = currentState
     End If
    
     ' Determine the correct state of the RadioButton.
     Dim buttonState As RadioButtonState = RadioButtonState.UncheckedNormal
     If Enabled Then
     If mouseDownState Then
     If Checked Then
     buttonState = RadioButtonState.CheckedPressed
     Else
     buttonState = RadioButtonState.UncheckedPressed
     End If
     ElseIf mouseHoverState Then
     If Checked Then
     buttonState = RadioButtonState.CheckedHot
     Else
     buttonState = RadioButtonState.UncheckedHot
     End If
     Else
     If Checked Then buttonState = RadioButtonState.CheckedNormal
     End If
     Else
     If Checked Then
     buttonState = RadioButtonState.CheckedDisabled
     Else
     buttonState = RadioButtonState.UncheckedDisabled
     End If
     End If
    
     ' Calculate the position at which to display the RadioButton.
     Dim offset As Int32 = CInt((ContentRectangle.Height - _
     RadioButtonRenderer.GetGlyphSize( _
     e.Graphics, buttonState).Height) / 2)
     Dim imageLocation As Point = New Point( _
     ContentRectangle.Location.X + 4, _
     ContentRectangle.Location.Y + offset)
    
     ' Paint the RadioButton. 
     RadioButtonRenderer.DrawRadioButton( _
     e.Graphics, imageLocation, buttonState)
    
    End Sub
    
  2. Override the OnMouseEnter, OnMouseLeave, OnMouseDown, and OnMouseUp methods to track the state of the mouse and ensure that the OnPaint method paints the correct option-button state.

    private bool mouseHoverState = false;
    
    protected override void OnMouseEnter(EventArgs e)
    {
     mouseHoverState = true;
    
     // Force the item to repaint with the new RadioButton state.
     Invalidate();
    
     base.OnMouseEnter(e);
    }
    
    protected override void OnMouseLeave(EventArgs e)
    {
     mouseHoverState = false;
     base.OnMouseLeave(e);
    }
    
    private bool mouseDownState = false;
    
    protected override void OnMouseDown(MouseEventArgs e)
    {
     mouseDownState = true;
    
     // Force the item to repaint with the new RadioButton state.
     Invalidate();
    
     base.OnMouseDown(e);
    }
    
    protected override void OnMouseUp(MouseEventArgs e)
    {
     mouseDownState = false;
     base.OnMouseUp(e);
    }
    
    Private mouseHoverState As Boolean = False
    
    Protected Overrides Sub OnMouseEnter(ByVal e As EventArgs)
     mouseHoverState = True
    
     ' Force the item to repaint with the new RadioButton state.
     Invalidate()
    
     MyBase.OnMouseEnter(e)
    End Sub
    
    Protected Overrides Sub OnMouseLeave(ByVal e As EventArgs)
     mouseHoverState = False
     MyBase.OnMouseLeave(e)
    End Sub
    
    Private mouseDownState As Boolean = False
    
    Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
     mouseDownState = True
    
     ' Force the item to repaint with the new RadioButton state.
     Invalidate()
    
     MyBase.OnMouseDown(e)
    End Sub
    
    Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
     mouseDownState = False
     MyBase.OnMouseUp(e)
    End Sub
    

To disable options on a submenu when the parent item is not selected

  1. Override the Enabled property so that the item is disabled when it has a parent item with both a CheckOnClick value of true and a Checked value of false.

    // Enable the item only if its parent item is in the checked state
    // and its Enabled property has not been explicitly set to false.
    public override bool Enabled
    {
     get
     {
     ToolStripMenuItem ownerMenuItem =
     OwnerItem as ToolStripMenuItem;
    
     // Use the base value in design mode to prevent the designer
     // from setting the base value to the calculated value.
     if (!DesignMode &&
     ownerMenuItem != null && ownerMenuItem.CheckOnClick)
     {
     return base.Enabled && ownerMenuItem.Checked;
     }
     else
     {
     return base.Enabled;
     }
     }
     set
     {
     base.Enabled = value;
     }
    }
    
    ' Enable the item only if its parent item is in the checked state 
    ' and its Enabled property has not been explicitly set to false. 
    Public Overrides Property Enabled() As Boolean
     Get
     Dim ownerMenuItem As ToolStripMenuItem = _
     TryCast(OwnerItem, ToolStripMenuItem)
    
     ' Use the base value in design mode to prevent the designer
     ' from setting the base value to the calculated value.
     If Not DesignMode AndAlso ownerMenuItem IsNot Nothing AndAlso _
     ownerMenuItem.CheckOnClick Then
     Return MyBase.Enabled AndAlso ownerMenuItem.Checked
     Else
     Return MyBase.Enabled
     End If
     End Get
    
     Set(ByVal value As Boolean)
     MyBase.Enabled = value
     End Set
    End Property
    
  2. Override the OnOwnerChanged method to subscribe to the CheckedChanged event of the parent item.

    // When OwnerItem becomes available, if it is a ToolStripMenuItem
    // with a CheckOnClick property value of true, subscribe to its
    // CheckedChanged event.
    protected override void OnOwnerChanged(EventArgs e)
    {
     ToolStripMenuItem ownerMenuItem =
     OwnerItem as ToolStripMenuItem;
     if (ownerMenuItem != null && ownerMenuItem.CheckOnClick)
     {
     ownerMenuItem.CheckedChanged +=
     new EventHandler(OwnerMenuItem_CheckedChanged);
     }
     base.OnOwnerChanged(e);
    }
    
    ' When OwnerItem becomes available, if it is a ToolStripMenuItem 
    ' with a CheckOnClick property value of true, subscribe to its 
    ' CheckedChanged event. 
    Protected Overrides Sub OnOwnerChanged(ByVal e As EventArgs)
    
     Dim ownerMenuItem As ToolStripMenuItem = _
     TryCast(OwnerItem, ToolStripMenuItem)
    
     If ownerMenuItem IsNot Nothing AndAlso _
     ownerMenuItem.CheckOnClick Then
     AddHandler ownerMenuItem.CheckedChanged, New _
     EventHandler(AddressOf OwnerMenuItem_CheckedChanged)
     End If
    
     MyBase.OnOwnerChanged(e)
    
    End Sub
    
  3. In the handler for the parent-item CheckedChanged event, invalidate the item to update the display with the new enabled state.

    // When the checked state of the parent item changes,
    // repaint the item so that the new Enabled state is displayed.
    private void OwnerMenuItem_CheckedChanged(
     object sender, EventArgs e)
    {
     Invalidate();
    }
    
    ' When the checked state of the parent item changes, 
    ' repaint the item so that the new Enabled state is displayed. 
    Private Sub OwnerMenuItem_CheckedChanged( _
     ByVal sender As Object, ByVal e As EventArgs)
     Invalidate()
    End Sub
    

Example

The following code example provides the complete ToolStripRadioButtonMenuItem class, and a Form class and Program class to demonstrate the option-button behavior.

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;

public class ToolStripRadioButtonMenuItem : ToolStripMenuItem
{
 public ToolStripRadioButtonMenuItem()
 : base()
 {
 Initialize();
 }

 public ToolStripRadioButtonMenuItem(string text)
 : base(text, null, (EventHandler)null)
 {
 Initialize();
 }

 public ToolStripRadioButtonMenuItem(Image image)
 : base(null, image, (EventHandler)null)
 {
 Initialize();
 }

 public ToolStripRadioButtonMenuItem(string text, Image image)
 : base(text, image, (EventHandler)null)
 {
 Initialize();
 }

 public ToolStripRadioButtonMenuItem(string text, Image image,
 EventHandler onClick)
 : base(text, image, onClick)
 {
 Initialize();
 }

 public ToolStripRadioButtonMenuItem(string text, Image image,
 EventHandler onClick, string name)
 : base(text, image, onClick, name)
 {
 Initialize();
 }

 public ToolStripRadioButtonMenuItem(string text, Image image,
 params ToolStripItem[] dropDownItems)
 : base(text, image, dropDownItems)
 {
 Initialize();
 }

 public ToolStripRadioButtonMenuItem(string text, Image image,
 EventHandler onClick, Keys shortcutKeys)
 : base(text, image, onClick)
 {
 Initialize();
 this.ShortcutKeys = shortcutKeys;
 }

 // Called by all constructors to initialize CheckOnClick.
 private void Initialize()
 {
 CheckOnClick = true;
 }

 protected override void OnCheckedChanged(EventArgs e)
 {
 base.OnCheckedChanged(e);

 // If this item is no longer in the checked state or if its
 // parent has not yet been initialized, do nothing.
 if (!Checked || this.Parent == null) return;

 // Clear the checked state for all siblings.
 foreach (ToolStripItem item in Parent.Items)
 {
 ToolStripRadioButtonMenuItem radioItem =
 item as ToolStripRadioButtonMenuItem;
 if (radioItem != null && radioItem != this && radioItem.Checked)
 {
 radioItem.Checked = false;

 // Only one item can be selected at a time,
 // so there is no need to continue.
 return;
 }
 }
 }

 protected override void OnClick(EventArgs e)
 {
 // If the item is already in the checked state, do not call
 // the base method, which would toggle the value.
 if (Checked) return;

 base.OnClick(e);
 }

 // Let the item paint itself, and then paint the RadioButton
 // where the check mark is normally displayed.
 protected override void OnPaint(PaintEventArgs e)
 {
 if (Image != null)
 {
 // If the client sets the Image property, the selection behavior
 // remains unchanged, but the RadioButton is not displayed and the
 // selection is indicated only by the selection rectangle.
 base.OnPaint(e);
 return;
 }
 else
 {
 // If the Image property is not set, call the base OnPaint method
 // with the CheckState property temporarily cleared to prevent
 // the check mark from being painted.
 CheckState currentState = this.CheckState;
 this.CheckState = CheckState.Unchecked;
 base.OnPaint(e);
 this.CheckState = currentState;
 }

 // Determine the correct state of the RadioButton.
 RadioButtonState buttonState = RadioButtonState.UncheckedNormal;
 if (Enabled)
 {
 if (mouseDownState)
 {
 if (Checked) buttonState = RadioButtonState.CheckedPressed;
 else buttonState = RadioButtonState.UncheckedPressed;
 }
 else if (mouseHoverState)
 {
 if (Checked) buttonState = RadioButtonState.CheckedHot;
 else buttonState = RadioButtonState.UncheckedHot;
 }
 else
 {
 if (Checked) buttonState = RadioButtonState.CheckedNormal;
 }
 }
 else
 {
 if (Checked) buttonState = RadioButtonState.CheckedDisabled;
 else buttonState = RadioButtonState.UncheckedDisabled;
 }

 // Calculate the position at which to display the RadioButton.
 Int32 offset = (ContentRectangle.Height -
 RadioButtonRenderer.GetGlyphSize(
 e.Graphics, buttonState).Height) / 2;
 Point imageLocation = new Point(
 ContentRectangle.Location.X + 4,
 ContentRectangle.Location.Y + offset);

 // Paint the RadioButton.
 RadioButtonRenderer.DrawRadioButton(
 e.Graphics, imageLocation, buttonState);
 }

 private bool mouseHoverState = false;

 protected override void OnMouseEnter(EventArgs e)
 {
 mouseHoverState = true;

 // Force the item to repaint with the new RadioButton state.
 Invalidate();

 base.OnMouseEnter(e);
 }

 protected override void OnMouseLeave(EventArgs e)
 {
 mouseHoverState = false;
 base.OnMouseLeave(e);
 }

 private bool mouseDownState = false;

 protected override void OnMouseDown(MouseEventArgs e)
 {
 mouseDownState = true;

 // Force the item to repaint with the new RadioButton state.
 Invalidate();

 base.OnMouseDown(e);
 }

 protected override void OnMouseUp(MouseEventArgs e)
 {
 mouseDownState = false;
 base.OnMouseUp(e);
 }

 // Enable the item only if its parent item is in the checked state
 // and its Enabled property has not been explicitly set to false.
 public override bool Enabled
 {
 get
 {
 ToolStripMenuItem ownerMenuItem =
 OwnerItem as ToolStripMenuItem;

 // Use the base value in design mode to prevent the designer
 // from setting the base value to the calculated value.
 if (!DesignMode &&
 ownerMenuItem != null && ownerMenuItem.CheckOnClick)
 {
 return base.Enabled && ownerMenuItem.Checked;
 }
 else
 {
 return base.Enabled;
 }
 }
 set
 {
 base.Enabled = value;
 }
 }

 // When OwnerItem becomes available, if it is a ToolStripMenuItem
 // with a CheckOnClick property value of true, subscribe to its
 // CheckedChanged event.
 protected override void OnOwnerChanged(EventArgs e)
 {
 ToolStripMenuItem ownerMenuItem =
 OwnerItem as ToolStripMenuItem;
 if (ownerMenuItem != null && ownerMenuItem.CheckOnClick)
 {
 ownerMenuItem.CheckedChanged +=
 new EventHandler(OwnerMenuItem_CheckedChanged);
 }
 base.OnOwnerChanged(e);
 }

 // When the checked state of the parent item changes,
 // repaint the item so that the new Enabled state is displayed.
 private void OwnerMenuItem_CheckedChanged(
 object sender, EventArgs e)
 {
 Invalidate();
 }
}

public class Form1 : Form
{
 private MenuStrip menuStrip1 = new MenuStrip();
 private ToolStripMenuItem mainToolStripMenuItem = new ToolStripMenuItem();
 private ToolStripMenuItem toolStripMenuItem1 = new ToolStripMenuItem();
 private ToolStripRadioButtonMenuItem toolStripRadioButtonMenuItem1 =
 new ToolStripRadioButtonMenuItem();
 private ToolStripRadioButtonMenuItem toolStripRadioButtonMenuItem2 =
 new ToolStripRadioButtonMenuItem();
 private ToolStripRadioButtonMenuItem toolStripRadioButtonMenuItem3 =
 new ToolStripRadioButtonMenuItem();
 private ToolStripRadioButtonMenuItem toolStripRadioButtonMenuItem4 =
 new ToolStripRadioButtonMenuItem();
 private ToolStripRadioButtonMenuItem toolStripRadioButtonMenuItem5 =
 new ToolStripRadioButtonMenuItem();
 private ToolStripRadioButtonMenuItem toolStripRadioButtonMenuItem6 =
 new ToolStripRadioButtonMenuItem();

 public Form1()
 {
 mainToolStripMenuItem.Text = "main";
 toolStripRadioButtonMenuItem1.Text = "option 1";
 toolStripRadioButtonMenuItem2.Text = "option 2";
 toolStripRadioButtonMenuItem3.Text = "option 2-1";
 toolStripRadioButtonMenuItem4.Text = "option 2-2";
 toolStripRadioButtonMenuItem5.Text = "option 3-1";
 toolStripRadioButtonMenuItem6.Text = "option 3-2";
 toolStripMenuItem1.Text = "toggle";
 toolStripMenuItem1.CheckOnClick = true;

 mainToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] {
 toolStripRadioButtonMenuItem1, toolStripRadioButtonMenuItem2,
 toolStripMenuItem1});
 toolStripRadioButtonMenuItem2.DropDownItems.AddRange(
 new ToolStripItem[] {toolStripRadioButtonMenuItem3,
 toolStripRadioButtonMenuItem4});
 toolStripMenuItem1.DropDownItems.AddRange(new ToolStripItem[] {
 toolStripRadioButtonMenuItem5, toolStripRadioButtonMenuItem6});

 menuStrip1.Items.AddRange(new ToolStripItem[] {mainToolStripMenuItem});
 Controls.Add(menuStrip1);
 MainMenuStrip = menuStrip1;
 Text = "ToolStripRadioButtonMenuItem demo";
 }
}

static class Program
{
 [STAThread]
 static void Main()
 {
 Application.EnableVisualStyles();
 Application.SetCompatibleTextRenderingDefault(false);
 Application.Run(new Form1());
 }
}
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Windows.Forms.VisualStyles

Public Class ToolStripRadioButtonMenuItem
 Inherits ToolStripMenuItem

 Public Sub New()
 MyBase.New()
 Initialize()
 End Sub

 Public Sub New(ByVal text As String)
 MyBase.New(text, Nothing, CType(Nothing, EventHandler))
 Initialize()
 End Sub

 Public Sub New(ByVal image As Image)
 MyBase.New(Nothing, image, CType(Nothing, EventHandler))
 Initialize()
 End Sub

 Public Sub New(ByVal text As String, ByVal image As Image)
 MyBase.New(text, image, CType(Nothing, EventHandler))
 Initialize()
 End Sub

 Public Sub New(ByVal text As String, _
 ByVal image As Image, ByVal onClick As EventHandler)
 MyBase.New(text, image, onClick)
 Initialize()
 End Sub

 Public Sub New(ByVal text As String, ByVal image As Image, _
 ByVal onClick As EventHandler, ByVal name As String)
 MyBase.New(text, image, onClick, name)
 Initialize()
 End Sub

 Public Sub New(ByVal text As String, ByVal image As Image, _
 ByVal ParamArray dropDownItems() As ToolStripItem)
 MyBase.New(text, image, dropDownItems)
 Initialize()
 End Sub

 Public Sub New(ByVal text As String, ByVal image As Image, _
 ByVal onClick As EventHandler, ByVal shortcutKeys As Keys)
 MyBase.New(text, image, onClick)
 Initialize()
 Me.ShortcutKeys = shortcutKeys
 End Sub

 ' Called by all constructors to initialize CheckOnClick.
 Private Sub Initialize()
 CheckOnClick = True
 End Sub

 Protected Overrides Sub OnCheckedChanged(ByVal e As EventArgs)

 MyBase.OnCheckedChanged(e)

 ' If this item is no longer in the checked state or if its 
 ' parent has not yet been initialized, do nothing.
 If Not Checked OrElse Me.Parent Is Nothing Then Return

 ' Clear the checked state for all siblings. 
 For Each item As ToolStripItem In Parent.Items

 Dim radioItem As ToolStripRadioButtonMenuItem = _
 TryCast(item, ToolStripRadioButtonMenuItem)
 If radioItem IsNot Nothing AndAlso _
 radioItem IsNot Me AndAlso _
 radioItem.Checked Then

 radioItem.Checked = False

 ' Only one item can be selected at a time, 
 ' so there is no need to continue.
 Return

 End If
 Next

 End Sub

 Protected Overrides Sub OnClick(ByVal e As EventArgs)

 ' If the item is already in the checked state, do not call 
 ' the base method, which would toggle the value. 
 If Checked Then Return

 MyBase.OnClick(e)
 End Sub

 ' Let the item paint itself, and then paint the RadioButton
 ' where the check mark is normally displayed.
 Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

 If Image IsNot Nothing Then
 ' If the client sets the Image property, the selection behavior
 ' remains unchanged, but the RadioButton is not displayed and the
 ' selection is indicated only by the selection rectangle. 
 MyBase.OnPaint(e)
 Return
 Else
 ' If the Image property is not set, call the base OnPaint method 
 ' with the CheckState property temporarily cleared to prevent
 ' the check mark from being painted.
 Dim currentState As CheckState = Me.CheckState
 Me.CheckState = CheckState.Unchecked
 MyBase.OnPaint(e)
 Me.CheckState = currentState
 End If

 ' Determine the correct state of the RadioButton.
 Dim buttonState As RadioButtonState = RadioButtonState.UncheckedNormal
 If Enabled Then
 If mouseDownState Then
 If Checked Then
 buttonState = RadioButtonState.CheckedPressed
 Else
 buttonState = RadioButtonState.UncheckedPressed
 End If
 ElseIf mouseHoverState Then
 If Checked Then
 buttonState = RadioButtonState.CheckedHot
 Else
 buttonState = RadioButtonState.UncheckedHot
 End If
 Else
 If Checked Then buttonState = RadioButtonState.CheckedNormal
 End If
 Else
 If Checked Then
 buttonState = RadioButtonState.CheckedDisabled
 Else
 buttonState = RadioButtonState.UncheckedDisabled
 End If
 End If

 ' Calculate the position at which to display the RadioButton.
 Dim offset As Int32 = CInt((ContentRectangle.Height - _
 RadioButtonRenderer.GetGlyphSize( _
 e.Graphics, buttonState).Height) / 2)
 Dim imageLocation As Point = New Point( _
 ContentRectangle.Location.X + 4, _
 ContentRectangle.Location.Y + offset)

 ' Paint the RadioButton. 
 RadioButtonRenderer.DrawRadioButton( _
 e.Graphics, imageLocation, buttonState)

 End Sub

 Private mouseHoverState As Boolean = False

 Protected Overrides Sub OnMouseEnter(ByVal e As EventArgs)
 mouseHoverState = True

 ' Force the item to repaint with the new RadioButton state.
 Invalidate()

 MyBase.OnMouseEnter(e)
 End Sub

 Protected Overrides Sub OnMouseLeave(ByVal e As EventArgs)
 mouseHoverState = False
 MyBase.OnMouseLeave(e)
 End Sub

 Private mouseDownState As Boolean = False

 Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
 mouseDownState = True

 ' Force the item to repaint with the new RadioButton state.
 Invalidate()

 MyBase.OnMouseDown(e)
 End Sub

 Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
 mouseDownState = False
 MyBase.OnMouseUp(e)
 End Sub

 ' Enable the item only if its parent item is in the checked state 
 ' and its Enabled property has not been explicitly set to false. 
 Public Overrides Property Enabled() As Boolean
 Get
 Dim ownerMenuItem As ToolStripMenuItem = _
 TryCast(OwnerItem, ToolStripMenuItem)

 ' Use the base value in design mode to prevent the designer
 ' from setting the base value to the calculated value.
 If Not DesignMode AndAlso ownerMenuItem IsNot Nothing AndAlso _
 ownerMenuItem.CheckOnClick Then
 Return MyBase.Enabled AndAlso ownerMenuItem.Checked
 Else
 Return MyBase.Enabled
 End If
 End Get

 Set(ByVal value As Boolean)
 MyBase.Enabled = value
 End Set
 End Property

 ' When OwnerItem becomes available, if it is a ToolStripMenuItem 
 ' with a CheckOnClick property value of true, subscribe to its 
 ' CheckedChanged event. 
 Protected Overrides Sub OnOwnerChanged(ByVal e As EventArgs)

 Dim ownerMenuItem As ToolStripMenuItem = _
 TryCast(OwnerItem, ToolStripMenuItem)

 If ownerMenuItem IsNot Nothing AndAlso _
 ownerMenuItem.CheckOnClick Then
 AddHandler ownerMenuItem.CheckedChanged, New _
 EventHandler(AddressOf OwnerMenuItem_CheckedChanged)
 End If

 MyBase.OnOwnerChanged(e)

 End Sub

 ' When the checked state of the parent item changes, 
 ' repaint the item so that the new Enabled state is displayed. 
 Private Sub OwnerMenuItem_CheckedChanged( _
 ByVal sender As Object, ByVal e As EventArgs)
 Invalidate()
 End Sub

End Class

Public Class Form1
 Inherits Form

 Private menuStrip1 As New MenuStrip()
 Private mainToolStripMenuItem As New ToolStripMenuItem()
 Private toolStripMenuItem1 As New ToolStripMenuItem()
 Private toolStripRadioButtonMenuItem1 As New ToolStripRadioButtonMenuItem()
 Private toolStripRadioButtonMenuItem2 As New ToolStripRadioButtonMenuItem()
 Private toolStripRadioButtonMenuItem3 As New ToolStripRadioButtonMenuItem()
 Private toolStripRadioButtonMenuItem4 As New ToolStripRadioButtonMenuItem()
 Private toolStripRadioButtonMenuItem5 As New ToolStripRadioButtonMenuItem()
 Private toolStripRadioButtonMenuItem6 As New ToolStripRadioButtonMenuItem()

 Public Sub New()

 Me.mainToolStripMenuItem.Text = "main"
 toolStripRadioButtonMenuItem1.Text = "option 1"
 toolStripRadioButtonMenuItem2.Text = "option 2"
 toolStripRadioButtonMenuItem3.Text = "option 2-1"
 toolStripRadioButtonMenuItem4.Text = "option 2-2"
 toolStripRadioButtonMenuItem5.Text = "option 3-1"
 toolStripRadioButtonMenuItem6.Text = "option 3-2"
 toolStripMenuItem1.Text = "toggle"
 toolStripMenuItem1.CheckOnClick = True

 mainToolStripMenuItem.DropDownItems.AddRange(New ToolStripItem() { _
 toolStripRadioButtonMenuItem1, toolStripRadioButtonMenuItem2, _
 toolStripMenuItem1})
 toolStripRadioButtonMenuItem2.DropDownItems.AddRange( _
 New ToolStripItem() {toolStripRadioButtonMenuItem3, _
 toolStripRadioButtonMenuItem4})
 toolStripMenuItem1.DropDownItems.AddRange(New ToolStripItem() { _
 toolStripRadioButtonMenuItem5, toolStripRadioButtonMenuItem6})

 menuStrip1.Items.AddRange(New ToolStripItem() {mainToolStripMenuItem})
 Controls.Add(menuStrip1)
 MainMenuStrip = menuStrip1
 Text = "ToolStripRadioButtonMenuItem demo"
 End Sub
End Class

Public Class Program

 <STAThread()> Public Shared Sub Main()
 Application.EnableVisualStyles()
 Application.SetCompatibleTextRenderingDefault(False)
 Application.Run(New Form1())
 End Sub

End Class

Compiling the Code

This example requires:

  • References to the System, System.Drawing, and System.Windows.Forms assemblies.

See also


Feedback

Was this page helpful?

Additional resources