【问题标题】:Custom paint Splitter control in C# WinFormsC# WinForms 中的自定义绘制拆分器控件
【发布时间】:2015-05-06 20:23:09
【问题描述】:

我正在尝试绘制拖动拆分器控件时出现的拆分线:

从这张图片可以看出,默认的分割器是棋盘格。

...这不起作用:

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
  • 我知道这是一个老问题,LarsTech 发布的答案非常好,但是处理程序闪烁有点烦人。如果您将Form 显示为拆分器处理程序并将其显示在拆分器容器上方,而不是在Form 中显示控件,则闪烁将消失。
  • 还要查看支持透明处理程序的自定义拆分器,请查看this related post。在另一篇文章中,我使用原始拆分器的源代码创建了一个新的拆分器控件,但更改了高亮显示:Change Splitter Highlighting/Resize Line

标签: c# winforms splitter


【解决方案1】:

旧的 Splitter 控件使用私有绘画方法来产生棋盘格效果,因此您无法覆盖任何东西来替换它。

您可以通过在屏幕上看到的棋盘控件空间中拖动自己的控件来伪造它。这可能会产生一些闪烁:

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

Splitter 控件已被弃用,取而代之的是 SplitContainer 控件。

【讨论】:

  • 真是个好主意,但闪烁有点烦人。我在当前表单上方使用了Form,而不是用户控件,然后由于原始突出显示在我使用的突出显示表单下方的拆分器容器上绘制,因此消除了闪烁。
【解决方案2】:

LarsTech 发布的答案非常好,但是处理程序闪烁有点烦人。如果您将Form 显示为拆分器处理程序并将其显示在拆分器的容器上方,而不是在Form 中显示控件,则闪烁将消失。

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

这是我用作突出显示的表格:

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

要查看支持透明处理程序的自定义拆分器,请查看此相关帖子。在另一篇文章中,我使用原始拆分器的源代码创建了一个新的拆分器控件,但更改了高亮显示:

【讨论】:

    猜你喜欢
    • 2010-12-15
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    相关资源
    最近更新 更多