Search code examples
c#winformssplitter

Custom paint Splitter control in C# WinForms


I am trying to paint the split line that appears when you drag a splitter control:

Splitter

As you can see from this image, the default splitter is a checkerboard.

...this doesn't work:

public partial class MockForm : Form
{
    public MockForm()
    {
        InitializeComponent();
        this.splitter1.Paint += splitter1_Paint;
    }

    private void splitter1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.Clear(Color.Red);
    }
}

this just paints the background of the control but not the splitter when it's dragged.

Any ideas?


Solution

  • The answer posted by LarsTech is really good, But the handler flickers are somehow annoying. Instead of showing the control in Form, if you show a Form as splitter handler and show it above the Container of splitter, the flickers will be gone.

    HighLight f = new HighLight() { BackColor = Color.Red };
    private void splitter1_SplitterMoving(object sender, SplitterEventArgs e)
    {
        this.splitter1.Parent.Refresh();
        f.Location = this.splitter1.Parent.PointToScreen(new Point(e.SplitX, e.SplitY));
        f.Size = this.splitter1.Size;
        if (!f.Visible)
            f.ShowInactiveTopmost();
    }
    private void splitter1_SplitterMoved(object sender, SplitterEventArgs e)
    {
        f.Hide();
    }
    

    Here is the form which I used as highlight:

    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    public class HighLight : Form
    {
        public HighLight()
        {
            Opacity = 0;
            FormBorderStyle = FormBorderStyle.None;
            ShowInTaskbar = false;
            StartPosition = FormStartPosition.Manual;
        }
        protected override void OnDeactivate(EventArgs e)
        {
            base.OnDeactivate(e);
            this.Hide();
        }
        private const int SW_SHOWNOACTIVATE = 4;
        private const int HWND_TOPMOST = -1;
        private const uint SWP_NOACTIVATE = 0x0010; 
        [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        static extern bool SetWindowPos(int hWnd, int hWndInsertAfter,
             int X, int Y, int cx, int cy, uint uFlags);
        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
        public void ShowInactiveTopmost()
        {
            ShowWindow(this.Handle, SW_SHOWNOACTIVATE);
            SetWindowPos(this.Handle.ToInt32(), HWND_TOPMOST,
            this.Left, this.Top, this.Width, this.Height,
            SWP_NOACTIVATE);
            this.Opacity = 1;
        }
    }
    

    To see a custom splitter which supports transparent handler take a look at this related post. In the other post I created a new splitter control using source codes of original splitter, but changed rendering the highlight: