diff --git a/Bin/SunnyUI.dll b/Bin/SunnyUI.dll
index 893852b4..6a528d54 100644
Binary files a/Bin/SunnyUI.dll and b/Bin/SunnyUI.dll differ
diff --git a/Bin/SunnyUI.pdb b/Bin/SunnyUI.pdb
index 28cb1001..543df514 100644
Binary files a/Bin/SunnyUI.pdb and b/Bin/SunnyUI.pdb differ
diff --git a/SunnyUI.Demo/Bin/SunnyUI.Demo.exe b/SunnyUI.Demo/Bin/SunnyUI.Demo.exe
index 6ac054b3..681536c6 100644
Binary files a/SunnyUI.Demo/Bin/SunnyUI.Demo.exe and b/SunnyUI.Demo/Bin/SunnyUI.Demo.exe differ
diff --git a/SunnyUI.Demo/Bin/SunnyUI.dll b/SunnyUI.Demo/Bin/SunnyUI.dll
index 893852b4..6a528d54 100644
Binary files a/SunnyUI.Demo/Bin/SunnyUI.dll and b/SunnyUI.Demo/Bin/SunnyUI.dll differ
diff --git a/SunnyUI.Demo/Controls/FTreeView.Designer.cs b/SunnyUI.Demo/Controls/FTreeView.Designer.cs
index 5bce9046..316da406 100644
--- a/SunnyUI.Demo/Controls/FTreeView.Designer.cs
+++ b/SunnyUI.Demo/Controls/FTreeView.Designer.cs
@@ -73,11 +73,10 @@
// uiTreeView1
//
this.uiTreeView1.BackColor = System.Drawing.Color.White;
- this.uiTreeView1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.uiTreeView1.DrawMode = System.Windows.Forms.TreeViewDrawMode.OwnerDrawAll;
+ this.uiTreeView1.CheckBoxes = true;
this.uiTreeView1.Font = new System.Drawing.Font("微软雅黑", 12F);
- this.uiTreeView1.ItemHeight = 28;
this.uiTreeView1.Location = new System.Drawing.Point(33, 54);
+ this.uiTreeView1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.uiTreeView1.Name = "uiTreeView1";
treeNode1.Name = "节点8";
treeNode1.Text = "节点8";
@@ -128,8 +127,11 @@
treeNode15,
treeNode16,
treeNode20});
+ this.uiTreeView1.SelectedNode = null;
+ this.uiTreeView1.ShowLines = true;
this.uiTreeView1.Size = new System.Drawing.Size(266, 313);
this.uiTreeView1.TabIndex = 0;
+ this.uiTreeView1.Text = null;
//
// uiLine1
//
diff --git a/SunnyUI/Controls/UITreeView.cs b/SunnyUI/Controls/UITreeView.cs
index bc340a5d..0fc6cfd6 100644
--- a/SunnyUI/Controls/UITreeView.cs
+++ b/SunnyUI/Controls/UITreeView.cs
@@ -17,241 +17,60 @@
* 创建日期: 2020-05-05
*
* 2020-05-05: V2.2.5 增加文件
+ * 2020-07-07: V2.2.7 全部重写,增加圆角,CheckBoxes等
******************************************************************************/
using System;
+using System.Collections;
using System.ComponentModel;
using System.Drawing;
+using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace Sunny.UI
{
- public sealed class UITreeView : TreeView, IStyleInterface
+ public sealed class UITreeView : UIPanel
{
- private readonly UIScrollBar Bar = new UIScrollBar();
+ private UIScrollBar Bar;
+
+ private bool ScrollBarVisible;
+ private TreeViewEx view;
public UITreeView()
{
- SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true);
- DrawMode = TreeViewDrawMode.OwnerDrawAll;
- DoubleBuffered = true;
- Font = UIFontColor.Font;
-
- ItemHeight = 28;
- BackColor = Color.White;
-
- Bar.ValueChanged += Bar_ValueChanged;
- Bar.Dock = DockStyle.Right;
- Bar.Visible = false;
- Bar.Style = UIStyle.Custom;
- Bar.StyleCustomMode = true;
- Bar.FillColor = fillColor;
-
- Bar.ForeColor = Color.Silver;
- Bar.HoverColor = Color.Silver;
- Bar.PressColor = Color.Silver;
-
- Controls.Add(Bar);
- Version = UIGlobal.Version;
+ InitializeComponent();
+ ShowText = false;
SetScrollInfo();
+
+ view.BeforeCheck += View_BeforeCheck;
+ view.AfterCheck += View_AfterCheck;
+ view.BeforeCollapse += View_BeforeCollapse;
+ view.AfterCollapse += View_AfterCollapse;
+ view.BeforeExpand += View_BeforeExpand;
+ view.AfterExpand += View_AfterExpand;
+ view.DrawNode += View_DrawNode;
+ view.ItemDrag += View_ItemDrag;
+ view.NodeMouseHover += View_NodeMouseHover;
+ view.BeforeSelect += View_BeforeSelect;
+ view.AfterSelect += View_AfterSelect;
+ view.NodeMouseClick += View_NodeMouseClick;
+ view.NodeMouseDoubleClick += View_NodeMouseDoubleClick;
}
- [DefaultValue(null)]
- public string TagString { get; set; }
-
- private Color fillColor = Color.White;
-
- ///
- /// 填充颜色,当值为背景色或透明色或空值则不填充
- ///
- [Description("背景颜色"), Category("自定义")]
- [DefaultValue(typeof(Color), "White")]
- public Color FillColor
- {
- get => fillColor;
- set
- {
- if (fillColor != value)
- {
- fillColor = value;
- _style = UIStyle.Custom;
- Invalidate();
- }
- }
- }
-
- private Color foreColor = UIFontColor.Primary;
-
- ///
- /// 填充颜色,当值为背景色或透明色或空值则不填充
- ///
- [Description("背景颜色"), Category("自定义")]
- [DefaultValue(typeof(Color), "48, 48, 48")]
- public override Color ForeColor
- {
- get => foreColor;
- set
- {
- if (foreColor != value)
- {
- foreColor = value;
- _style = UIStyle.Custom;
- Invalidate();
- }
- }
- }
-
- protected override void OnSizeChanged(EventArgs e)
- {
- base.OnSizeChanged(e);
- SetScrollInfo();
- }
-
- private void Bar_ValueChanged(object sender, EventArgs e)
- {
- ScrollBarInfo.SetScrollValue(Handle, Bar.Value);
- }
-
- [DefaultValue(false)]
- public bool StyleCustomMode { get; set; }
-
- private Color selectedColor = Color.FromArgb(80, 160, 255);
-
- private bool showTips;
-
- [Description("是否显示角标"), Category("自定义")]
- [DefaultValue(false)]
- public bool ShowTips
- {
- get => showTips;
- set
- {
- if (showTips != value)
- {
- showTips = value;
- Invalidate();
- }
- }
- }
-
- private Font tipsFont = new Font("Microsoft Sans Serif", 9);
-
- [Description("角标文字字体"), Category("自定义")]
- [DefaultValue(typeof(Font), "Microsoft Sans Serif, 9pt")]
- public Font TipsFont
- {
- get => tipsFont;
- set
- {
- if (!tipsFont.Equals(value))
- {
- tipsFont = value;
- Invalidate();
- }
- }
- }
-
- [DefaultValue(typeof(Color), "80, 160, 255")]
- public Color SelectedColor
- {
- get => selectedColor;
- set
- {
- if (selectedColor != value)
- {
- selectedColor = value;
- _style = UIStyle.Custom;
- Invalidate();
- }
- }
- }
-
- private Color selectedHighColor = UIColor.White;
-
- ///
- /// 边框颜色
- ///
- [Description("选中Tab页高亮"), Category("自定义")]
- [DefaultValue(typeof(Color), "White")]
- public Color SelectedHighColor
-
- {
- get => selectedHighColor;
- set
- {
- selectedHighColor = value;
- _style = UIStyle.Custom;
- Invalidate();
- }
- }
-
- private Color hoverColor = Color.FromArgb(155, 200, 255);
-
- [DefaultValue(typeof(Color), "155, 200, 255")]
- public Color HoverColor
- {
- get => hoverColor;
- set
- {
- hoverColor = value;
- _style = UIStyle.Custom;
- }
- }
-
- private UIStyle _style = UIStyle.Blue;
-
- [DefaultValue(UIStyle.Blue)]
- public UIStyle Style
- {
- get => _style;
- set => SetStyle(value);
- }
-
- private Color rectColor = UIStyles.Blue.RectColor;
-
- ///
- /// 边框颜色
- ///
- [Description("边框颜色"), Category("自定义")]
- [DefaultValue(typeof(Color), "80, 160, 255")]
- public Color RectColor
- {
- get => rectColor;
- set => SetRectColor(value);
- }
-
- ///
- /// 设置边框颜色
- ///
- /// 颜色
- private void SetRectColor(Color value)
- {
- if (rectColor != value)
- {
- rectColor = value;
- _style = UIStyle.Custom;
- Invalidate();
- }
- }
-
- public void SetStyle(UIStyle style)
- {
- SetStyleColor(UIStyles.GetStyleColor(style));
- _style = style;
- }
-
- public void SetStyleColor(UIBaseStyle uiColor)
+ public override void SetStyleColor(UIBaseStyle uiColor)
{
if (uiColor.IsCustom()) return;
- selectedForeColor = selectedHighColor = UIColor.White;
-
- rectColor = uiColor.RectColor;
- fillColor = UIColor.White;
- selectedColor = uiColor.TreeViewSelectedColor;
- foreColor = UIFontColor.Primary;
- hoverColor = uiColor.TreeViewHoverColor;
+ if (view != null)
+ {
+ view.SelectedForeColor = UIColor.White;
+ rectColor = uiColor.RectColor;
+ view.BackColor = fillColor = UIColor.White;
+ view.SelectedColor = uiColor.TreeViewSelectedColor;
+ view.ForeColor = foreColor = UIFontColor.Primary;
+ view.HoverColor = uiColor.TreeViewHoverColor;
+ }
if (Bar != null)
{
@@ -262,254 +81,360 @@ namespace Sunny.UI
}
Invalidate();
-
- Invalidate();
}
- private Color selectedForeColor = UIColor.White;
-
- [DefaultValue(typeof(Color), "White")]
- public Color SelectedForeColor
+ protected override void AfterSetFillColor(Color color)
{
- get => selectedForeColor;
- set
+ base.AfterSetFillColor(color);
+ if (view != null)
{
- if (selectedForeColor != value)
- {
- selectedForeColor = value;
- _style = UIStyle.Custom;
- Invalidate();
- }
+ view.FillColor = color;
}
}
- private bool ScrollBarVisible;
-
- private TreeNode CurrentNode;
-
- protected override void OnMouseMove(MouseEventArgs e)
+ [DefaultValue(TreeViewDrawMode.OwnerDrawAll)]
+ public TreeViewDrawMode DrawMode
{
- base.OnMouseMove(e);
- TreeNode node = GetNodeAt(e.Location);
- if (node == null || CurrentNode == node)
- {
- return;
- }
-
- Graphics g = CreateGraphics();
- if (CurrentNode != null)
- {
- OnDrawNode(new DrawTreeNodeEventArgs(g, CurrentNode, new Rectangle(0, CurrentNode.Bounds.Y, Width, CurrentNode.Bounds.Height), TreeNodeStates.Default));
- }
-
- CurrentNode = node;
- OnDrawNode(new DrawTreeNodeEventArgs(g, CurrentNode, new Rectangle(0, CurrentNode.Bounds.Y, Width, CurrentNode.Bounds.Height), TreeNodeStates.Hot));
- g.Dispose();
+ get => view.DrawMode;
+ set => view.DrawMode = value;
}
- protected override void OnMouseLeave(EventArgs e)
+ [DefaultValue(false)]
+ public bool CheckBoxes
{
- Graphics g = CreateGraphics();
- if (CurrentNode != null)
- {
- OnDrawNode(new DrawTreeNodeEventArgs(g, CurrentNode, new Rectangle(0, CurrentNode.Bounds.Y, Width, CurrentNode.Bounds.Height), TreeNodeStates.Default));
- CurrentNode = null;
- }
-
- g.Dispose();
+ get => view.CheckBoxes;
+ set => view.CheckBoxes = value;
}
- private bool checkBoxes;
+ [DefaultValue(false)]
+ public bool ShowLines
+ {
+ get => view.ShowLinesEx;
+ set => view.ShowLinesEx = value;
+ }
+
+ [DefaultValue(28)]
+ public int ItemHeight
+ {
+ get => view.ItemHeight;
+ set => view.ItemHeight = value;
+ }
[Browsable(false)]
- public new bool CheckBoxes
+ public TreeNode SelectedNode
{
- get => checkBoxes;
- set => checkBoxes = false;
+ get => view.SelectedNode;
+ set => view.SelectedNode = value;
}
- private readonly NavMenuHelper MenuHelper = new NavMenuHelper();
-
- protected override void OnDrawNode(DrawTreeNodeEventArgs e)
+ [DefaultValue(true)]
+ public bool HideSelection
{
- if (BorderStyle == BorderStyle.Fixed3D)
- {
- BorderStyle = BorderStyle.FixedSingle;
- }
-
- SetScrollInfo();
- CheckBoxes = false;
-
- if (e.Node == null || (e.Node.Bounds.Width <= 0 && e.Node.Bounds.Height <= 0 && e.Node.Bounds.X <= 0 && e.Node.Bounds.Y <= 0))
- {
- e.DrawDefault = true;
- }
- else
- {
- int drawLeft = (e.Node.Level + 1) * 19 + 3;
- int imageLeft = drawLeft;
- bool haveImage = false;
-
- if (MenuHelper.GetSymbol(e.Node) > 0)
- {
- haveImage = true;
- drawLeft += MenuHelper.GetSymbolSize(e.Node) + 6;
- }
- else
- {
- if (ImageList != null && ImageList.Images.Count > 0 && e.Node.ImageIndex >= 0 && e.Node.ImageIndex < ImageList.Images.Count)
- {
- haveImage = true;
- drawLeft += ImageList.ImageSize.Width + 6;
- }
- }
-
- SizeF sf = e.Graphics.MeasureString(e.Node.Text, Font);
- if (e.Node == SelectedNode)
- {
- e.Graphics.FillRectangle((e.State & TreeNodeStates.Hot) != 0 ? HoverColor : SelectedColor,
- new Rectangle(new Point(0, e.Node.Bounds.Y), new Size(Width, e.Node.Bounds.Height)));
-
- e.Graphics.DrawString(e.Node.Text, Font, SelectedForeColor, drawLeft, e.Bounds.Y + (ItemHeight - sf.Height) / 2.0f);
- }
- else if (e.Node == CurrentNode && (e.State & TreeNodeStates.Hot) != 0)
- {
- e.Graphics.FillRectangle(HoverColor, new Rectangle(new Point(0, e.Node.Bounds.Y), new Size(Width, e.Node.Bounds.Height)));
- e.Graphics.DrawString(e.Node.Text, Font, ForeColor, drawLeft, e.Bounds.Y + (ItemHeight - sf.Height) / 2.0f);
- }
- else
- {
- e.Graphics.FillRectangle(fillColor, new Rectangle(new Point(0, e.Node.Bounds.Y), new Size(Width, e.Node.Bounds.Height)));
- e.Graphics.DrawString(e.Node.Text, Font, ForeColor, drawLeft, e.Bounds.Y + (ItemHeight - sf.Height) / 2.0f);
- }
-
- if (haveImage)
- {
- if (MenuHelper.GetSymbol(e.Node) > 0)
- {
- SizeF fiSize = e.Graphics.GetFontImageSize(MenuHelper.GetSymbol(e.Node), MenuHelper.GetSymbolSize(e.Node));
- e.Graphics.DrawFontImage(MenuHelper.GetSymbol(e.Node), MenuHelper.GetSymbolSize(e.Node), Color.White,
- imageLeft + (MenuHelper.GetSymbolSize(e.Node) - fiSize.Width) / 2.0f, e.Bounds.Y + (e.Bounds.Height - fiSize.Height) / 2);
- }
- else
- {
- if (TreeNodeSelected(e) && e.Node.SelectedImageIndex >= 0 && e.Node.SelectedImageIndex < ImageList.Images.Count)
- e.Graphics.DrawImage(ImageList.Images[e.Node.SelectedImageIndex], imageLeft, e.Bounds.Y + (e.Bounds.Height - ImageList.ImageSize.Height) / 2);
- else
- e.Graphics.DrawImage(ImageList.Images[e.Node.ImageIndex], imageLeft, e.Bounds.Y + (e.Bounds.Height - ImageList.ImageSize.Height) / 2);
- }
- }
-
- int lineY = e.Bounds.Y + e.Node.Bounds.Height / 2 - 1;
- int lineX = 3 + e.Node.Level * 19 + 9;
-
- try
- {
- //绘制虚线
- Pen pn = new Pen(UIFontColor.Primary);
- pn.DashStyle = DashStyle.Dot;
- e.Graphics.DrawLine(pn, lineX, lineY, lineX + 10, lineY);
-
- if (e.Node.Level >= 1)
- {
- e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Bounds.Top);
- if (e.Node.NextNode != null)
- {
- e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Bottom);
- }
-
- TreeNode pNode = e.Node.Parent;
- while (pNode != null)
- {
- lineX -= 19;
-
- if (pNode.Level == 0 && pNode.NextNode != null)
- {
- e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Top);
- }
-
- if (pNode.NextNode != null)
- {
- e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Bottom);
- }
-
- pNode = pNode.Parent;
- }
- }
- else
- {
- if (e.Node.PrevNode != null)
- {
- e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Top);
- }
-
- if (e.Node.NextNode != null)
- {
- e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Bottom);
- }
- }
-
- pn.Dispose();
- }
- catch (Exception exception)
- {
- Console.WriteLine(exception);
- }
-
- lineX = 3 + e.Node.Level * 19 + 9;
- //绘制左侧+号
- if (e.Node.Nodes.Count > 0)
- {
- e.Graphics.FillRectangle(Color.White, new Rectangle(lineX - 4, lineY - 4, 8, 8));
- e.Graphics.DrawRectangle(UIFontColor.Primary, new Rectangle(lineX - 4, lineY - 4, 8, 8));
- e.Graphics.DrawLine(UIFontColor.Primary, lineX - 2, lineY, lineX + 2, lineY);
- if (!e.Node.IsExpanded)
- {
- e.Graphics.DrawLine(UIFontColor.Primary, lineX, lineY - 2, lineX, lineY + 2);
- }
- }
-
- if (ShowTips && MenuHelper.GetTipsText(e.Node).IsValid())
- {
- SizeF tipsSize = e.Graphics.MeasureString(MenuHelper.GetTipsText(e.Node), TipsFont);
- float sfMax = Math.Max(tipsSize.Width, tipsSize.Height) + 1;
- float tipsLeft = Width - (ScrollBarVisible ? 50 : 30) - 6 - sfMax;
- float tipsTop = e.Bounds.Y + (ItemHeight - sfMax) / 2;
-
- e.Graphics.FillEllipse(Color.Red, tipsLeft, tipsTop, sfMax, sfMax);
- e.Graphics.DrawString(MenuHelper.GetTipsText(e.Node), TipsFont, Color.White, tipsLeft + sfMax / 2.0f - tipsSize.Width / 2.0f, tipsTop + sfMax / 2.0f - tipsSize.Height / 2.0f);
- }
- }
+ get => view.HideSelection;
+ set => view.HideSelection = value;
}
- private bool TreeNodeSelected(DrawTreeNodeEventArgs e)
+ [DefaultValue(-1)]
+ [Localizable(true)]
+ [RefreshProperties(RefreshProperties.Repaint)]
+ [TypeConverter(typeof(NoneExcludedImageIndexConverter))]
+ [Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
+ typeof(UITypeEditor))]
+ [RelatedImageList("ImageList")]
+ public int ImageIndex
{
- return e.State == TreeNodeStates.Selected || e.State == TreeNodeStates.Focused ||
- e.State == (TreeNodeStates.Focused | TreeNodeStates.Selected);
+ get => view.ImageIndex;
+ set => view.ImageIndex = value;
}
- public string Version { get; }
-
- protected override void OnNodeMouseClick(TreeNodeMouseClickEventArgs e)
+ [Localizable(true)]
+ [TypeConverter(typeof(ImageKeyConverter))]
+ [Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
+ typeof(UITypeEditor))]
+ [DefaultValue("")]
+ [RefreshProperties(RefreshProperties.Repaint)]
+ [RelatedImageList("ImageList")]
+ public string ImageKey
{
- base.OnNodeMouseClick(e);
+ get => view.ImageKey;
+ set => view.ImageKey = value;
+ }
- if (e.Node != null && e.Node.Nodes.Count > 0)
- {
- if (e.X >= (e.Node.Level + 1) * 19 + 3)
- {
- if (e.Node.IsExpanded)
- {
- e.Node.Collapse();
- }
- else
- {
- e.Node.Expand();
- }
- }
- }
+ [DefaultValue(null)]
+ [RefreshProperties(RefreshProperties.Repaint)]
+ public ImageList ImageList
+ {
+ get => view.ImageList;
+ set => view.ImageList = value;
+ }
- SelectedNode = e.Node;
+ [DefaultValue(null)]
+ public ImageList StateImageList
+ {
+ get => view.StateImageList;
+ set => view.StateImageList = value;
+ }
+
+ [Localizable(true)]
+ [DefaultValue(19)]
+ public int Indent
+ {
+ get => view.Indent;
+ set => view.Indent = value;
+ }
+
+ [DefaultValue(typeof(Color), "Black")]
+ public Color LineColor
+ {
+ get => view.LineColor;
+ set => view.LineColor = value;
+ }
+
+ [DefaultValue("\\")]
+ public string PathSeparator
+ {
+ get => view.PathSeparator;
+ set => view.PathSeparator = value;
+ }
+
+ [DefaultValue(-1)]
+ [TypeConverter(typeof(NoneExcludedImageIndexConverter))]
+ [Localizable(true)]
+ [Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
+ typeof(UITypeEditor))]
+ [RelatedImageList("ImageList")]
+ public int SelectedImageIndex
+ {
+ get => view.SelectedImageIndex;
+ set => view.SelectedImageIndex = value;
+ }
+
+ [Localizable(true)]
+ [TypeConverter(typeof(ImageKeyConverter))]
+ [Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
+ typeof(UITypeEditor))]
+ [DefaultValue("")]
+ [RefreshProperties(RefreshProperties.Repaint)]
+ [RelatedImageList("ImageList")]
+ public string SelectedImageKey
+ {
+ get => view.SelectedImageKey;
+ set => view.SelectedImageKey = value;
+ }
+
+ [DefaultValue(false)]
+ public bool ShowNodeToolTips
+ {
+ get => view.ShowNodeToolTips;
+ set => view.ShowNodeToolTips = value;
+ }
+
+ [DefaultValue(true)]
+ public bool ShowPlusMinus
+ {
+ get => view.ShowPlusMinus;
+ set => view.ShowPlusMinus = value;
+ }
+
+ [DefaultValue(false)]
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool Sorted
+ {
+ get => view.Sorted;
+ set => view.Sorted = value;
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public IComparer TreeViewNodeSorter
+ {
+ get => view.TreeViewNodeSorter;
+ set => view.TreeViewNodeSorter = value;
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public TreeNode TopNode
+ {
+ get => view.TopNode;
+ set => view.TopNode = value;
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public int VisibleCount => view.VisibleCount;
+
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
+ [Localizable(true)]
+ [MergableProperty(false)]
+ public TreeNodeCollection Nodes => view.Nodes;
+
+ public event TreeViewCancelEventHandler BeforeCheck;
+
+ public event TreeViewEventHandler AfterCheck;
+
+ public event TreeViewCancelEventHandler BeforeCollapse;
+
+ public event TreeViewEventHandler AfterCollapse;
+
+ public event TreeViewCancelEventHandler BeforeExpand;
+
+ public event TreeViewEventHandler AfterExpand;
+
+ public event DrawTreeNodeEventHandler DrawNode;
+
+ public event ItemDragEventHandler ItemDrag;
+
+ public event TreeNodeMouseHoverEventHandler NodeMouseHover;
+
+ public event TreeViewCancelEventHandler BeforeSelect;
+
+ public event TreeViewEventHandler AfterSelect;
+
+ public event TreeNodeMouseClickEventHandler NodeMouseClick;
+
+ public event TreeNodeMouseClickEventHandler NodeMouseDoubleClick;
+
+ private void View_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
+ {
+ NodeMouseDoubleClick?.Invoke(sender, e);
+ }
+
+ private void View_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
+ {
+ NodeMouseClick?.Invoke(sender, e);
+ }
+
+ private void View_AfterSelect(object sender, TreeViewEventArgs e)
+ {
+ AfterSelect?.Invoke(sender, e);
+ }
+
+ private void View_BeforeSelect(object sender, TreeViewCancelEventArgs e)
+ {
+ BeforeSelect?.Invoke(sender, e);
+ }
+
+ private void View_NodeMouseHover(object sender, TreeNodeMouseHoverEventArgs e)
+ {
+ NodeMouseHover?.Invoke(sender, e);
+ }
+
+ private void View_ItemDrag(object sender, ItemDragEventArgs e)
+ {
+ ItemDrag?.Invoke(sender, e);
+ }
+
+ private void View_DrawNode(object sender, DrawTreeNodeEventArgs e)
+ {
+ DrawNode?.Invoke(sender, e);
+ }
+
+ private void View_AfterExpand(object sender, TreeViewEventArgs e)
+ {
+ AfterExpand?.Invoke(sender, e);
+ }
+
+ private void View_BeforeExpand(object sender, TreeViewCancelEventArgs e)
+ {
+ BeforeExpand?.Invoke(sender, e);
+ }
+
+ private void View_AfterCollapse(object sender, TreeViewEventArgs e)
+ {
+ AfterCollapse?.Invoke(sender, e);
+ }
+
+ private void View_BeforeCollapse(object sender, TreeViewCancelEventArgs e)
+ {
+ BeforeCollapse?.Invoke(sender, e);
+ }
+
+ private void View_AfterCheck(object sender, TreeViewEventArgs e)
+ {
+ AfterCheck?.Invoke(sender, e);
+ }
+
+ private void View_BeforeCheck(object sender, TreeViewCancelEventArgs e)
+ {
+ BeforeCheck?.Invoke(sender, e);
+ }
+
+ public void BeginUpdate()
+ {
+ view.BeginUpdate();
+ }
+
+ public void CollapseAll()
+ {
+ view.CollapseAll();
+ }
+
+ public void EndUpdate()
+ {
+ view.EndUpdate();
+ }
+
+ public void ExpandAll()
+ {
+ view.ExpandAll();
+ }
+
+ public TreeViewHitTestInfo HitTest(Point pt)
+ {
+ return view.HitTest(pt);
+ }
+
+ public TreeViewHitTestInfo HitTest(int x, int y)
+ {
+ return view.HitTest(x, y);
+ }
+
+ public int GetNodeCount(bool includeSubTrees)
+ {
+ return view.GetNodeCount(includeSubTrees);
+ }
+
+ public TreeNode GetNodeAt(Point pt)
+ {
+ return view.GetNodeAt(pt);
+ }
+
+ public TreeNode GetNodeAt(int x, int y)
+ {
+ return view.GetNodeAt(x, y);
+ }
+
+ public override string ToString()
+ {
+ return view.ToString();
+ }
+
+ public void Sort()
+ {
+ view.Sort();
+ }
+
+ private void SetPos()
+ {
+ if (view == null) return;
+ view.Left = 2;
+ view.Top = 2;
+ view.Width = Width - 4;
+ view.Height = Height - 4;
+
+ if (Bar == null) return;
+ Bar.Top = 2;
+ Bar.Left = Width - ScrollBarInfo.VerticalScrollBarWidth() - 2;
+ Bar.Width = ScrollBarInfo.VerticalScrollBarWidth();
+ Bar.Height = Height - 4;
+ }
+
+ protected override void OnFontChanged(EventArgs e)
+ {
+ base.OnFontChanged(e);
+ if (view != null) view.Font = Font;
}
protected override void OnMouseWheel(MouseEventArgs e)
@@ -517,26 +442,32 @@ namespace Sunny.UI
base.OnMouseWheel(e);
if (e.Delta > 10)
- {
- ScrollBarInfo.ScrollUp(Handle);
- }
- else if (e.Delta < -10)
- {
- ScrollBarInfo.ScrollDown(Handle);
- }
+ ScrollBarInfo.ScrollUp(view.Handle);
+ else if (e.Delta < -10) ScrollBarInfo.ScrollDown(view.Handle);
SetScrollInfo();
}
+ protected override void OnSizeChanged(EventArgs e)
+ {
+ base.OnSizeChanged(e);
+ SetScrollInfo();
+ SetPos();
+ }
+
public void SetScrollInfo()
{
+ if (view == null || Bar == null) return;
+
if (Nodes.Count == 0)
{
Bar.Visible = false;
return;
}
- var si = ScrollBarInfo.GetInfo(Handle);
+ var si = ScrollBarInfo.GetInfo(view.Handle);
+
+ SetPos();
Bar.Maximum = si.ScrollMax;
Bar.Visible = si.ScrollMax > 0 && si.nMax > 0 && si.nPage > 0;
Bar.Value = si.nPos;
@@ -549,31 +480,294 @@ namespace Sunny.UI
}
}
- protected override void OnAfterExpand(TreeViewEventArgs e)
+ private void InitializeComponent()
+ {
+ view = new TreeViewEx();
+ Bar = new UIScrollBar();
+ SuspendLayout();
+ //
+ // view
+ //
+ view.BackColor = Color.White;
+ view.BorderStyle = BorderStyle.None;
+ view.CheckBoxes = true;
+ view.DrawMode = TreeViewDrawMode.OwnerDrawAll;
+ view.ForeColor = Color.FromArgb(48, 48, 48);
+ view.FullRowSelect = true;
+ view.ItemHeight = 28;
+ view.Location = new Point(2, 2);
+ view.Name = "view";
+ view.ShowLines = false;
+ view.Size = new Size(266, 176);
+ view.TabIndex = 0;
+ view.AfterCollapse += view_AfterCollapse;
+ view.AfterExpand += view_AfterExpand;
+ view.DrawNode += view_DrawNode;
+ //
+ // Bar
+ //
+ Bar.Font = new Font("微软雅黑", 12F);
+ Bar.Location = new Point(247, 3);
+ Bar.Name = "Bar";
+ Bar.Size = new Size(19, 173);
+ Bar.Style = UIStyle.Custom;
+ Bar.StyleCustomMode = true;
+ Bar.TabIndex = 2;
+ Bar.Visible = false;
+ Bar.ValueChanged += Bar_ValueChanged;
+ //
+ // UITreeViewEx
+ //
+ Controls.Add(Bar);
+ Controls.Add(view);
+ FillColor = Color.White;
+ Style = UIStyle.Custom;
+ ResumeLayout(false);
+ }
+
+ private void Bar_ValueChanged(object sender, EventArgs e)
+ {
+ ScrollBarInfo.SetScrollValue(view.Handle, Bar.Value);
+ }
+
+ private void view_AfterExpand(object sender, TreeViewEventArgs e)
{
- base.OnAfterExpand(e);
SetScrollInfo();
}
- protected override void OnAfterCollapse(TreeViewEventArgs e)
+ private void view_AfterCollapse(object sender, TreeViewEventArgs e)
{
- base.OnAfterCollapse(e);
SetScrollInfo();
}
- protected override void WndProc(ref Message m)
+ private void view_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
- base.WndProc(ref m);
+ SetScrollInfo();
+ }
- if (IsDisposed || Disposing) return;
- ScrollBarInfo.ShowScrollBar(Handle, 3, false);
- if (m.Msg == 0xf || m.Msg == 0x133)
+ internal sealed class NoneExcludedImageIndexConverter : ImageIndexConverter
+ {
+ protected override bool IncludeNoneAsStandardValue => false;
+ }
+
+ internal class TreeViewEx : TreeView
+ {
+ private TreeNode CurrentNode;
+
+ private bool showLines;
+
+ public TreeViewEx()
{
- if (BorderStyle == BorderStyle.FixedSingle)
+ DrawMode = TreeViewDrawMode.OwnerDrawAll;
+ base.DoubleBuffered = true;
+ }
+
+ [DefaultValue(typeof(Color), "155, 200, 255")]
+ public Color HoverColor { get; set; } = Color.FromArgb(155, 200, 255);
+
+ public Color SelectedColor { get; set; } = Color.FromArgb(80, 160, 255);
+
+ public Color SelectedForeColor { get; set; } = Color.White;
+
+ public Color FillColor { get; set; } = Color.White;
+
+ public bool ShowLinesEx
+ {
+ get => showLines;
+ set
{
- ControlEx.ResetBorderColor(m, this, 1, Enabled ? RectColor : UIStyles.Blue.RectDisableColor);
+ showLines = value;
+ Invalidate();
}
}
+
+ protected override void OnMouseMove(MouseEventArgs e)
+ {
+ base.OnMouseMove(e);
+ var node = GetNodeAt(e.Location);
+ if (node == null || CurrentNode == node) return;
+
+ var g = CreateGraphics();
+ if (CurrentNode != null)
+ OnDrawNode(new DrawTreeNodeEventArgs(g, CurrentNode,
+ new Rectangle(0, CurrentNode.Bounds.Y, Width, CurrentNode.Bounds.Height),
+ TreeNodeStates.Default));
+
+ CurrentNode = node;
+ OnDrawNode(new DrawTreeNodeEventArgs(g, CurrentNode,
+ new Rectangle(0, CurrentNode.Bounds.Y, Width, CurrentNode.Bounds.Height), TreeNodeStates.Hot));
+ g.Dispose();
+ }
+
+ protected override void OnMouseLeave(EventArgs e)
+ {
+ var g = CreateGraphics();
+ if (CurrentNode != null)
+ {
+ OnDrawNode(new DrawTreeNodeEventArgs(g, CurrentNode,
+ new Rectangle(0, CurrentNode.Bounds.Y, Width, CurrentNode.Bounds.Height),
+ TreeNodeStates.Default));
+ CurrentNode = null;
+ }
+
+ g.Dispose();
+ }
+
+ protected override void OnDrawNode(DrawTreeNodeEventArgs e)
+ {
+ base.OnDrawNode(e);
+
+ if (BorderStyle == BorderStyle.Fixed3D) BorderStyle = BorderStyle.FixedSingle;
+
+ if (e.Node == null || e.Node.Bounds.Width <= 0 && e.Node.Bounds.Height <= 0 && e.Node.Bounds.X <= 0 &&
+ e.Node.Bounds.Y <= 0)
+ {
+ e.DrawDefault = true;
+ }
+ else
+ {
+ var drawLeft = (e.Node.Level + 1) * Indent + 3;
+ var checkBoxLeft = (e.Node.Level + 1) * Indent + 3;
+ var imageLeft = drawLeft;
+ var haveImage = false;
+ var sf = e.Graphics.MeasureString(e.Node.Text, Font);
+
+ if (CheckBoxes) drawLeft += 16;
+
+ if (ImageList != null && ImageList.Images.Count > 0 && e.Node.ImageIndex >= 0 &&
+ e.Node.ImageIndex < ImageList.Images.Count)
+ {
+ haveImage = true;
+ drawLeft += ImageList.ImageSize.Width + 6;
+ }
+
+ var checkboxColor = ForeColor;
+ if (e.Node == SelectedNode)
+ {
+ e.Graphics.FillRectangle((e.State & TreeNodeStates.Hot) != 0 ? HoverColor : SelectedColor,
+ new Rectangle(new Point(0, e.Node.Bounds.Y), new Size(Width, e.Node.Bounds.Height)));
+
+ e.Graphics.DrawString(e.Node.Text, Font, SelectedForeColor, drawLeft,
+ e.Bounds.Y + (ItemHeight - sf.Height) / 2.0f);
+
+ checkboxColor = SelectedForeColor;
+ }
+ else if (e.Node == CurrentNode && (e.State & TreeNodeStates.Hot) != 0)
+ {
+ e.Graphics.FillRectangle(HoverColor,
+ new Rectangle(new Point(0, e.Node.Bounds.Y), new Size(Width, e.Node.Bounds.Height)));
+ e.Graphics.DrawString(e.Node.Text, Font, ForeColor, drawLeft,
+ e.Bounds.Y + (ItemHeight - sf.Height) / 2.0f);
+ }
+ else
+ {
+ e.Graphics.FillRectangle(FillColor,
+ new Rectangle(new Point(0, e.Node.Bounds.Y), new Size(Width, e.Node.Bounds.Height)));
+ e.Graphics.DrawString(e.Node.Text, Font, ForeColor, drawLeft,
+ e.Bounds.Y + (ItemHeight - sf.Height) / 2.0f);
+ }
+
+ if (haveImage)
+ {
+ if (TreeNodeSelected(e) && e.Node.SelectedImageIndex >= 0 &&
+ e.Node.SelectedImageIndex < ImageList.Images.Count)
+ e.Graphics.DrawImage(ImageList.Images[e.Node.SelectedImageIndex], imageLeft,
+ e.Bounds.Y + (e.Bounds.Height - ImageList.ImageSize.Height) / 2);
+ else
+ e.Graphics.DrawImage(ImageList.Images[e.Node.ImageIndex], imageLeft,
+ e.Bounds.Y + (e.Bounds.Height - ImageList.ImageSize.Height) / 2);
+ }
+
+ if (CheckBoxes)
+ {
+ if (!e.Node.Checked)
+ using (var pn = new Pen(checkboxColor, 1))
+ {
+ e.Graphics.DrawRectangle(pn,
+ new Rectangle(checkBoxLeft + 2, e.Bounds.Y + (ItemHeight - 12) / 2 - 1, 12, 12));
+ }
+ else
+ using (var pn = new Pen(checkboxColor, 2))
+ {
+ var pt1 = new Point(checkBoxLeft + 2 + 2, e.Bounds.Y + (ItemHeight - 12) / 2 - 1 + 5);
+ var pt2 = new Point(pt1.X + 3, pt1.Y + 3);
+ var pt3 = new Point(pt2.X + 5, pt2.Y - 5);
+
+ PointF[] CheckMarkLine = { pt1, pt2, pt3 };
+
+ e.Graphics.SetHighQuality();
+ e.Graphics.DrawLines(pn, CheckMarkLine);
+ e.Graphics.SetDefaultQuality();
+ e.Graphics.DrawRectangle(checkboxColor,
+ new Rectangle(checkBoxLeft + 2, e.Bounds.Y + (ItemHeight - 12) / 2 - 1, 12, 12));
+ }
+ }
+
+ var lineY = e.Bounds.Y + e.Node.Bounds.Height / 2 - 1;
+ var lineX = 3 + e.Node.Level * Indent + 9;
+
+ if (ShowLinesEx)
+ try
+ {
+ //绘制虚线
+ var pn = new Pen(LineColor);
+ pn.DashStyle = DashStyle.Dot;
+ e.Graphics.DrawLine(pn, lineX, lineY, lineX + 10, lineY);
+
+ if (e.Node.Level >= 1)
+ {
+ e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Bounds.Top);
+ if (e.Node.NextNode != null)
+ e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Bottom);
+
+ var pNode = e.Node.Parent;
+ while (pNode != null)
+ {
+ lineX -= Indent;
+
+ if (pNode.Level == 0 && pNode.NextNode != null)
+ e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Top);
+
+ if (pNode.NextNode != null)
+ e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Bottom);
+
+ pNode = pNode.Parent;
+ }
+ }
+ else
+ {
+ if (e.Node.PrevNode != null)
+ e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Top);
+
+ if (e.Node.NextNode != null)
+ e.Graphics.DrawLine(pn, lineX, lineY, lineX, e.Node.Bounds.Bottom);
+ }
+
+ pn.Dispose();
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine(exception);
+ }
+
+ lineX = 3 + e.Node.Level * Indent + 9;
+ //绘制左侧+号
+ if (ShowPlusMinus && e.Node.Nodes.Count > 0)
+ {
+ e.Graphics.FillRectangle(Color.White, new Rectangle(lineX - 4, lineY - 4, 8, 8));
+ e.Graphics.DrawRectangle(UIFontColor.Primary, new Rectangle(lineX - 4, lineY - 4, 8, 8));
+ e.Graphics.DrawLine(UIFontColor.Primary, lineX - 2, lineY, lineX + 2, lineY);
+ if (!e.Node.IsExpanded)
+ e.Graphics.DrawLine(UIFontColor.Primary, lineX, lineY - 2, lineX, lineY + 2);
+ }
+ }
+ }
+
+ private bool TreeNodeSelected(DrawTreeNodeEventArgs e)
+ {
+ return e.State == TreeNodeStates.Selected || e.State == TreeNodeStates.Focused ||
+ e.State == (TreeNodeStates.Focused | TreeNodeStates.Selected);
+ }
}
}
}
\ No newline at end of file