// ********************************* // Message from Original Author: // // 2008 Jose Menendez Poo // Please give me credit if you use this code. It's all I ask. // Contact me for more info: menendezpoo@gmail.com // ********************************* // // Original project from http://ribbon.codeplex.com/ // Continue to support and maintain by http://officeribbon.codeplex.com/ using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Windows.Forms.VisualStyles; namespace System.Windows.Forms { public class RibbonCheckBox : RibbonItem { public enum CheckBoxOrientationEnum { Left = 0, Right = 1 } public enum CheckBoxStyle { CheckBox, RadioButton } #region Fields private const int spacing = 3; private Rectangle _labelBounds; private Rectangle _checkboxBounds; private int _labelWidth; private int _checkboxSize; private CheckBoxOrientationEnum _checkBoxOrientation; private CheckBoxStyle _style; #endregion #region Events /// /// Raised when the property value has changed /// public event EventHandler CheckBoxCheckChanged; /// /// Raised when the property value is changing /// public event CancelEventHandler CheckBoxCheckChanging; #endregion #region Ctor public RibbonCheckBox() { _checkboxSize = 16; } #endregion #region Props /// /// Gets or sets the style of the checkbox item /// [DefaultValue(CheckBoxStyle.CheckBox)] [Category("Appearance")] public CheckBoxStyle Style { get => _style; set { _style = value; NotifyOwnerRegionsChanged(); } } /// /// Gets or sets the width of the Label /// [DefaultValue(CheckBoxOrientationEnum.Left)] [Category("Appearance")] public CheckBoxOrientationEnum CheckBoxOrientation { get => _checkBoxOrientation; set { _checkBoxOrientation = value; NotifyOwnerRegionsChanged(); } } /// /// Gets the bounds of the label that is shown next to the textbox /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public virtual Rectangle LabelBounds => _labelBounds; /// /// Gets a value indicating if the label is currently visible /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool LabelVisible { get; private set; } = true; /// /// Gets the bounds of the text /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public virtual Rectangle CheckBoxBounds => _checkboxBounds; /// /// Gets or sets the width of the Label /// [DefaultValue(0)] [Category("Appearance")] public int LabelWidth { get => _labelWidth; set { _labelWidth = value; NotifyOwnerRegionsChanged(); } } /// /// Gets or sets if a click on the text changes the checked state. /// [Description("Click on text changes the checked state.")] [Category("Behavior")] [DefaultValue(true)] public bool TextClickable { get; set; } = true; #endregion #region Methods /// /// Measures the suposed height of the boxbox /// /// protected virtual int MeasureHeight() { return _checkboxSize + Owner.ItemMargin.Vertical; } public override void OnPaint(object sender, RibbonElementPaintEventArgs e) { if (Owner != null) { Owner.Renderer.OnRenderRibbonItem(new RibbonItemRenderEventArgs(Owner, e.Graphics, Bounds, this)); if (Style == CheckBoxStyle.CheckBox) { CheckBoxState CheckState = Checked ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal; if (Selected) CheckState += 1; if (CheckBoxOrientation == CheckBoxOrientationEnum.Left) CheckBoxRenderer.DrawCheckBox(e.Graphics, new Point(_checkboxBounds.Left, _checkboxBounds.Top), CheckState); else CheckBoxRenderer.DrawCheckBox(e.Graphics, new Point(_checkboxBounds.Left + spacing, _checkboxBounds.Top), CheckState); } else { RadioButtonState RadioState = Checked ? RadioButtonState.CheckedNormal : RadioButtonState.UncheckedNormal; if (Selected) RadioState += 1; if (CheckBoxOrientation == CheckBoxOrientationEnum.Left) RadioButtonRenderer.DrawRadioButton(e.Graphics, new Point(_checkboxBounds.Left, _checkboxBounds.Top), RadioState); else RadioButtonRenderer.DrawRadioButton(e.Graphics, new Point(_checkboxBounds.Left + spacing, _checkboxBounds.Top), RadioState); } if (LabelVisible) { StringFormat f = new StringFormat(); if (_checkBoxOrientation == CheckBoxOrientationEnum.Left) f.Alignment = StringAlignment.Near; else f.Alignment = StringAlignment.Far; f.LineAlignment = StringAlignment.Far; //Top f.Trimming = StringTrimming.None; f.FormatFlags |= StringFormatFlags.NoWrap; Owner.Renderer.OnRenderRibbonItemText(new RibbonTextEventArgs(Owner, e.Graphics, _labelBounds, this, LabelBounds, Text, f)); } } } public override void SetBounds(Rectangle bounds) { base.SetBounds(bounds); if (CheckBoxOrientation == CheckBoxOrientationEnum.Left) { _checkboxBounds = new Rectangle( bounds.Left + Owner.ItemMargin.Left, bounds.Top + Owner.ItemMargin.Top + ((bounds.Height - _checkboxSize) / 2), _checkboxSize, _checkboxSize); int itemImageToTextSpacing = (SizeMode == RibbonElementSizeMode.DropDown) ? Owner.ItemImageToTextSpacing : 0; _labelBounds = Rectangle.FromLTRB( _checkboxBounds.Right + itemImageToTextSpacing, bounds.Top + Owner.ItemMargin.Top, bounds.Right - Owner.ItemMargin.Right, bounds.Bottom - Owner.ItemMargin.Bottom); } else { _checkboxBounds = new Rectangle( bounds.Right - Owner.ItemMargin.Right - _checkboxSize, bounds.Top + Owner.ItemMargin.Top + ((bounds.Height - _checkboxSize) / 2), _checkboxSize, _checkboxSize); _labelBounds = Rectangle.FromLTRB( bounds.Left + Owner.ItemMargin.Left, bounds.Top + Owner.ItemMargin.Top, _checkboxBounds.Left, bounds.Bottom - Owner.ItemMargin.Bottom); } if (SizeMode == RibbonElementSizeMode.Large) { LabelVisible = true; } else if (SizeMode == RibbonElementSizeMode.Medium) { LabelVisible = true; _labelBounds = Rectangle.Empty; } else if (SizeMode == RibbonElementSizeMode.Compact) { _labelBounds = Rectangle.Empty; LabelVisible = false; } } private bool checkedGlyphSize; public override Size MeasureSize(object sender, RibbonElementMeasureSizeEventArgs e) { if (!checkedGlyphSize) { try { if (Style == CheckBoxStyle.CheckBox) _checkboxSize = CheckBoxRenderer.GetGlyphSize(e.Graphics, Checked ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal).Height + spacing; else _checkboxSize = CheckBoxRenderer.GetGlyphSize(e.Graphics, Checked ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal).Height + spacing; } catch { /* I don't mind at all */ } checkedGlyphSize = true; } if (!Visible && !Owner.IsDesignMode()) { SetLastMeasuredSize(new Size(0, 0)); return LastMeasuredSize; } Size size = Size.Empty; int w = Owner.ItemMargin.Horizontal; int iwidth = Image != null ? Image.Width + spacing : 0; int lwidth = string.IsNullOrEmpty(Text) ? 0 : _labelWidth > 0 ? _labelWidth : e.Graphics.MeasureString(Text, Owner.Font).ToSize().Width; w += _checkboxSize; switch (e.SizeMode) { case RibbonElementSizeMode.DropDown: w += iwidth + lwidth + Owner.ItemImageToTextSpacing; break; case RibbonElementSizeMode.Large: w += iwidth + lwidth; break; case RibbonElementSizeMode.Medium: w += iwidth; break; } SetLastMeasuredSize(new Size(w, MeasureHeight())); return LastMeasuredSize; } public override void OnMouseEnter(MouseEventArgs e) { if (!Enabled) return; base.OnMouseEnter(e); //Canvas.Cursor = Cursors.Default; //SetSelected(true); } public override void OnMouseLeave(MouseEventArgs e) { if (!Enabled) return; base.OnMouseLeave(e); Canvas.Cursor = Cursors.Default; //SetSelected(false); } public override void OnMouseDown(MouseEventArgs e) { if (!Enabled) return; base.OnMouseDown(e); Rectangle clickableBounds = TextClickable ? Bounds : CheckBoxBounds; if (clickableBounds.Contains(e.X, e.Y)) { CancelEventArgs cev = new CancelEventArgs(); OnCheckChanging(cev); if (!cev.Cancel) { Checked = !Checked; OnCheckChanged(e); } } } public override void OnMouseMove(MouseEventArgs e) { if (!Enabled) return; base.OnMouseMove(e); Rectangle clickableBounds = TextClickable ? Bounds : CheckBoxBounds; if (clickableBounds.Contains(e.X, e.Y)) { Debug.WriteLine("Owner.Cursor = Cursors.Hand e.X=" + e.X + " e.Y=" + e.Y + " CheckBoxBounds (" + CheckBoxBounds + ")"); Canvas.Cursor = Cursors.Hand; if (!Selected) SetSelected(true); } else { Debug.WriteLine("Owner.Cursor = Cursors.Default e.X=" + e.X + " e.Y=" + e.Y + " CheckBoxBounds (" + CheckBoxBounds + ")"); Canvas.Cursor = Cursors.Default; if (Selected) SetSelected(false); } } /// /// Raises the event /// /// public void OnCheckChanged(EventArgs e) { if (!Enabled) return; NotifyOwnerRegionsChanged(); if (CheckBoxCheckChanged != null) { CheckBoxCheckChanged(this, e); } } /// /// Raises the event /// /// public void OnCheckChanging(CancelEventArgs e) { if (!Enabled) return; if (CheckBoxCheckChanging != null) { CheckBoxCheckChanging(this, e); } } #endregion } }