代码之家  ›  专栏  ›  技术社区  ›  SMUsamaShah

如何在SplitContainer的拆分器中添加抓取句柄

  •  15
  • SMUsamaShah  · 技术社区  · 14 年前

    一个拆分容器的拆分条中过去有3个点。就像StackOverflow上有三行“问题详细信息”文本框显示可以抓取它一样。如何使用.NET中SplitContainer的分隔条执行此操作?

    6 回复  |  直到 12 年前
        1
  •  43
  •   shousper    12 年前

    不是说我反对亚历克斯的回答,但我想我会把这个解决方案 对我好一点(在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)));
        }
    }
    

    希望这能取悦别人?哈!

        2
  •  12
  •   Alex Essilfie    11 年前

    这还没有实现。如果您喜欢这个特性,最好派生SplitContainer并重写OnPaint方法。


    更新1

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

    Imports System.Windows.Forms
    Imports System.ComponentModel
    Imports System.Drawing
    
    Public Class SplitContainerEx
        Inherits SplitContainer
    
        ''' <summary>Determines the thickness of the splitter.</summary>
        <DefaultValue(GetType(Integer), "5"), Description("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#等价物,是因为你把你的问题标成了C#等价物。
    如果 vb makes you sick ,学会面对 Convert VB.NET to C# - Developer Fusion 并进行VB到C的转换。

    using System;
    using System.Diagnostics;
    using System.Windows.Forms;
    using System.ComponentModel;
    using System.Drawing;
    
    public class SplitContainerEx : SplitContainer
    {
    
        /// <summary>Determines the thickness of the splitter.</summary>
        [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)));
            }
        }
    }
    
        3
  •  6
  •   Shibumi    14 年前

    如果你不亲自粉刷的话,你最接近的就是 BorderStyle Fixed3D . 在两个面板之间会有一个“条”。

    如果您不喜欢这两个面板本身的凹陷外观,您可以通过将分割面板放在另一个面板的内部并设置其 Location 到负值(例如。 -n,-n )其大小与其父面板大小相同+ 2*n . 然后我把锚定在 Top | Left | Bottom | Right 以便在调整父面板的大小时保持这种方式。

    这是一种混乱,但我确实考虑过做一些我讨厌的事,没有迹象表明“抓捕点”在哪里。

        4
  •  5
  •   Ryan    12 年前

    我喜欢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);
        }
    }
    
        5
  •  3
  •   Shaun    12 年前

    我真的不想在写内部管理工具的时候做所有的抓取手柄的工作,这太过分了。根据 this article on MSDN 您可以对SplitContainer进行子类划分,覆盖OnPaint(PaintEventArgs)方法并包含以下行:

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

    这将在窗格之间画一条基本的分界线。

        6
  •  2
  •   Mick Bruno    13 年前

    我更喜欢的是添加一个绘画处理程序。这意味着您不需要派生一个新类,如果将静态函数放入一个可由不同项目共享的文件中,则该静态函数很容易重用—只需记住使用“add as link”,这样,如果您编辑了该文件,则将对包含该文件的所有项目进行更改。它的主要缺点是不能自动处理控件颜色的更改。

    ...
    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);
      }
    }