如何在SplitContainer的Splitter中添加抓柄

SplitContainer的分割条中曾经有3个点。 就像StackOverflow上有三行问题详细信息文本框一样,可以抓住它。 如何使用.NET中SplitContainer的分割条执行此操作?

并不是说我对Alex的答案有任何反对意见,但我认为我会分享这个解决方案,因为它对我来说看起来更好一点(无论如何在XP机器上?)。

private void SplitContainer_Paint(object sender, PaintEventArgs e) { var control = sender as SplitContainer; //paint the three dots' Point[] points = new Point[3]; var w = control.Width; var h = control.Height; var d = control.SplitterDistance; var sW = control.SplitterWidth; //calculate the position of the points' if (control.Orientation == Orientation.Horizontal) { points[0] = new Point((w / 2), d + (sW / 2)); points[1] = new Point(points[0].X - 10, points[0].Y); points[2] = new Point(points[0].X + 10, points[0].Y); } else { points[0] = new Point(d + (sW / 2), (h / 2)); points[1] = new Point(points[0].X, points[0].Y - 10); points[2] = new Point(points[0].X, points[0].Y + 10); } foreach (Point p in points) { p.Offset(-2, -2); e.Graphics.FillEllipse(SystemBrushes.ControlDark, new Rectangle(p, new Size(3, 3))); p.Offset(1, 1); e.Graphics.FillEllipse(SystemBrushes.ControlLight, new Rectangle(p, new Size(3, 3))); } } 

希望这能让人高兴吗? 哈阿!

那没有实现。 如果您喜欢该function,最好派生SplitContainer并覆盖OnPaint方法。


更新1

这里有一些代码可以满足您的要求。 它是在VB.NET中,点放置可以做一些调整。 总的来说,代码按预期工作。

 Imports System.Windows.Forms Imports System.ComponentModel Imports System.Drawing Public Class SplitContainerEx Inherits SplitContainer ''' Determines the thickness of the splitter.  _ Public Overridable Shadows Property SplitterWidth() As Integer Get Return MyBase.SplitterWidth End Get Set(ByVal value As Integer) If value < 5 Then value = 5 MyBase.SplitterWidth = value End Set End Property Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) MyBase.OnPaint(e) 'paint the three dots Dim points(2) As Point Dim pointRect = Rectangle.Empty 'calculate the position of the points If Orientation = Windows.Forms.Orientation.Horizontal Then points(0) = New Point((MyBase.Width \ 2), SplitterDistance + (SplitterWidth \ 2)) points(1) = New Point(points(0).X - 10, points(0).Y) points(2) = New Point(points(2).X + 10, points(0).Y) pointRect = New Rectangle(points(1).X - 2, points(1).Y - 2, 25, 5) Else points(0) = New Point(SplitterDistance + (SplitterWidth \ 2), (MyBase.Height \ 2)) points(1) = New Point(points(0).X, points(0).Y - 10) points(2) = New Point(points(0).X, points(0).Y + 10) pointRect = New Rectangle(points(1).X - 2, points(1).Y - 2, 5, 25) End If e.Graphics.FillRectangle(Brushes.Gray, pointRect) For Each p In points p.Offset(-1, -1) e.Graphics.FillEllipse(Brushes.Black, New Rectangle(p, New Size(3, 3))) Next End Sub End Class 

更新2

我提出了C#等价物,因为你标记了你的问题。
如果vb makes you sick ,请学会转向将VB.NET转换为C# - Developer Fusion并进行VB转换为C#。

 using System; using System.Diagnostics; using System.Windows.Forms; using System.ComponentModel; using System.Drawing; public class SplitContainerEx : SplitContainer { /// Determines the thickness of the splitter. [DefaultValue(typeof(int), "5"), Description("Determines the thickness of the splitter.")] public virtual new int SplitterWidth { get { return base.SplitterWidth; } set { if (value < 5) value = 5; base.SplitterWidth = value; } } protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { base.OnPaint(e); //paint the three dots Point[] points = new Point[3]; Rectangle pointRect = Rectangle.Empty; //calculate the position of the points if (Orientation == System.Windows.Forms.Orientation.Horizontal) { points[0] = new Point((int)(base.Width / 2), SplitterDistance + (int)(SplitterWidth / 2)); points[1] = new Point(points[0].X - 10, points[0].Y); points[2] = new Point(points[2].X + 10, points[0].Y); pointRect = new Rectangle(points[1].X - 2, points[1].Y - 2, 25, 5); } else { points[0] = new Point(SplitterDistance + (int)(SplitterWidth / 2), (int)(base.Height / 2)); points[1] = new Point(points[0].X, points[0].Y - 10); points[2] = new Point(points[0].X, points[0].Y + 10); pointRect = new Rectangle(points[1].X - 2, points[1].Y - 2, 5, 25); } e.Graphics.FillRectangle(Brushes.Gray, pointRect); foreach (Point p in points) { p.Offset(-1, -1); e.Graphics.FillEllipse(Brushes.Black, new Rectangle(p, new Size(3, 3))); } } } 

没有自己绘制的最接近的是将BorderStyle更改为Fixed3D 。 这将在两个面板之间给你一种“条形”。

如果您不喜欢两个面板本身的凹陷外观,可以通过将分割面板放在另一个面板中并将其Location设置为负值(例如-n,-n )来“隐藏”外边框。其尺寸为其父面板尺寸+ 2*n 。 然后我将Anchor设置为Top | Left | Bottom | Right Top | Left | Bottom | Right Top | Left | Bottom | Right以便在调整父面板大小时保持这种状态。

这是一种kludge,但我当然认为这样做,因为我讨厌没有迹象表明“抓点”在哪里。

我喜欢shousper和Alex的答案,但根据我的口味,它们似乎有点’复杂’; 似乎有更多我认为必要的代码。

Shaun的答案也有效(我也发现MSDN中有一个),但在我正在开发的应用程序中,’抓握把手’变得非常分散注意力,因为它们几乎填满了分离器,我们有很多。

所以我提出了这个,介于两者之间。 没有数组,没有新的矩形。 对于“接受”答案中的“3D”效果,只需要很少的额外工作,但3个普通点对我有用:

 protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { base.OnPaint(e); Point centerPoint = new Point(SplitterRectangle.Left - 1 + SplitterRectangle.Width / 2, SplitterRectangle.Top - 1 + SplitterRectangle.Height / 2); e.Graphics.FillEllipse(SystemBrushes.ControlText, centerPoint.X, centerPoint.Y, 3, 3); if (Orientation == System.Windows.Forms.Orientation.Horizontal) { e.Graphics.FillEllipse(SystemBrushes.ControlText, centerPoint.X - 10, centerPoint.Y, 3, 3); e.Graphics.FillEllipse(SystemBrushes.ControlText, centerPoint.X + 10, centerPoint.Y, 3, 3); } else { e.Graphics.FillEllipse(SystemBrushes.ControlText, centerPoint.X, centerPoint.Y - 10, 3, 3); e.Graphics.FillEllipse(SystemBrushes.ControlText, centerPoint.X, centerPoint.Y + 10, 3, 3); } } 

我更喜欢的是添加一个油漆处理程序。 这意味着您不需要派生新类,并且如果将静态函数放入可以由各种项目共享的文件中,则可以轻松地重复使用静态函数 – 只需记住使用“添加为链接”,这样如果您编辑文件,它将被包含它的所有项目更改。 这个的主要缺点是它不会自动处理改变控件的颜色。

 ... mySplitContainer.Paint += CustomPaint.PaintSplitterWithHandle; ... public static class CustomPaint { public static void PaintSplitterWithHandle(object sender, PaintEventArgs p) { SplitContainer splitter = sender as SplitContainer; if (splitter == null) return; if (splitter.Orientation == Orientation.Horizontal) p.Graphics.DrawLine(Pens.DarkGray, 0, splitter.SplitterDistance + (splitter.SplitterWidth / 2), splitter.Width, splitter.SplitterDistance + (splitter.SplitterWidth / 2)); else p.Graphics.DrawLine(Pens.DarkGray, splitter.SplitterDistance + (splitter.SplitterWidth / 2), 0, splitter.SplitterDistance + (splitter.SplitterWidth / 2), splitter.Height); } } 

当我在编写内部管理工具时,我并不是真的想要完成绘制抓柄的所有笨拙工作,这太过分了。 根据MSDN上的这篇文章,你可以对SplitContainer进行子类化,覆盖OnPaint(PaintEventArgs)方法并包含以下行:

 ControlPaint.DrawGrabHandle(e.Graphics, SplitterRectangle, true, Enabled); 

这将绘制窗格之间的基本分界线。