From 8ce0156d976774d7383a9a69dd291957de0a0fb1 Mon Sep 17 00:00:00 2001 From: Sunny Date: Thu, 9 Nov 2023 13:52:19 +0800 Subject: [PATCH] =?UTF-8?q?*=20UIRadioButtonGroup:=20=E9=87=8D=E5=86=99UIR?= =?UTF-8?q?adioButtonGroup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SunnyUI/Controls/UIRadioButtonGroup.cs | 245 +++++++++++++++---------- 1 file changed, 144 insertions(+), 101 deletions(-) diff --git a/SunnyUI/Controls/UIRadioButtonGroup.cs b/SunnyUI/Controls/UIRadioButtonGroup.cs index 20e432e3..d8f70d91 100644 --- a/SunnyUI/Controls/UIRadioButtonGroup.cs +++ b/SunnyUI/Controls/UIRadioButtonGroup.cs @@ -23,6 +23,7 @@ * 2022-11-21: V3.2.9 修复未显示时切换节点文本为空的问题 * 2023-04-22: V3.3.5 设置选择项ForeColor * 2023-06-27: V3.3.9 内置条目关联值由Tag改为TagString + * 2023-11-09: V3.5.2 重写UIRadioButtonGroup ******************************************************************************/ using System; @@ -45,18 +46,38 @@ namespace Sunny.UI public UIRadioButtonGroup() { items.CountChange += Items_CountChange; + ForeColor = UIStyles.Blue.CheckBoxForeColor; + checkBoxColor = UIStyles.Blue.CheckBoxColor; + hoverColor = UIStyles.Blue.ListItemHoverColor; } - protected override void OnFontChanged(EventArgs e) - { - base.OnFontChanged(e); + private Color checkBoxColor; + private Color hoverColor; - if (DefaultFontSize < 0) + /// + /// 设置主题样式 + /// + /// 主题样式 + public override void SetStyleColor(UIBaseStyle uiColor) + { + base.SetStyleColor(uiColor); + checkBoxColor = uiColor.CheckBoxColor; + ForeColor = uiColor.CheckBoxForeColor; + hoverColor = uiColor.ListItemHoverColor; + } + + /// + /// 填充颜色,当值为背景色或透明色或空值则不填充 + /// + [Description("填充颜色"), Category("SunnyUI")] + [DefaultValue(typeof(Color), "80, 160, 255")] + public Color RadioButtonColor + { + get => checkBoxColor; + set { - foreach (var item in buttons) - { - item.Font = Font; - } + checkBoxColor = value; + Invalidate(); } } @@ -65,28 +86,12 @@ namespace Sunny.UI Invalidate(); } - ~UIRadioButtonGroup() - { - ClearButtons(); - } - - private void ClearButtons() - { - foreach (var button in buttons) - { - button.Hide(); - button.Dispose(); - } - - buttons.Clear(); - } - public void Clear() { Items.Clear(); - ClearButtons(); SelectedIndex = -1; Invalidate(); + ValueChanged(this, -1, ""); } [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] @@ -98,42 +103,6 @@ namespace Sunny.UI private readonly UIObjectCollection items = new UIObjectCollection(); - private void CreateBoxes() - { - if (Items.Count == 0) return; - if (Items.Count != buttons.Count) - { - ClearButtons(); - - for (int i = 0; i < Items.Count; i++) - { - UIRadioButton button = new UIRadioButton - { - BackColor = Color.Transparent, - Font = Font, - Parent = this, - TagString = i.ToString(), - Style = Style, - Text = Items[i]?.ToString(), - StyleCustomMode = StyleCustomMode, - ForeColor = ForeColor - }; - - button.ValueChanged += Button_ValueChanged; - buttons.Add(button); - } - } - } - - protected override void AfterSetForeColor(Color color) - { - base.AfterSetForeColor(color); - foreach (var item in buttons) - { - item.ForeColor = color; - } - } - /// /// 重载绘图 /// @@ -142,30 +111,124 @@ namespace Sunny.UI { base.OnPaint(e); - CreateBoxes(); + if (Items.Count == 0) return; + + if (activeIndex >= 0 && CheckBoxRects.ContainsKey(activeIndex)) + { + e.Graphics.FillRectangle(hoverColor, CheckBoxRects[activeIndex]); + } int startX = StartPos.X; int startY = TitleTop + StartPos.Y; + for (int i = 0; i < Items.Count; i++) { - buttons[i].Text = Items[i].ToString(); - + string text = Items[i].ToString(); int rowIndex = i / ColumnCount; int columnIndex = i % ColumnCount; + int left = startX + ItemSize.Width * columnIndex + ColumnInterval * columnIndex; + int top = startY + ItemSize.Height * rowIndex + RowInterval * rowIndex; + Rectangle rect = new Rectangle(left, top, ItemSize.Width, ItemSize.Height); + if (CheckBoxRects.NotContainsKey(i)) + CheckBoxRects.Add(i, rect); + else + CheckBoxRects[i] = rect; + + int ImageSize = RadioButtonSize; + + //图标 + top = rect.Top + (rect.Height - ImageSize) / 2; + left = rect.Left + 6; + Color color = Enabled ? checkBoxColor : foreDisableColor; + + if (SelectedIndex == i) + { + e.Graphics.FillEllipse(color, left, top, ImageSize, ImageSize); + float pointSize = ImageSize - 4; + e.Graphics.FillEllipse(BackColor.IsValid() ? BackColor : Color.White, + left + ImageSize / 2.0f - pointSize / 2.0f, + top + ImageSize / 2.0f - pointSize / 2.0f, + pointSize, pointSize); + + pointSize = ImageSize - 8; + e.Graphics.FillEllipse(color, + left + ImageSize / 2.0f - pointSize / 2.0f, + top + ImageSize / 2.0f - pointSize / 2.0f, + pointSize, pointSize); + } + else + { + using Pen pn = new Pen(color, 2); + e.Graphics.SetHighQuality(); + e.Graphics.DrawEllipse(pn, left + 1, top + 1, ImageSize - 2, ImageSize - 2); + e.Graphics.SetDefaultQuality(); + } + + e.Graphics.DrawString(text, Font, ForeColor, rect, ContentAlignment.MiddleLeft, ImageSize + 10, 0); - buttons[i].Left = startX + ItemSize.Width * columnIndex + ColumnInterval * columnIndex; - buttons[i].Top = startY + ItemSize.Height * rowIndex + RowInterval * rowIndex; - buttons[i].Size = ItemSize; - buttons[i].Show(); } } - private void Button_ValueChanged(object sender, bool value) + private Dictionary CheckStates = new Dictionary(); + private Dictionary CheckBoxRects = new Dictionary(); + + int activeIndex = -1; + private int _imageSize = 16; + + [DefaultValue(16)] + [Description("图标大小"), Category("SunnyUI")] + [Browsable(false)] + public int RadioButtonSize { - UIRadioButton button = (UIRadioButton)sender; - if (value) + get => _imageSize; + set { - SelectedIndex = button.TagString.ToInt(); + _imageSize = Math.Max(value, 16); + _imageSize = Math.Min(value, 64); + Invalidate(); + } + } + + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + + int index = -1; + foreach (var item in CheckBoxRects) + { + if (e.Location.InRect(item.Value)) + { + index = item.Key; + break; + } + } + + if (activeIndex != index) + { + activeIndex = index; + Invalidate(); + } + } + + protected override void OnMouseLeave(EventArgs e) + { + base.OnMouseLeave(e); + + activeIndex = -1; + Invalidate(); + } + + protected override void OnMouseClick(MouseEventArgs e) + { + base.OnMouseClick(e); + + foreach (var pair in CheckBoxRects) + { + if (e.Location.InRect(pair.Value) && pair.Key >= 0 && pair.Key < items.Count) + { + SelectedIndex = pair.Key; + Invalidate(); + } } } @@ -178,11 +241,6 @@ namespace Sunny.UI get => selectedIndex; set { - if (buttons.Count != Items.Count) - { - CreateBoxes(); - } - if (Items.Count == 0) { selectedIndex = -1; @@ -191,28 +249,13 @@ namespace Sunny.UI if (SelectedIndex != value) { - if (value >= 0 && value < buttons.Count) - { - selectedIndex = value; - buttons[value].Checked = true; - ValueChanged?.Invoke(this, value, buttons[value].Text); - } + selectedIndex = value; + Invalidate(); + ValueChanged?.Invoke(this, value, items.ContainsIndex(value) ? items[value].ToString() : ""); } } } - public void SelectedNone() - { - foreach (var button in buttons) - { - button.Checked = false; - } - - selectedIndex = -1; - } - - private readonly List buttons = new List(); - private int columnCount = 1; [DefaultValue(1)] @@ -227,9 +270,9 @@ namespace Sunny.UI } } - private Size itemSize = new Size(150, 35); + private Size itemSize = new Size(150, 29); - [DefaultValue(typeof(Size), "150, 35")] + [DefaultValue(typeof(Size), "150, 29")] [Description("列表项大小"), Category("SunnyUI")] public Size ItemSize { @@ -255,9 +298,9 @@ namespace Sunny.UI } } - public int columnInterval; + public int columnInterval = 6; - [DefaultValue(0)] + [DefaultValue(6)] [Description("显示列间隔"), Category("SunnyUI")] public int ColumnInterval { @@ -269,9 +312,9 @@ namespace Sunny.UI } } - private int rowInterval; + private int rowInterval = 2; - [DefaultValue(0)] + [DefaultValue(2)] [Description("显示行间隔"), Category("SunnyUI")] public int RowInterval {