4

Is there a direct way to de-focus a TextBox when clicking absolutely anywhere else in the form, whether or not the clicked thing itself can receive focus (e.g. toolbar buttons, toolbar and/or client area empty space, etc)? That is to say, the de-focusing click event could occur on a variety of other controls that know nothing about the focused control.

This question is rather similar to this one and this one, but the answers there are incomplete in that they don't offer any advice on when to perform the action (i.e. what event on what control).

I have a form (a UserControl subclass) with draggable widgets on a panel along with a couple of toolbars. The draggable widgets are made up of PictureBoxes and Labels. Double-clicking on a widget's label replaces the label with a TextBox to allow the user to rename the component. The intent is to force focus to leave the TextBox when clicking anywhere else, to cause validation to occur (as if the user had pressed Enter).

Here's a quick rundown of the heirarchy:

UserControl
  +- ToolStripContainer
     +- ToolStripConainer.TopToolStripPanel
     |  +- ToolStrip
     +- ToolStripContainer.RightToolStripPanel
     |  +- ToolStrip
     +- ToolStripContainer.ContentPanel
        +- CompositorPanel (subclass of Panel to provide proper transparency)
           +- UserControl (draggable widget)
              +- PictureBox
              +- Label
              +- TextBox

I can add event handlers to various other components on the form to force the focused TextBox to un-focus (i.e. programmatically move the focus to another element), but that seems kludgy and requires unrelated elements to be aware of the currently-focused TextBox.

I tried overriding OnMouseDown on the outermost class (the containing UserControl for everything, based on an idea presented here) but the method was never called.

Community
  • 1
  • 1
Brian A. Henning
  • 1,374
  • 9
  • 24
  • 'De-focussing' is the wrong concept. You need to put the Focus __somewhere else__. – TaW Nov 02 '16 at 14:27
  • Semantics. The control is losing focus. I need it to lose focus whether the next clicked-on thing is focusable or not. The fact that that means I must put the focus on something else is irrelevant; the important question is when to make that happen. I'll try to reword my question to make that clear. – Brian A. Henning Nov 02 '16 at 14:31

1 Answers1

2

In order to detect if the mouse is clicked anywhere outside of the TextBox would require a mouse hook, or you can try a simple hack by placing a timer on your UserControl:

public UserControl1() {
  InitializeComponent();
  mouseTimer.Interval = 16;
  mouseTimer.Tick += mouseTimer_Tick;
  mouseTimer.Enabled = true;
}

private void mouseTimer_Tick(object sender, EventArgs e) {
  if (this.ActiveControl != null && this.ActiveControl.Equals(textBox1)) {
    if (MouseButtons != MouseButtons.None) {
      if (!textBox1.ClientRectangle.Contains(textBox1.PointToClient(MousePosition))) {
        if (this.ParentForm != null) {
          this.ParentForm.ActiveControl = null;
        } else {
          this.ActiveControl = null;
        }
      }
    }
  }
}
Community
  • 1
  • 1
LarsTech
  • 80,625
  • 14
  • 153
  • 225
  • This timer approach seems to be usable in my situation. I've modified it so that the timer is only running while the UserControl is in "edit mode" (i.e. the text box is visble, etc). – Brian A. Henning Nov 02 '16 at 17:07