An Unselectable UserControl

This is gonna be simple. There are certain situations when you need your custom control not to receive input focus (or not to steal the focus from another control when it is ‘activated’). In the simplest form, this is easy to achieve by deriving your control from Windows.Forms.Control and removing the ControlStyles.Selectable flag.
So it may look like the following one:


    class CustomControl : System.Windows.Forms.Control
    {
        public CustomControl()
        {
            this.SetStyle(ControlStyles.Selectable, false);
        }
    }

Ok. So far, so good. It’s easy for Control, but if you try the same with UserControl, it won’t work, setting ControlStyles.Selectable has no effect. And if you start looking why (by the .net reflector or ILSpy), you will probably end up looking on a code like the one below:

This means that an UserControl internally sets the input focus on every mouse click. And this is exactly what we don’t want.

Luckily, the solution is quite easy: override the OnMouseDown() function without calling base.OnMouseDown(). Now, the UserControl’s OnMouseDown() isn’t called, so the focus stays where it should, but on the other hand it also means that the MouseDown event is not raised at all. So if you need the event, you have to raise it manually, and this is the place where the .net reflection comes in handy. At the end, you may end up with a code similar to this one:


protected override void OnMouseDown(MouseEventArgs e)
{
    // do not set input focus, just raise the event
    object mouseDownEvent = typeof(Control).GetField("EventMouseDown", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static).GetValue(null);
    MouseEventHandler handler = (MouseEventHandler)Events[mouseDownEvent];
    if (handler != null)
        handler(this, e);
}

You can download a complete source code and example here:

Download example

You may also like

Leave a Reply

Your email address will not be published. Required fields are marked *