Custom paint Splitter control in C# WinForms

那年仲夏 提交于 2019-12-01 10:53:45
Reza Aghaei

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:

The old Splitter control uses a private painting method to produce that checkerboard effect, so there isn't any thing you can override to replace that.

You can fake it by dragging your own control in the space of the checkerboard control you see on the screen. This may produce some flicker:

Control draggingControl = new Control { BackColor = Color.Green, Visible = false };

public MockForm() {
  InitializeComponent();
  this.Controls.Add(draggingControl);
  splitter1.SplitterMoving += splitter1_SplitterMoving;
  splitter1.SplitterMoved += splitter1_SplitterMoved;
}

void splitter1_SplitterMoving(object sender, SplitterEventArgs e) {
  draggingControl.Bounds = new Rectangle(new Point(e.X - (e.X - e.SplitX), 0),
                                         splitter1.Size);
  if (!draggingControl.Visible) {
    draggingControl.Visible = true;
    draggingControl.BringToFront();
  }
  this.Refresh();
}

void splitter1_SplitterMoved(object sender, SplitterEventArgs e) {
  draggingControl.Visible = false;
  this.Refresh();
}

The Splitter control was deprecated in favor of the SplitContainer control.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!