禁用SplitContainer上的焦点提示



如何禁用SplitContainer上的焦点提示?我之所以这么问,是因为我宁愿自己用OnPaint绘制它们,以使其看起来更平滑。

我试过这个:

    protected override bool ShowFocusCues
    {
        get
        {
            return false;
        }
    }

这是我的控制:

    public class cSplitContainer : SplitContainer
    {
        private bool IsDragging;
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (!IsSplitterFixed) IsDragging = true;
            Invalidate();
        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            if (IsDragging)
            {
                IsDragging = false;
                IsSplitterFixed = false;
            }
        }
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (IsDragging)
            {
                IsSplitterFixed = true;
                if (e.Button == MouseButtons.Left)
                {
                    if (Orientation == Orientation.Vertical)
                    {
                        if (e.X > 0 && e.X < Width) SplitterDistance = e.X;
                    }
                    else
                    {
                        if (e.Y > 0 && e.Y < Height) SplitterDistance = e.Y;
                    }
                }
                else
                {
                    IsDragging = false;
                    IsSplitterFixed = false;
                }
            }
        }
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            base.OnPaint(e);
            if (IsDragging)
            {
                e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(127, 0, 0, 0)), Orientation == Orientation.Horizontal ? new Rectangle(0, SplitterDistance, Width, SplitterWidth) : new Rectangle(SplitterDistance, 0, SplitterWidth, Height));
            }
        }
    }

但没有奏效。我也尝试了一些之前提到的其他方法,但我仍然得到了焦点提示。

我不认为你看到的是FocusCue,而不是一个用于移动滑块的浮动窗口。

如果键盘访问不重要,你可以尝试使其不可选择:

public class MySplit : SplitContainer {
  public MySplit() {
    this.SetStyle(ControlStyles.Selectable, false);
  }
  protected override void OnPaint(PaintEventArgs e) {
    e.Graphics.Clear(Color.Red);
  }
}

这会阻止SplitContainer获得焦点,但您的鼠标仍然可以与它交互。

SplitContainer的代码如下:

protected override void OnPaint(PaintEventArgs e) {
  base.OnPaint(e);
  if (Focused) {
    DrawFocus(e.Graphics,SplitterRectangle);
  }
}

DrawFocus不是虚拟的。因此您无法覆盖它。
聚焦是虚拟的。也许您可以在OnPaint覆盖中调用base.OnPaint(...)时将其设置为false。

所以你可以添加以下代码(我没有测试它是否有效):

private bool _painting;
public override bool Focused
{
  get { return _painting ? false : base.Focused; }
}
protected override void OnPaint(PaintEventArgs e)
{
  _painting = true;
  try
  {
    base.OnPaint(e);
  }
  finally
  {
    _painting = false;
  }
}

这与其说是一个干净的解决方案,不如说是一种破解。

我在谷歌上搜索这个问题,这个问题出现在了顶部。

在微软的一个论坛上,有一个解决方案和有趣的讨论,关于拆分器毫无理由地窃取焦点。以下评论很到位:


您提到的焦点问题是设计上的,但是为了获得您想要的性能,您可以使用以下解决方法:。。。。


它可以是";通过设计";,但它不是一个很好的。你在任何一个微软生产应用程序中都见过哪些会暂时将焦点从拆分的窗格中转移开的喷子?我还添加了你建议的代码,它确实防止了我永久性地将焦点转移到拆分器上,但我仍然不喜欢我的窗格在操作拆分器时隐藏和显示它们的选择。

这种令人分心的选择闪光灯在大多数专业应用程序中都不存在。这已经足够好了,可能在一段时间内不值得我花时间来修复,但这不是大多数人真正想要的。如果你尊重TabStop属性,甚至添加了AcceptsFocus属性,大多数人都会希望关闭它。我认为你应该在未来的版本中将此选项添加到设计中。

--Brendan

简单的解决方案:收到焦点后立即放弃

三个步骤:

  1. SplitContainer创建一个GotFocus处理程序
  2. 使用AnotherControl.Focus()将焦点转发到另一个控件
  3. TabStop设置为False

仅此而已。丑陋的焦点提示从未显示。

现在,有一个微妙之处:将焦点放在其他哪个控件上?这取决于你。只需按选项卡顺序获取第一个控件,或者在SplitContainer的右窗格中获取左上角的可聚焦控件(下面ASCII图中的TextBox)。完美的解决方案是有焦点的前一个控件,但遗憾的是,这并不容易找到:找到最后一个焦点的控件,但IMHO左上角的可聚焦控件是一个非常好的响应。

       left pane            right pane
------------------------------------------------
:                     ::                       :
:                     ::   [TextBox] [Button]  :
:                     ::                       :
:                     ::   [Combobox V]        :
:                     ::                       :
------------------------------------------------

这是一种类似于在stackoflow上提出的问题,建议您使用一个解决方案,同时覆盖showfocuscues属性,您也需要覆盖paint方法。

最新更新