В разделительной панели SplitContainer было 3 точки. Точно так же, как есть три строки, о которых идет речь, текстовое поле на StackOverflow, которое показывает, что его можно схватить. Как это сделать с помощью разделительной панели SplitContainer в .NET?
Как добавить рукоятку захвата в Splitter of SplitContainer
Ответ 1
Не то, чтобы у меня было что-то против Алекс, но я думал, что поделюсь этим решением, поскольку он выглядит немного лучше для меня (на любом компьютере 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
Это не реализовано. Если вам нужна эта функция, лучше всего вывести 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
Я использую эквивалент С#, потому что вы отметили свой вопрос так.
Если vb makes you sick, научитесь переходить к Преобразование VB.NET в С# - Разработчик Fusion и преобразование VB в С#.
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
Ближе всего вы можете прийти, не нарисовав его самостоятельно, чтобы изменить BorderStyle на Fixed3D. Это даст вам своего рода "бар" между двумя панелями.
Если вам не нравится затонувший вид на обеих панелях, вы можете "скрыть" внешние границы, поместив свою разделенную панель на другую панель и установив ее Location на отрицательное значение (например, -n,-n) и его размер до размера его родительской панели + 2*n. Затем я установил Anchor в Top | Left | Bottom | Right, чтобы он оставался таким, как вы изменяете размер родительской панели.
Это своего рода kludge, но кое-что, что я, безусловно, считал своим делом, поскольку ненавижу, что нет никаких указаний о том, где находится "точка захвата".
Ответ 4
Мне понравились shousper, и Алекс ответил, но они казались немного "сложными" для моего вкуса; казалось, было больше кода, который я бы счел нужным.
Ответ Shaun также работает (я также нашел это в MSDN), но в приложении, над которым я работаю, "ручки захвата" стали довольно отвлекающими, так как они почти заполняют разделитель, и у нас есть довольно много их.
Итак, я придумал это, которое находится между ними. Нет массивов, нет новых прямоугольников. Потребуется очень немного дополнительной работы для эффекта "3D" из "принятого" ответа, но для меня три простых точки:
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
Я предпочитаю просто добавлять обработчик краски. Это означает, что вам не нужно выводить новый класс, и статическая функция легко повторно используется, если вы помещаете ее в файл, который может использоваться различными проектами - просто не забудьте использовать "добавить как ссылку", чтобы при редактировании файл, он будет изменен для всех проектов, которые его включают. Основной недостаток заключается в том, что он автоматически не обрабатывает изменение цвета элемента управления.
...
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);
}
}
Ответ 6
Я действительно не хотел делать всю грубую работу по рисованию дескриптора захвата, поскольку я писал собственный инструмент администрирования, и это было излишним. По этой статье в MSDN вы можете подклассифицировать SplitContainer, переопределить метод OnPaint (PaintEventArgs) и включить следующую строку:
ControlPaint.DrawGrabHandle(e.Graphics, SplitterRectangle, true, Enabled);
Это приведет к базовой разделительной линии между панелями.