* UICheckBoxGroup: 重写UICheckBoxGroup

This commit is contained in:
Sunny 2023-11-07 23:19:23 +08:00
parent 718560e5c4
commit 0c1b7d13ba
2 changed files with 119 additions and 120 deletions

View File

@ -52,7 +52,7 @@ namespace Sunny.UI
Size = new Size(150, 29);
SetStyle(ControlStyles.StandardDoubleClick, UseDoubleClick);
foreColor = UIStyles.Blue.CheckBoxForeColor;
ForeColor = UIStyles.Blue.CheckBoxForeColor;
fillColor = UIStyles.Blue.CheckBoxColor;
}
@ -126,7 +126,7 @@ namespace Sunny.UI
set
{
_imageSize = Math.Max(value, 16);
_imageSize = Math.Min(value, 128);
_imageSize = Math.Min(value, 64);
Invalidate();
}
}
@ -138,17 +138,6 @@ namespace Sunny.UI
[Description("是否只读"), Category("SunnyUI")]
public bool ReadOnly { get; set; }
/// <summary>
/// 字体颜色
/// </summary>
[Description("字体颜色"), Category("SunnyUI")]
[DefaultValue(typeof(Color), "48, 48, 48")]
public override Color ForeColor
{
get => foreColor;
set => SetForeColor(value);
}
/// <summary>
/// 图标与文字之间间隔
/// </summary>
@ -200,7 +189,7 @@ namespace Sunny.UI
protected override void OnPaintFore(Graphics g, GraphicsPath path)
{
//填充文字
Color color = foreColor;
Color color = ForeColor;
color = Enabled ? color : UIDisableColor.Fore;
Rectangle rect = new Rectangle(_imageSize + _imageInterval * 2, 0, Width - _imageSize + _imageInterval * 2, Height);
g.DrawString(Text, Font, color, rect, ContentAlignment.MiddleLeft);
@ -263,7 +252,7 @@ namespace Sunny.UI
{
base.SetStyleColor(uiColor);
fillColor = uiColor.CheckBoxColor;
foreColor = uiColor.CheckBoxForeColor;
ForeColor = uiColor.CheckBoxForeColor;
}
/// <summary>

View File

@ -24,6 +24,7 @@
* 2022-11-21: V3.2.9
* 2023-04-19: V3.3.5 ForeColor
* 2023-06-27: V3.3.9 Tag改为TagString
* 2023-11-07: V3.5.2 UICheckBoxGroup
******************************************************************************/
using System;
@ -62,20 +63,11 @@ namespace Sunny.UI
public UICheckBoxGroup()
{
items.CountChange += Items_CountChange;
ForeColor = UIStyles.Blue.CheckBoxForeColor;
checkBoxColor = UIStyles.Blue.CheckBoxColor;
}
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
if (DefaultFontSize < 0)
{
foreach (var item in boxes)
{
item.Font = Font;
}
}
}
private Color checkBoxColor;
private void Items_CountChange(object sender, EventArgs e)
{
@ -90,26 +82,29 @@ namespace Sunny.UI
public bool this[int index]
{
get => GetItemCheckState(index);
set => SetItemCheckState(index, value);
set
{
SetItemCheckState(index, value);
Invalidate();
}
}
/// <summary>
/// 析构事件
/// </summary>
~UICheckBoxGroup()
{
ClearBoxes();
}
private Dictionary<int, bool> CheckStates = new Dictionary<int, bool>();
private Dictionary<int, Rectangle> CheckBoxRects = new Dictionary<int, Rectangle>();
private int _imageSize = 16;
private void ClearBoxes()
[DefaultValue(16)]
[Description("图标大小"), Category("SunnyUI")]
[Browsable(false)]
public int CheckBoxSize
{
foreach (var box in boxes)
get => _imageSize;
set
{
box.Hide();
box.Dispose();
_imageSize = Math.Max(value, 16);
_imageSize = Math.Min(value, 64);
Invalidate();
}
boxes.Clear();
}
/// <summary>
@ -118,7 +113,8 @@ namespace Sunny.UI
public void Clear()
{
Items.Clear();
ClearBoxes();
CheckStates.Clear();
CheckBoxRects.Clear();
Invalidate();
}
@ -134,36 +130,29 @@ namespace Sunny.UI
private readonly UIObjectCollection items = new UIObjectCollection();
private void CreateBoxes()
/// <summary>
/// 设置主题样式
/// </summary>
/// <param name="uiColor">主题样式</param>
public override void SetStyleColor(UIBaseStyle uiColor)
{
if (Items.Count != boxes.Count)
{
ClearBoxes();
for (int i = 0; i < Items.Count; i++)
{
UICheckBox box = new UICheckBox();
box.BackColor = Color.Transparent;
box.Font = Font;
box.Parent = this;
box.TagString = i.ToString();
box.Style = Style;
//box.IsScaled = IsScaled;
box.ValueChanged += Box_ValueChanged;
box.Text = Items[i]?.ToString();
box.StyleCustomMode = StyleCustomMode;
box.ForeColor = ForeColor;
boxes.Add(box);
}
}
base.SetStyleColor(uiColor);
checkBoxColor = uiColor.CheckBoxColor;
ForeColor = uiColor.CheckBoxForeColor;
}
protected override void AfterSetForeColor(Color color)
/// <summary>
/// 填充颜色,当值为背景色或透明色或空值则不填充
/// </summary>
[Description("填充颜色"), Category("SunnyUI")]
[DefaultValue(typeof(Color), "80, 160, 255")]
public Color CheckBoxColor
{
base.AfterSetForeColor(color);
foreach (var item in boxes)
get => checkBoxColor;
set
{
item.ForeColor = color;
checkBoxColor = value;
Invalidate();
}
}
@ -174,33 +163,66 @@ namespace Sunny.UI
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
CreateBoxes();
if (Items.Count == 0) return;
int startX = StartPos.X;
int startY = TitleTop + StartPos.Y;
for (int i = 0; i < Items.Count; i++)
{
boxes[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);
int ImageSize = CheckBoxSize;
boxes[i].Left = startX + ItemSize.Width * columnIndex + ColumnInterval * columnIndex;
boxes[i].Top = startY + ItemSize.Height * rowIndex + RowInterval * rowIndex;
boxes[i].Size = ItemSize;
boxes[i].Show();
//图标
top = rect.Top + (rect.Height - ImageSize) / 2;
Color color = Enabled ? checkBoxColor : foreDisableColor;
if (this[i])
{
e.Graphics.FillRoundRectangle(color, new Rectangle((int)left, (int)top, ImageSize, ImageSize), 1);
color = BackColor.IsValid() ? BackColor : Color.White;
Point pt2 = new Point((int)(left + ImageSize * 2 / 5.0f), (int)(top + ImageSize * 3 / 4.0f) - (ImageSize.Div(10)));
Point pt1 = new Point((int)left + 2 + ImageSize.Div(10), pt2.Y - (pt2.X - 2 - ImageSize.Div(10) - (int)left));
Point pt3 = new Point((int)left + ImageSize - 2 - ImageSize.Div(10), pt2.Y - (ImageSize - pt2.X - 2 - ImageSize.Div(10)) - (int)left);
PointF[] CheckMarkLine = { pt1, pt2, pt3 };
using Pen pn = new Pen(color, 2);
e.Graphics.SetHighQuality();
e.Graphics.DrawLines(pn, CheckMarkLine);
e.Graphics.SetDefaultQuality();
}
else
{
using Pen pn = new Pen(color, 1);
e.Graphics.DrawRoundRectangle(pn, new Rectangle((int)left + 1, (int)top + 1, ImageSize - 2, ImageSize - 2), 1);
e.Graphics.DrawRectangle(pn, new Rectangle((int)left + 2, (int)top + 2, ImageSize - 4, ImageSize - 4));
}
e.Graphics.DrawString(text, Font, ForeColor, rect, ContentAlignment.MiddleLeft, ImageSize + 4, 0);
if (CheckBoxRects.NotContainsKey(i))
CheckBoxRects.Add(i, rect);
else
CheckBoxRects[i] = rect;
}
}
private void Box_ValueChanged(object sender, bool value)
protected override void OnMouseClick(MouseEventArgs e)
{
UICheckBox checkBox = (UICheckBox)sender;
base.OnMouseClick(e);
if (!multiChange)
foreach (var pair in CheckBoxRects)
{
ValueChanged?.Invoke(this, checkBox.TagString.ToInt(), checkBox.Text, checkBox.Checked);
if (e.Location.InRect(pair.Value) && pair.Key >= 0 && pair.Key < items.Count)
{
this[pair.Key] = !this[pair.Key];
ValueChanged?.Invoke(this, pair.Key, Items[pair.Key].ToString(), this[pair.Key]);
Invalidate();
}
}
}
@ -213,29 +235,24 @@ namespace Sunny.UI
get
{
List<int> indexes = new List<int>();
for (int i = 0; i < boxes.Count; i++)
for (int i = 0; i < Items.Count; i++)
{
if (boxes[i].Checked)
indexes.Add(i);
if (this[i]) indexes.Add(i);
}
return indexes;
}
set
{
if (boxes.Count != Items.Count)
{
CreateBoxes();
}
foreach (int i in value)
{
if (i >= 0 && i < boxes.Count)
if (i >= 0 && i < Items.Count)
{
boxes[i].Checked = true;
SetItemCheckState(i, true);
}
}
Invalidate();
}
}
@ -246,11 +263,12 @@ namespace Sunny.UI
/// <param name="isChecked">是否选中</param>
public void SetItemCheckState(int index, bool isChecked)
{
CreateBoxes();
if (index >= 0 && index < boxes.Count)
if (index >= 0 && index < Items.Count && CheckStates.NotContainsKey(index))
{
boxes[index].Checked = isChecked;
CheckStates.Add(index, isChecked);
}
CheckStates[index] = isChecked;
}
/// <summary>
@ -260,8 +278,8 @@ namespace Sunny.UI
/// <returns>是否选中</returns>
public bool GetItemCheckState(int index)
{
if (index >= 0 && index < items.Count)
return boxes[index].Checked;
if (index >= 0 && index < items.Count && CheckStates.ContainsKey(index))
return CheckStates[index];
return false;
}
@ -276,18 +294,15 @@ namespace Sunny.UI
{
List<object> objects = new List<object>();
for (int i = 0; i < boxes.Count; i++)
for (int i = 0; i < Items.Count; i++)
{
if (boxes[i].Checked)
objects.Add(Items[i]);
if (this[i]) objects.Add(Items[i]);
}
return objects;
}
}
private readonly List<UICheckBox> boxes = new List<UICheckBox>();
private int columnCount = 1;
/// <summary>
@ -340,12 +355,12 @@ namespace Sunny.UI
}
private int columnInterval;
private int columnInterval = 6;
/// <summary>
/// 显示项列之间的间隔
/// </summary>
[DefaultValue(0)]
[DefaultValue(6)]
[Description("显示项列之间的间隔"), Category("SunnyUI")]
public int ColumnInterval
{
@ -379,13 +394,12 @@ namespace Sunny.UI
/// </summary>
public void SelectAll()
{
multiChange = true;
foreach (var box in boxes)
for (int i = 0; i < Items.Count; i++)
{
box.Checked = true;
SetItemCheckState(i, true);
}
multiChange = false;
Invalidate();
}
/// <summary>
@ -393,13 +407,12 @@ namespace Sunny.UI
/// </summary>
public void UnSelectAll()
{
multiChange = true;
foreach (var box in boxes)
for (int i = 0; i < Items.Count; i++)
{
box.Checked = false;
SetItemCheckState(i, false);
}
multiChange = false;
Invalidate();
}
/// <summary>
@ -407,15 +420,12 @@ namespace Sunny.UI
/// </summary>
public void ReverseSelected()
{
multiChange = true;
foreach (var box in boxes)
for (int i = 0; i < Items.Count; i++)
{
box.Checked = !box.Checked;
SetItemCheckState(i, !this[i]);
}
multiChange = false;
}
private bool multiChange;
Invalidate();
}
}
}