first commit
This commit is contained in:
@@ -0,0 +1,254 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user