Add button control(s) to SplitContainer Splitter

4.1k views Asked by At

Is there any way to display controls (like buttons) on the adjustable splitter that displays between the two panels in a .NET SplitContainer?

Example:

Diagram

I don't think SplitContainer natively supports this, but overriding the control to get this functionality that seems omni-present in numerous applications seems a bit much to me - I feel like I'm over-thinking this or missing something obvious.

1

There are 1 answers

1
Tergiver On BEST ANSWER

Here's an example that uses a TableLayoutPanel to simulate a SplitContainer.

using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;

class Form1 : Form
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    TableLayoutPanel rootPanel;
    float originalWidth;
    int splitPointX;

    public Form1()
    {
        Controls.Add(rootPanel = new TableLayoutPanel
        {
            ColumnCount = 3,
            ColumnStyles =
            {
                // Notice the use of Absolute here as this will control the 'splitting'
                new ColumnStyle(SizeType.Absolute, 120F),
                // Size of button panel
                new ColumnStyle(SizeType.AutoSize),
                // Remaining size
                new ColumnStyle(SizeType.Percent, 100F),
            },
            Dock = DockStyle.Fill,
            RowCount = 1,
            RowStyles = { new RowStyle(SizeType.Percent, 100F) },
        });

        Panel buttonPanel;
        rootPanel.Controls.Add(buttonPanel = new Panel
        {
            Anchor = AnchorStyles.Top | AnchorStyles.Bottom,
            BackColor = SystemColors.ControlDark,
            Margin = new Padding(0),
            MinimumSize = new Size(80, 0),
            Size = new Size(80, 0),
            Controls =
            {
                // UseVisualStyleBackColor = true only because we altered the container's BackColor
                new Button { Text = ">>", Location = new Point(19, 112), Size = new Size(40, 23), UseVisualStyleBackColor = true },
                new Button { Text = ">", Location = new Point(19, 83), Size = new Size(40, 23), UseVisualStyleBackColor = true },
                new Button { Text = "<", Location = new Point(19, 54), Size = new Size(40, 23), UseVisualStyleBackColor = true },
                new Button { Text = "<<", Location = new Point(19, 25), Size = new Size(40, 23), UseVisualStyleBackColor = true },
            },
        }, 1, 0);

        buttonPanel.MouseDown += (s, e) =>
            {
                if (e.Button == MouseButtons.Left)
                {
                    // Capture mouse so that all mouse move messages go to this control
                    (s as Control).Capture = true;

                    // Record original column width
                    originalWidth = rootPanel.ColumnStyles[0].Width;

                    // Record first clicked point
                    // Convert to screen coordinates because this window will be a moving target
                    Point windowPoint = (s as Control).PointToScreen(e.Location);
                    splitPointX = windowPoint.X;
                }
            };
        buttonPanel.MouseMove += (s, e) =>
            {
                if ((s as Control).Capture)
                {
                    Point windowPoint = (s as Control).PointToScreen(e.Location);

                    // Calculate distance of mouse from splitPoint
                    int offset = windowPoint.X - splitPointX;

                    // Apply to originalWidth
                    float newWidth = originalWidth + offset;

                    // Clamp it.
                    // The control in the left pane's MinimumSize.Width would be more appropriate than zero
                    newWidth = Math.Max(0, newWidth);

                    // Update column width
                    if (Math.Abs(newWidth - rootPanel.ColumnStyles[0].Width) >= 1)
                        rootPanel.ColumnStyles[0].Width = newWidth;
                }
            };
        buttonPanel.MouseUp += (s, e) =>
            {
                if (e.Button == MouseButtons.Left)
                {
                    // Release mouse capture
                    if ((s as Control).Capture)
                        (s as Control).Capture = false;
                }
            };
    }
}