254 lines
7.3 KiB
C#
254 lines
7.3 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using System.Windows.Forms.VisualStyles;
|
|
|
|
namespace LibreHardwareMonitor.UI;
|
|
|
|
/// <summary>
|
|
/// https://docs.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-display-option-buttons-in-a-menustrip-windows-forms
|
|
/// </summary>
|
|
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();
|
|
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 || Parent == null) return;
|
|
|
|
// Clear the checked state for all siblings.
|
|
foreach (ToolStripItem item in Parent.Items)
|
|
{
|
|
if (item is ToolStripRadioButtonMenuItem radioItem
|
|
&& 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 = CheckState;
|
|
CheckState = CheckState.Unchecked;
|
|
base.OnPaint(e);
|
|
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.
|
|
int 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;
|
|
|
|
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;
|
|
|
|
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
|
|
{
|
|
// Use the base value in design mode to prevent the designer
|
|
// from setting the base value to the calculated value.
|
|
if (!DesignMode
|
|
&& OwnerItem is ToolStripMenuItem ownerMenuItem
|
|
&& 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)
|
|
{
|
|
if (OwnerItem is ToolStripMenuItem ownerMenuItem
|
|
&& 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();
|
|
}
|
|
} |