通过单击任意位置或任何其他内容从TextBox中删除焦点

时间:2016-11-02 13:53:45

标签: c# .net winforms user-controls

是否有一种直接的方法可以在单击表单中的任何其他位置时对TextBox进行去焦点,无论点击的内容本身是否可以获得焦点(例如工具栏按钮,工具栏和/或客户区空白区域)等)?也就是说,去聚焦点击事件可能发生在对聚焦控制一无所知的各种其他控件上。

此问题与this onethis one非常相似,但答案不完整,因为他们没有就何时执行此操作提供任何建议(即什么事件发生在什么事情上)控制)。

我有一个表单(UserControl子类),面板上有可拖动的小部件以及几个工具栏。可拖动的小部件由PictureBox es和Label组成。双击小部件的标签会将标签替换为TextBox,以允许用户重命名该组件。目的是强制焦点在点击任何地方时离开TextBox,以便进行验证(就像用户按Enter键一样)。

这里是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

我可以将事件处理程序添加到窗体上的各种其他组件,以强制聚焦的TextBox取消焦点(即以编程方式将焦点移动到另一个元素),但这看起来很糟糕,需要不相关的元素才能知道当前的 - 专注于TextBox。

我尝试在最外面的类上覆盖OnMouseDown(包含UserControl的所有内容,基于提出的here提示,但该方法从未被调用过。

1 个答案:

答案 0 :(得分:2)

为了检测鼠标是否被单击在TextBox之外的任何地方需要mouse hook,或者您可以通过在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;
        }
      }
    }
  }
}