【问题标题】:How to deselect textbox if user clicks elsewhere on the form?如果用户单击表单上的其他位置,如何取消选择文本框?
【发布时间】:2011-11-04 17:17:03
【问题描述】:

目前在我的应用程序中,无法取消选择文本框。唯一的方法是选择另一个文本框。我的用户和我同意单击表单上的其他任何位置应取消选择当前文本框。我尝试在许多控件上覆盖 MouseDown 并将焦点设置为随机标签,但它不适用于 MenuStrip 或滚动条等某些控件。有什么想法吗?

【问题讨论】:

  • 这样一个要求的理由是什么?这对您的用户有什么好处?
  • 您使用的是什么平台? WinForms、ASP.NET、WPF?
  • @cdhowie:因为表单上还有 NumericUpDown,并且在这些值上使用鼠标滚轮增加/减少值。用户希望能够单击面板并使用滚轮来移动它。但是,NumericUpDown 仍处于选中状态,而是滚动该值。我不想只对 NumericUpDown 有这种行为,因为它会使用户感到困惑。
  • 那么也许点击面板应该将焦点分配给它的滚动条。
  • @cdhowie——我明白他为什么想要这个——网页的行为方式是这样的。单击一个大文本区域,您的鼠标滚轮将在内部文本窗口中滚动。单击文本区域外的任何位置,鼠标滚轮将滚动页面。我假设他希望他的 WinForms 以相同的方式运行。

标签: c# winforms textbox focus setfocus


【解决方案1】:

这是通用答案:要在用户单击表单上的其他任何位置时取消选择 TextBoxes,首先使控件失去焦点。为此订阅表单的点击事件:

private void Form1_Click(object sender, EventArgs e)
{
    this.ActiveControl = null;
}

接下来将您的 TextBoxes 订阅到 Focus Leave 事件并将 SelectionLength 设置为 0(以取消选择文本,尽管文本框在失去焦点时不显示选择,但它不会以某种方式被取消选择):

private void textBoxes_Leave(object sender, EventArgs e)
{
    TextBox txbox = sender as TextBox;
    txbox.SelectionLength = 0;
}

如果您将 TexBox 嵌套在自定义用户控件中,则必须以类似的方式在该用户控件中添加事件。希望对其他人有所帮助。

【讨论】:

    【解决方案2】:

    我最近遇到了类似的问题。我的界面非常复杂,有很多面板和标签页,所以我找到的更简单的答案都没有奏效。

    我的解决方案是以编程方式将鼠标单击处理程序添加到表单中的每个不可聚焦的控件,这将尝试将任何标签集中在表单上。在不同的标签页上聚焦特定标签不起作用,所以我最终循环并聚焦所有标签。

    要完成的代码如下:

        private void HookControl(Control controlToHook)
        {
            // Add any extra "unfocusable" control types as needed
            if (controlToHook.GetType() == typeof(Panel)
                || controlToHook.GetType() == typeof(GroupBox)
                || controlToHook.GetType() == typeof(Label)
                || controlToHook.GetType() == typeof(TableLayoutPanel)
                || controlToHook.GetType() == typeof(FlowLayoutPanel)
                || controlToHook.GetType() == typeof(TabControl)
                || controlToHook.GetType() == typeof(TabPage)
                || controlToHook.GetType() == typeof(PictureBox))
            {
                controlToHook.MouseClick += AllControlsMouseClick;
            }
            foreach (Control ctl in controlToHook.Controls)
            {
                HookControl(ctl);
            }
        }
        void AllControlsMouseClick(object sender, MouseEventArgs e)
        {
            FocusLabels(this);
        }
        private void FocusLabels(Control control)
        {
            if (control.GetType() == typeof(Label))
            {
                control.Focus();
            }
            foreach (Control ctl in control.Controls)
            {
                FocusLabels(ctl);
            }
        }
    

    然后将其添加到您的 Form_Load 事件中:

    HookControl(this);
    

    【讨论】:

      【解决方案3】:

      由于您的 winform 上可能有标签或任何其他控件,我会采用解决方案 recommended here,并在单击表单时将焦点放在标签上。

      最坏的情况,你甚至可以添加一个位于 -100、-100 位置的标签,将他设置为 tab 顺序中的第一个,然后在表单点击时将其 Focus()。

      【讨论】:

        【解决方案4】:

        假设您的论坛上没有其他控件,请尝试添加可以接收焦点的面板控件。

        Panel 控件上的TabIndex 设置为小于TextBoxNumericUpDown 控件所具有的值。

        现在,当您的主窗体获得焦点时,Panel 应该获得焦点,而不是 TextBox 区域。

        【讨论】:

        • 这并不能解决我的问题。我不希望它们被启用或禁用,只有当用户单击时它们才会失去焦点。此外,这只会检测表单点击,而不是控制表单上的点击。
        • 如果控件被禁用,它将不会收到鼠标消息,也不会获得焦点。
        • 是的,但它只会在用户单击 form 上的空白区域时禁用它(我不希望这样做)。
        • 您的表单上是否还有其他可以让您关注的控件? (我猜不是)
        • 就像 CKoenig 说的,你可以添加另一个控件。一个基本的面板就可以了,你可以在上面设置TextBox 控件,然后给Panel 焦点。这个想法是将焦点发送到其他地方,因为 TextBox 控件的 Tab Index 是(当前)最低的,这迫使它在 Form 获得焦点时始终获得焦点。
        【解决方案5】:

        我为您准备了某种“解决方法”。只是背景中的另一个控件(可以获取焦点)。我为 GridView 测试了这个(它将把你的控件涂成灰色) - 但你应该能够使用你想要的颜色的自定义控件来做到这一点,或者只是设置 gridview 的背景颜色(doh)。 这样每次用户点击背景时,这个背景控件都会获得焦点。

        【讨论】:

        • 这也不起作用。它只是将所有控件的容器从表单更改为面板。同样的问题仍然存在。
        猜你喜欢
        • 2015-07-27
        • 2022-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多