diff --git a/Bin/net40/SunnyUI.dll b/Bin/net40/SunnyUI.dll
index ec775cb2..21ce6ae4 100644
Binary files a/Bin/net40/SunnyUI.dll and b/Bin/net40/SunnyUI.dll differ
diff --git a/SunnyUI/Common/UControl.cs b/SunnyUI/Common/UControl.cs
index a3f61318..e625ebe1 100644
--- a/SunnyUI/Common/UControl.cs
+++ b/SunnyUI/Common/UControl.cs
@@ -43,6 +43,16 @@ namespace Sunny.UI
return timer;
}
+ public static bool IsNull(this Control ctrl)
+ {
+ return ctrl == null;
+ }
+
+ public static bool IsValid(this Control ctrl)
+ {
+ return ctrl != null;
+ }
+
public static Rectangle ScreenRectangle(this Control ctrl)
{
return ctrl.RectangleToScreen(ctrl.ClientRectangle);
diff --git a/SunnyUI/Common/UScrollBarInfo.cs b/SunnyUI/Common/UScrollBarInfo.cs
index 73606c40..30b619aa 100644
--- a/SunnyUI/Common/UScrollBarInfo.cs
+++ b/SunnyUI/Common/UScrollBarInfo.cs
@@ -65,6 +65,15 @@ namespace Sunny.UI
return si;
}
+ public static SCROLLINFO GetHorInfo(IntPtr handle)
+ {
+ SCROLLINFO si = new SCROLLINFO();
+ si.cbSize = Marshal.SizeOf(si);
+ si.fMask = SIF_DISABLENOSCROLL | SIF_ALL;
+ User.GetScrollInfo(handle, User.SB_HORZ, ref si);
+ return si;
+ }
+
///
/// 设置控件滚动条滚动值
///
@@ -78,6 +87,19 @@ namespace Sunny.UI
User.PostMessage(handle, User.WM_VSCROLL, MakeLong(User.SB_THUMBTRACK, highPart: (short)info.nPos), 0);
}
+ ///
+ /// 设置控件滚动条滚动值
+ ///
+ /// 控件句柄
+ /// 滚动值
+ public static void SetHorScrollValue(IntPtr handle, int value)
+ {
+ SCROLLINFO info = GetHorInfo(handle);
+ info.nPos = value;
+ User.SetScrollInfo(handle, User.SB_HORZ, ref info, true);
+ User.PostMessage(handle, User.WM_HSCROLL, MakeLong(User.SB_THUMBTRACK, highPart: (short)info.nPos), 0);
+ }
+
///
/// 控件向上滚动一个单位
///
@@ -101,5 +123,11 @@ namespace Sunny.UI
if (!ctrl.IsHandleCreated) return false;
return (Sunny.UI.Win32.User.GetWindowLong(ctrl.Handle, User.GWL_STYLE) & User.WS_VSCROLL) != 0;
}
+
+ public static bool IsHorizontalScrollBarVisible(Control ctrl)
+ {
+ if (!ctrl.IsHandleCreated) return false;
+ return (Sunny.UI.Win32.User.GetWindowLong(ctrl.Handle, User.GWL_STYLE) & User.WS_HSCROLL) != 0;
+ }
}
}
\ No newline at end of file
diff --git a/SunnyUI/Controls/UIHorScrollBar.cs b/SunnyUI/Controls/UIHorScrollBar.cs
index 179fda27..68a2f59c 100644
--- a/SunnyUI/Controls/UIHorScrollBar.cs
+++ b/SunnyUI/Controls/UIHorScrollBar.cs
@@ -273,7 +273,7 @@ namespace Sunny.UI
{
isScrollUp = up;
largeChange = large;
- timer.Start();
+ //timer.Start();
}
private void StopScroll()
@@ -297,7 +297,7 @@ namespace Sunny.UI
if (Value > 0)
{
left_state = DrawItemState.Selected;
- ScrollLeft(false);
+ ScrollLeft(true);
StartScroll(true, false);
}
break;
@@ -312,7 +312,7 @@ namespace Sunny.UI
if (Value < Maximum)
{
right_state = DrawItemState.Selected;
- ScrollRight(false);
+ ScrollRight(true);
StartScroll(false, false);
}
break;
@@ -331,7 +331,7 @@ namespace Sunny.UI
case 5:
if (Value < Maximum)
{
- ScrollRight(false);
+ ScrollRight(true);
if (IsPress)
{
StartScroll(false, true);
diff --git a/SunnyUI/Controls/UITreeView.cs b/SunnyUI/Controls/UITreeView.cs
index f6303509..56082a49 100644
--- a/SunnyUI/Controls/UITreeView.cs
+++ b/SunnyUI/Controls/UITreeView.cs
@@ -23,6 +23,7 @@
* 2021-08-26: V3.0.6 CheckBoxes增加三态,感谢群友:笑口常开
* 2022-01-05: V3.0.9 TreeNodeStateSync: 节点点击时同步父节点和子节点的状态
* 2022-03-19: V3.1.1 重构主题配色
+ * 2022-04-01: V3.1.2 增加水平滚动条
******************************************************************************/
using System;
@@ -43,8 +44,10 @@ namespace Sunny.UI
public sealed class UITreeView : UIPanel, IToolTip
{
private UIScrollBar Bar;
+ private UIHorScrollBar HBar;
private bool ScrollBarVisible;
+ private bool HScrollBarVisible;
private TreeViewEx view;
public UITreeView()
@@ -52,6 +55,7 @@ namespace Sunny.UI
InitializeComponent();
SetStyleFlags(true, false);
ShowText = false;
+ view.HBar = HBar;
SetScrollInfo();
view.BeforeCheck += View_BeforeCheck;
@@ -179,6 +183,14 @@ namespace Sunny.UI
Bar.HoverColor = uiColor.ButtonFillHoverColor;
Bar.PressColor = uiColor.ButtonFillPressColor;
}
+
+ if (HBar != null)
+ {
+ HBar.FillColor = uiColor.TreeViewBarFillColor;
+ HBar.ForeColor = uiColor.TreeViewBarForeColor;
+ HBar.HoverColor = uiColor.ButtonFillHoverColor;
+ HBar.PressColor = uiColor.ButtonFillPressColor;
+ }
}
protected override void AfterSetFillColor(Color color)
@@ -194,6 +206,11 @@ namespace Sunny.UI
{
Bar.FillColor = color;
}
+
+ if (HBar != null)
+ {
+ HBar.FillColor = color;
+ }
}
protected override void AfterSetForeColor(Color color)
@@ -535,11 +552,21 @@ namespace Sunny.UI
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;
+ if (Bar != null)
+ {
+ Bar.Top = 2;
+ Bar.Left = Width - ScrollBarInfo.VerticalScrollBarWidth() - 2;
+ Bar.Width = ScrollBarInfo.VerticalScrollBarWidth();
+ Bar.Height = Height - 4;
+ }
+
+ if (HBar != null)
+ {
+ HBar.Left = 2;
+ HBar.Top = Height - ScrollBarInfo.HorizontalScrollBarHeight() - 2;
+ HBar.Width = Width - (ScrollBarVisible ? ScrollBarInfo.VerticalScrollBarWidth() : 0) - 2 - 2;
+ HBar.Height = ScrollBarInfo.HorizontalScrollBarHeight();
+ }
}
protected override void OnFontChanged(EventArgs e)
@@ -572,7 +599,7 @@ namespace Sunny.UI
public void SetScrollInfo()
{
- if (view == null || Bar == null) return;
+ if (view == null || Bar == null || HBar == null) return;
if (Nodes.Count == 0)
{
@@ -581,8 +608,10 @@ namespace Sunny.UI
}
var si = ScrollBarInfo.GetInfo(view.Handle);
+ var si1 = ScrollBarInfo.GetHorInfo(view.Handle);
SetPos();
+
Bar.Maximum = si.ScrollMax;
Bar.Visible = si.ScrollMax > 0 && si.nMax > 0 && si.nPage > 0;
Bar.Value = si.nPos;
@@ -593,12 +622,24 @@ namespace Sunny.UI
ScrollBarVisible = Bar.Visible;
Invalidate();
}
+
+ HBar.Maximum = si1.ScrollMax;
+ HBar.Visible = si1.ScrollMax > 0 && si1.nMax > 0 && si1.nPage > 0;
+ HBar.Value = si1.nPos;
+ HBar.BringToFront();
+
+ if (HScrollBarVisible != HBar.Visible)
+ {
+ HScrollBarVisible = HBar.Visible;
+ Invalidate();
+ }
}
private void InitializeComponent()
{
view = new TreeViewEx();
Bar = new UIScrollBar();
+ HBar = new UIHorScrollBar();
SuspendLayout();
//
// view
@@ -630,9 +671,22 @@ namespace Sunny.UI
Bar.Visible = false;
Bar.ValueChanged += Bar_ValueChanged;
//
+ // HBar
+ //
+ HBar.Font = new Font("微软雅黑", 12F);
+ HBar.Location = new Point(247, 3);
+ HBar.Name = "HBar";
+ HBar.Size = new Size(173, 19);
+ HBar.Style = UIStyle.Custom;
+ HBar.StyleCustomMode = true;
+ HBar.TabIndex = 3;
+ HBar.Visible = false;
+ HBar.ValueChanged += HBar_ValueChanged;
+ //
// UITreeViewEx
//
Controls.Add(Bar);
+ Controls.Add(HBar);
Controls.Add(view);
FillColor = Color.White;
Style = UIStyle.Custom;
@@ -644,6 +698,12 @@ namespace Sunny.UI
ScrollBarInfo.SetScrollValue(view.Handle, Bar.Value);
}
+ private void HBar_ValueChanged(object sender, EventArgs e)
+ {
+ ScrollBarInfo.SetHorScrollValue(view.Handle, HBar.Value);
+ //view.Invalidate();
+ }
+
private void view_AfterExpand(object sender, TreeViewEventArgs e)
{
SetScrollInfo();
@@ -666,6 +726,8 @@ namespace Sunny.UI
internal class TreeViewEx : TreeView
{
+ public UIHorScrollBar HBar;
+
private TreeNode CurrentNode;
private bool showLines;
@@ -757,6 +819,7 @@ namespace Sunny.UI
{
DicNodeStatus.Add(e.Node.GetHashCode(), false);
}
+
if (CheckBoxes)
{
if (TreeNodeStateSync && e.Node.Parent != null && DicNodeStatus.ContainsKey(e.Node.Parent.GetHashCode()) && !DicNodeStatus[e.Node.Parent.GetHashCode()])
@@ -764,7 +827,11 @@ namespace Sunny.UI
SetParentNodeCheckedState(e.Node);
}
}
- if (BorderStyle == BorderStyle.Fixed3D) BorderStyle = BorderStyle.FixedSingle;
+
+ 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)
{
@@ -772,9 +839,13 @@ namespace Sunny.UI
}
else
{
+ int drawLeft;
+ if (!HBar.Visible)
+ drawLeft = e.Bounds.X + (e.Node.Level + 1) * Indent + 3;
+ else
+ drawLeft = -(int)(Width * HBar.Value * 1.0 / HBar.Maximum) + (e.Node.Level + 1) * Indent + 3;
- var drawLeft = (e.Node.Level + 1) * Indent + 3;
- var checkBoxLeft = (e.Node.Level + 1) * Indent + 1;
+ var checkBoxLeft = drawLeft - 2;
var imageLeft = drawLeft;
var haveImage = false;
var sf = e.Graphics.MeasureString(e.Node.Text, Font);
@@ -785,8 +856,7 @@ namespace Sunny.UI
imageLeft += 16;
}
- if (ImageList != null && ImageList.Images.Count > 0 && e.Node.ImageIndex >= 0 &&
- e.Node.ImageIndex < ImageList.Images.Count)
+ if (ImageList != null && ImageList.Images.Count > 0 && e.Node.ImageIndex >= 0 && e.Node.ImageIndex < ImageList.Images.Count)
{
haveImage = true;
drawLeft += ImageList.ImageSize.Width + 6;
@@ -834,8 +904,6 @@ namespace Sunny.UI
if (CheckBoxes)
{
-
-
if (!e.Node.Checked)
{
e.Graphics.DrawRectangle(checkboxColor,
@@ -872,7 +940,11 @@ namespace Sunny.UI
}
var lineY = e.Bounds.Y + e.Node.Bounds.Height / 2 - 1;
- var lineX = 3 + e.Node.Level * Indent + 9;
+ int lineX;
+ if (!HBar.Visible)
+ lineX = 3 + e.Node.Level * Indent + 9;
+ else
+ lineX = -(int)(Width * HBar.Value * 1.0 / HBar.Maximum) + 3 + e.Node.Level * Indent + 9;
if (ShowLinesEx)
{
@@ -926,7 +998,11 @@ namespace Sunny.UI
}
}
- lineX = 3 + e.Node.Level * Indent + 9;
+ if (!HBar.Visible)
+ lineX = 3 + e.Node.Level * Indent + 9;
+ else
+ lineX = -(int)(Width * HBar.Value * 1.0 / HBar.Maximum) + 3 + e.Node.Level * Indent + 9;
+
//绘制左侧+号
if (ShowPlusMinus && e.Node.Nodes.Count > 0)
{
@@ -981,7 +1057,6 @@ namespace Sunny.UI
private void SetParentNodeCheckedState(TreeNode currNode, bool ByMouse = false)
{
-
if (currNode.Parent == null)
return;
TreeNode parentNode = currNode.Parent; //获得当前节点的父节点
@@ -1021,7 +1096,6 @@ namespace Sunny.UI
}
-
//选中节点之后,选中节点的所有子节点
private void SetChildNodeCheckedState(TreeNode currNode, bool state)
{