Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add grab handle in Splitter of SplitContainer

Tags:

c#

.net

winforms

There used to be 3 dots in the splitter bar of a SplitContainer. Just like there are three lines in question details text box on StackOverflow that shows it can be grabbed. How can I do this with the splitter bar of a SplitContainer in .NET?

like image 346
SMUsamaShah Avatar asked Nov 15 '10 17:11

SMUsamaShah


2 Answers

Not that I have anything against Alex's answer, but I thought I'd share this solution as it looks a bit nicer to me (on an XP machine anyway?).

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

Hope this pleases someone? Haa!

like image 82
shousper Avatar answered Sep 29 '22 07:09

shousper


That isn't implemented. If you'd like that feature, it's best you derive the SplitContainer and override the OnPaint method.


Update 1

Here's some code to do what you requested. It is in VB.NET and the dot placement can do with some tweaking. Overall, the code works as expected.

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

Update 2

I'm putting up the C# equivalent because you tagged your question so.
If vb makes you sick, learn to head over to Convert VB.NET to C# - Developer Fusion and do the VB to C# conversion.

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)));
        }
    }
}
like image 40
Alex Essilfie Avatar answered Sep 29 '22 07:09

Alex Essilfie