* UICheckBoxGroup: 重写UICheckBoxGroup
This commit is contained in:
parent
718560e5c4
commit
0c1b7d13ba
@ -52,7 +52,7 @@ namespace Sunny.UI
|
|||||||
Size = new Size(150, 29);
|
Size = new Size(150, 29);
|
||||||
SetStyle(ControlStyles.StandardDoubleClick, UseDoubleClick);
|
SetStyle(ControlStyles.StandardDoubleClick, UseDoubleClick);
|
||||||
|
|
||||||
foreColor = UIStyles.Blue.CheckBoxForeColor;
|
ForeColor = UIStyles.Blue.CheckBoxForeColor;
|
||||||
fillColor = UIStyles.Blue.CheckBoxColor;
|
fillColor = UIStyles.Blue.CheckBoxColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ namespace Sunny.UI
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
_imageSize = Math.Max(value, 16);
|
_imageSize = Math.Max(value, 16);
|
||||||
_imageSize = Math.Min(value, 128);
|
_imageSize = Math.Min(value, 64);
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,17 +138,6 @@ namespace Sunny.UI
|
|||||||
[Description("是否只读"), Category("SunnyUI")]
|
[Description("是否只读"), Category("SunnyUI")]
|
||||||
public bool ReadOnly { get; set; }
|
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>
|
||||||
/// 图标与文字之间间隔
|
/// 图标与文字之间间隔
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -200,7 +189,7 @@ namespace Sunny.UI
|
|||||||
protected override void OnPaintFore(Graphics g, GraphicsPath path)
|
protected override void OnPaintFore(Graphics g, GraphicsPath path)
|
||||||
{
|
{
|
||||||
//填充文字
|
//填充文字
|
||||||
Color color = foreColor;
|
Color color = ForeColor;
|
||||||
color = Enabled ? color : UIDisableColor.Fore;
|
color = Enabled ? color : UIDisableColor.Fore;
|
||||||
Rectangle rect = new Rectangle(_imageSize + _imageInterval * 2, 0, Width - _imageSize + _imageInterval * 2, Height);
|
Rectangle rect = new Rectangle(_imageSize + _imageInterval * 2, 0, Width - _imageSize + _imageInterval * 2, Height);
|
||||||
g.DrawString(Text, Font, color, rect, ContentAlignment.MiddleLeft);
|
g.DrawString(Text, Font, color, rect, ContentAlignment.MiddleLeft);
|
||||||
@ -263,7 +252,7 @@ namespace Sunny.UI
|
|||||||
{
|
{
|
||||||
base.SetStyleColor(uiColor);
|
base.SetStyleColor(uiColor);
|
||||||
fillColor = uiColor.CheckBoxColor;
|
fillColor = uiColor.CheckBoxColor;
|
||||||
foreColor = uiColor.CheckBoxForeColor;
|
ForeColor = uiColor.CheckBoxForeColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
* 2022-11-21: V3.2.9 修复未显示时切换节点文本为空的问题
|
* 2022-11-21: V3.2.9 修复未显示时切换节点文本为空的问题
|
||||||
* 2023-04-19: V3.3.5 设置选择项ForeColor
|
* 2023-04-19: V3.3.5 设置选择项ForeColor
|
||||||
* 2023-06-27: V3.3.9 内置条目关联值由Tag改为TagString
|
* 2023-06-27: V3.3.9 内置条目关联值由Tag改为TagString
|
||||||
|
* 2023-11-07: V3.5.2 重写UICheckBoxGroup
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
@ -62,20 +63,11 @@ namespace Sunny.UI
|
|||||||
public UICheckBoxGroup()
|
public UICheckBoxGroup()
|
||||||
{
|
{
|
||||||
items.CountChange += Items_CountChange;
|
items.CountChange += Items_CountChange;
|
||||||
|
ForeColor = UIStyles.Blue.CheckBoxForeColor;
|
||||||
|
checkBoxColor = UIStyles.Blue.CheckBoxColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnFontChanged(EventArgs e)
|
private Color checkBoxColor;
|
||||||
{
|
|
||||||
base.OnFontChanged(e);
|
|
||||||
|
|
||||||
if (DefaultFontSize < 0)
|
|
||||||
{
|
|
||||||
foreach (var item in boxes)
|
|
||||||
{
|
|
||||||
item.Font = Font;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Items_CountChange(object sender, EventArgs e)
|
private void Items_CountChange(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
@ -90,26 +82,29 @@ namespace Sunny.UI
|
|||||||
public bool this[int index]
|
public bool this[int index]
|
||||||
{
|
{
|
||||||
get => GetItemCheckState(index);
|
get => GetItemCheckState(index);
|
||||||
set => SetItemCheckState(index, value);
|
set
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 析构事件
|
|
||||||
/// </summary>
|
|
||||||
~UICheckBoxGroup()
|
|
||||||
{
|
|
||||||
ClearBoxes();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ClearBoxes()
|
|
||||||
{
|
|
||||||
foreach (var box in boxes)
|
|
||||||
{
|
{
|
||||||
box.Hide();
|
SetItemCheckState(index, value);
|
||||||
box.Dispose();
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boxes.Clear();
|
private Dictionary<int, bool> CheckStates = new Dictionary<int, bool>();
|
||||||
|
private Dictionary<int, Rectangle> CheckBoxRects = new Dictionary<int, Rectangle>();
|
||||||
|
private int _imageSize = 16;
|
||||||
|
|
||||||
|
[DefaultValue(16)]
|
||||||
|
[Description("图标大小"), Category("SunnyUI")]
|
||||||
|
[Browsable(false)]
|
||||||
|
public int CheckBoxSize
|
||||||
|
{
|
||||||
|
get => _imageSize;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_imageSize = Math.Max(value, 16);
|
||||||
|
_imageSize = Math.Min(value, 64);
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -118,7 +113,8 @@ namespace Sunny.UI
|
|||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
Items.Clear();
|
Items.Clear();
|
||||||
ClearBoxes();
|
CheckStates.Clear();
|
||||||
|
CheckBoxRects.Clear();
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,36 +130,29 @@ namespace Sunny.UI
|
|||||||
|
|
||||||
private readonly UIObjectCollection items = new UIObjectCollection();
|
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)
|
base.SetStyleColor(uiColor);
|
||||||
{
|
checkBoxColor = uiColor.CheckBoxColor;
|
||||||
ClearBoxes();
|
ForeColor = uiColor.CheckBoxForeColor;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void AfterSetForeColor(Color color)
|
/// <summary>
|
||||||
|
/// 填充颜色,当值为背景色或透明色或空值则不填充
|
||||||
|
/// </summary>
|
||||||
|
[Description("填充颜色"), Category("SunnyUI")]
|
||||||
|
[DefaultValue(typeof(Color), "80, 160, 255")]
|
||||||
|
public Color CheckBoxColor
|
||||||
{
|
{
|
||||||
base.AfterSetForeColor(color);
|
get => checkBoxColor;
|
||||||
foreach (var item in boxes)
|
set
|
||||||
{
|
{
|
||||||
item.ForeColor = color;
|
checkBoxColor = value;
|
||||||
|
Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,33 +163,66 @@ namespace Sunny.UI
|
|||||||
protected override void OnPaint(PaintEventArgs e)
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnPaint(e);
|
base.OnPaint(e);
|
||||||
|
|
||||||
CreateBoxes();
|
|
||||||
|
|
||||||
if (Items.Count == 0) return;
|
if (Items.Count == 0) return;
|
||||||
|
|
||||||
int startX = StartPos.X;
|
int startX = StartPos.X;
|
||||||
int startY = TitleTop + StartPos.Y;
|
int startY = TitleTop + StartPos.Y;
|
||||||
|
|
||||||
for (int i = 0; i < Items.Count; i++)
|
for (int i = 0; i < Items.Count; i++)
|
||||||
{
|
{
|
||||||
boxes[i].Text = Items[i].ToString();
|
string text = Items[i].ToString();
|
||||||
|
|
||||||
int rowIndex = i / ColumnCount;
|
int rowIndex = i / ColumnCount;
|
||||||
int columnIndex = 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;
|
top = rect.Top + (rect.Height - ImageSize) / 2;
|
||||||
boxes[i].Size = ItemSize;
|
Color color = Enabled ? checkBoxColor : foreDisableColor;
|
||||||
boxes[i].Show();
|
|
||||||
|
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
|
get
|
||||||
{
|
{
|
||||||
List<int> indexes = new List<int>();
|
List<int> indexes = new List<int>();
|
||||||
|
for (int i = 0; i < Items.Count; i++)
|
||||||
for (int i = 0; i < boxes.Count; i++)
|
|
||||||
{
|
{
|
||||||
if (boxes[i].Checked)
|
if (this[i]) indexes.Add(i);
|
||||||
indexes.Add(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return indexes;
|
return indexes;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (boxes.Count != Items.Count)
|
|
||||||
{
|
|
||||||
CreateBoxes();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (int i in value)
|
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>
|
/// <param name="isChecked">是否选中</param>
|
||||||
public void SetItemCheckState(int index, bool isChecked)
|
public void SetItemCheckState(int index, bool isChecked)
|
||||||
{
|
{
|
||||||
CreateBoxes();
|
if (index >= 0 && index < Items.Count && CheckStates.NotContainsKey(index))
|
||||||
if (index >= 0 && index < boxes.Count)
|
|
||||||
{
|
{
|
||||||
boxes[index].Checked = isChecked;
|
CheckStates.Add(index, isChecked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckStates[index] = isChecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -260,8 +278,8 @@ namespace Sunny.UI
|
|||||||
/// <returns>是否选中</returns>
|
/// <returns>是否选中</returns>
|
||||||
public bool GetItemCheckState(int index)
|
public bool GetItemCheckState(int index)
|
||||||
{
|
{
|
||||||
if (index >= 0 && index < items.Count)
|
if (index >= 0 && index < items.Count && CheckStates.ContainsKey(index))
|
||||||
return boxes[index].Checked;
|
return CheckStates[index];
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -276,18 +294,15 @@ namespace Sunny.UI
|
|||||||
{
|
{
|
||||||
List<object> objects = new List<object>();
|
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)
|
if (this[i]) objects.Add(Items[i]);
|
||||||
objects.Add(Items[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return objects;
|
return objects;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly List<UICheckBox> boxes = new List<UICheckBox>();
|
|
||||||
|
|
||||||
private int columnCount = 1;
|
private int columnCount = 1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -340,12 +355,12 @@ namespace Sunny.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private int columnInterval;
|
private int columnInterval = 6;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 显示项列之间的间隔
|
/// 显示项列之间的间隔
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(0)]
|
[DefaultValue(6)]
|
||||||
[Description("显示项列之间的间隔"), Category("SunnyUI")]
|
[Description("显示项列之间的间隔"), Category("SunnyUI")]
|
||||||
public int ColumnInterval
|
public int ColumnInterval
|
||||||
{
|
{
|
||||||
@ -379,13 +394,12 @@ namespace Sunny.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void SelectAll()
|
public void SelectAll()
|
||||||
{
|
{
|
||||||
multiChange = true;
|
for (int i = 0; i < Items.Count; i++)
|
||||||
foreach (var box in boxes)
|
|
||||||
{
|
{
|
||||||
box.Checked = true;
|
SetItemCheckState(i, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
multiChange = false;
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -393,13 +407,12 @@ namespace Sunny.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void UnSelectAll()
|
public void UnSelectAll()
|
||||||
{
|
{
|
||||||
multiChange = true;
|
for (int i = 0; i < Items.Count; i++)
|
||||||
foreach (var box in boxes)
|
|
||||||
{
|
{
|
||||||
box.Checked = false;
|
SetItemCheckState(i, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
multiChange = false;
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -407,15 +420,12 @@ namespace Sunny.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void ReverseSelected()
|
public void ReverseSelected()
|
||||||
{
|
{
|
||||||
multiChange = true;
|
for (int i = 0; i < Items.Count; i++)
|
||||||
foreach (var box in boxes)
|
|
||||||
{
|
{
|
||||||
box.Checked = !box.Checked;
|
SetItemCheckState(i, !this[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
multiChange = false;
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool multiChange;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user