Как добавить ручку захвата в Splitter SplitContainer - PullRequest
15 голосов
/ 15 ноября 2010

Раньше в разделительной панели SplitContainer было 3 точки.Так же, как в StackOverflow есть три строки в текстовом поле с подробностями вопроса, которые показывают, что его можно взять.Как я могу сделать это с помощью разделительной панели SplitContainer в .NET?

Ответы [ 6 ]

43 голосов
/ 10 декабря 2010

Не то, чтобы у меня было что-то против ответа Алекса, но я подумал, что поделюсь этим решением, поскольку оно выглядит немного лучше для меня (на компьютере с 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)));
    }
}

Надеюсь, это кому-нибудь понравится?Хаа!

12 голосов
/ 15 ноября 2010

Это не реализовано. Если вам нужна эта функция, лучше всего вывести 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, научитесь переходить на Конвертировать 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
{

    /// <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)));
        }
    }
}
6 голосов
/ 16 ноября 2010

Самое близкое, что вы можете сделать, не покрасив его самостоятельно, - это изменить BorderStyle на Fixed3D.Это даст вам своего рода «полосу» между двумя панелями.

Если вам не нравится утонувший вид самих двух панелей, вы можете как бы «скрыть» внешние границы, поместивразделить панель внутри другой панели и установить для ее Location отрицательное значение (например, -n,-n), а для ее размера - размер родительской панели + 2*n.Затем я бы установил Anchor на Top | Left | Bottom | Right, чтобы он оставался таким же, как вы изменяете размер родительской панели.

Это своего рода клочок, но я определенно подумал, что делать, поскольку я ненавижу, что нетуказание, где находится «точка захвата».

5 голосов
/ 09 ноября 2012

Мне понравились ответы Шоупера и Алекса, но они показались мне немного «сложными» на мой вкус; казалось, было больше кода, который я бы счел необходимым.

Ответ Шона также работает (я также нашел его в 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);
    }
}
2 голосов
/ 05 октября 2012

Я действительно не хотел выполнять всю тяжелую работу по рисованию ручек захвата, поскольку я писал собственный инструмент администратора, и это было излишним.Согласно этой статье на MSDN вы можете создать подкласс SplitContainer, переопределить метод OnPaint (PaintEventArgs) и включить следующую строку:

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

Это проведет основную разделительную линию междустекла.

2 голосов
/ 01 июня 2011

Что я предпочитаю, так это просто добавить обработчик рисования.Это означает, что вам не нужно извлекать новый класс, а статическую функцию легко использовать повторно, если вы поместите ее в файл, который может использоваться различными проектами - просто не забудьте использовать «добавить как ссылку», чтобы при редактированиифайл, он будет изменен для всех проектов, которые его включают.Основная ошибка в том, что он не обрабатывает автоматически изменение цвета элемента управления.

...
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);
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...