Disable focus cues on a SplitContainer
Asked Answered
L

5

5

How can I disable the focus cues on a SplitContainer? I ask because I'd rather draw them myself using OnPaint in order to make it look somewhat smoother.

I tried this:

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

And this is my control:

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

but it didn't work. I also tried some other methods mentioned before, but I'm still getting focus cues.

Lessee answered 14/3, 2012 at 18:0 Comment(0)
T
4

The code of SplitContainer is like:

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

DrawFocus is not virtual. So you can't override it.
Focused is virtual. Maybe you can set it to false while calling base.OnPaint(...) in your OnPaint override.

So you could add following code (I did not tested if it works):

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

That is more a hack than a clean solution.

Tatting answered 14/3, 2012 at 18:49 Comment(3)
It's too bad they marked DrawSplitHelper as private void. I'm guessing the OP is not happy with that HalfToneBrush they are using.Dobbins
It's still not working. The cues are shown when finished dragging, twice. Have you tried my code?Lessee
@Devilschild I tested it and it helps only a little bit. It shows clues when you focus splitterbar. If control looses focus (e.g. by selecting a window of another application and gets focus again: then it would not show any clues.Tatting
D
11

I don't think what you are seeing is the FocusCue so much as a floating window that is used to move the slider.

If keyboard access isn't important, you can try making it unselectable:

public class MySplit : SplitContainer {

  public MySplit() {
    this.SetStyle(ControlStyles.Selectable, false);
  }

  protected override void OnPaint(PaintEventArgs e) {
    e.Graphics.Clear(Color.Red);
  }
}

This prevents the SplitContainer from getting focus, but your mouse can still interact with it.

Dobbins answered 14/3, 2012 at 18:40 Comment(1)
Notice that the first time you resize there is still a cue visible.Add this to remove it completly: protected override void OnGotFocus(EventArgs e) { // nothing }Instauration
T
4

The code of SplitContainer is like:

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

DrawFocus is not virtual. So you can't override it.
Focused is virtual. Maybe you can set it to false while calling base.OnPaint(...) in your OnPaint override.

So you could add following code (I did not tested if it works):

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

That is more a hack than a clean solution.

Tatting answered 14/3, 2012 at 18:49 Comment(3)
It's too bad they marked DrawSplitHelper as private void. I'm guessing the OP is not happy with that HalfToneBrush they are using.Dobbins
It's still not working. The cues are shown when finished dragging, twice. Have you tried my code?Lessee
@Devilschild I tested it and it helps only a little bit. It shows clues when you focus splitterbar. If control looses focus (e.g. by selecting a window of another application and gets focus again: then it would not show any clues.Tatting
G
4

I was googling for this issue and this question came up on the top.

There is a solution and interesting discussion on a Microsoft forum regarding the splitter stealing focus for no good reason. The following comment is spot on:


The focus issue you mentioned is by design, however to get the performance you want, you can use the following workaround: ....


It may be "by design", but it is not a very good one. What spitters have you ever seen in any Microsoft production application that even temporarily take the focus from the panes they split? I also added the code you suggest, and it does keep me from permanently losing the focus to the splitter, but I still don't like the fact that my panes hide and show their selections during splitter manipulation.

This distracting selection flash just is not present in most professional applications. It is just good enough that it probably won't be worth my time to fix for a while, but not what most people really want. If you respected the TabStop property or even added a AcceptsFocus property, most people would want this off. I think you should add this option to the design in a future version.

--Brendan

Graiae answered 18/5, 2013 at 17:16 Comment(0)
B
2

Simple solution: give away focus immediately when receiving it!

Three steps:

  1. Create a GotFocus handler for the SplitContainer
  2. Forward the focus to another control with AnotherControl.Focus().
  3. Set TabStop to False

That's all. The ugly focus cue is never shown.

Now, one subtlety: Which other control to give the focus to? It's up to you. Just take the first control by tab order, or a upper-left focusable control in the right pane of the SplitContainer (TextBox in the ASCII diagram below). The perfect solution would be the previous control which had focus, but sadly this is not easy to find out: Find out the control with last focus, but IMHO the upper-left focusable control is a very good response.

       left pane            right pane
------------------------------------------------
:                     ::                       :
:                     ::   [TextBox] [Button]  :
:                     ::                       :
:                     ::   [Combobox V]        :
:                     ::                       :
------------------------------------------------
Blessed answered 17/7, 2012 at 11:29 Comment(1)
Finding out the child control that last had focus is indeed tricky! The GotFocus event fires asynchronously, so the GotFocus event of the child control which was originally given focus may under some circumstances fire after the GotFocus event of the SplitContainer itself.Conduct
I
0

it is a kind a similar question being asked on stackoveflow one solution is sugested as being used by you also along with overriding showfocuscues property you need to override paint method as well.

Intonate answered 14/3, 2012 at 18:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.