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) {