如何在SplitContainer的Splitter中添加抓柄

时间:2010-11-15 17:40:39

标签: c# .net winforms

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

5 个答案:

答案 0 :(得分:43)

并不是说我有什么可以反对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)));
    }
}

希望这能让某些人高兴吗? HAA!

答案 1 :(得分:12)

没有实施。如果您喜欢该功能,最好派生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#等价物,因为你标记了你的问题 如果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)));
        }
    }
}

答案 2 :(得分:6)

您最接近而不自己绘画就是将BorderStyle更改为Fixed3D。这将在两个小组之间给你一种“条形”。

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

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

答案 3 :(得分:2)

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

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

答案 4 :(得分:2)

我并不是真的想做一个抓握手柄的笨拙工作,因为我正在编写一个内部管理工具,这太过分了。根据{{​​3}},您可以对SplitContainer进行子类化,覆盖OnPaint(PaintEventArgs)方法并包含以下行:

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

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