【问题标题】:Got focus and lost focus both event calling repeatedly when handling get and lost focus event of multiple textboxes it goes into infinite loop在处理多个文本框的获取和失去焦点事件时,获得焦点和失去焦点这两个事件重复调用它进入无限循环
【发布时间】:2014-03-19 12:21:33
【问题描述】:

以下是我处理表单中所有可用文本框的 gotfocus 和 lostfocus 事件的代码。

private void Form1_Load(object sender, EventArgs e)
    {

        foreach (Control c in this.Controls)
        {
            if (c is TextBox)
            {
                c.GotFocus += new System.EventHandler(this.txtGotFocus);
                c.LostFocus += new System.EventHandler(this.txtLostfocus);
            }
        }
    }
    private void txtGotFocus(object sender, EventArgs e)
    {
        TextBox tb = (TextBox)sender;
        if (tb != null)
        {
            tb.BackColor = Color.Silver;
            tb.BorderStyle = BorderStyle.FixedSingle;
        }

    }
    private void txtLostFocus(object sender, EventArgs e)
    {

        TextBox tb = (TextBox)sender;
        if (tb != null)
        {
            tb.BackColor = Color.White;
            tb.BorderStyle = BorderStyle.Fixed3D;
        }
    }

它适用于第一个文本框,但是当我通过按 Tab 键转到下一个文本框时,它会重复调用这两个事件,并且文本框的行为就像闪烁一样。一段时间后,错误消息显示在代码中,例如:

对“System.Windows.Forms!System.Windows.Forms.NativeMethods+WndProc::Invoke”类型的垃圾收集委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。将委托传递给非托管代码时,托管应用程序必须使它们保持活动状态,直到保证它们永远不会被调用。

代码有什么问题?有什么解决办法吗?

【问题讨论】:

    标签: c# .net winforms events


    【解决方案1】:
       c.LostFocus += new System.EventHandler(this.txtLostfocus);
    

    LostFocus 是一个危险事件,Control.LostFocus 的 MSDN 库文章对此提出了警告,并强烈建议改用 Leave 事件。这是您可以在设计器中看到的内容,将 TextBox 拖放到表单上,然后单击“属性”窗口中的闪电图标。请注意 GotFocus 和 LostFocus 事件是如何可见的。您必须改用 Enter 和 Leave 事件。

    这里发生了什么的一些背景。您的程序崩溃了,因为您分配了 BorderStyle 属性。这是一个“困难”的属性,它会影响窗口的样式标志,也就是传递给本机 CreateWindowEx() 函数的那个​​。所以改变边框样式需要Winforms重新创建原生窗口。这就是导致您看到闪烁的原因,文本框被破坏并重新创建,然后重新绘制。你看。

    但这除了闪烁之外还有副作用,它还会导致低级别的 GotFocus 和 LostFocus 事件触发。因为被破坏的窗口当然也失去了焦点。这在您的程序中的交互非常糟糕,因为您的 LostFocus 事件处理程序再次更改了 BorderStyle,迫使 Winforms 再次重新创建窗口。并触发 GotFocus 事件,您将再次更改 BorderStyle。这一遍又一遍地重复,您会看到文本框快速闪烁。这不会无休止地进行,在创建窗口 10,000 次之后,操作系统会拔掉插头,不让您的程序再创建一个。结果是窗口过程的硬崩溃。

    Enter 和 Leave 事件没有问题,它们在低级 Windows 通知中不起作用,因此在重新创建文本框窗口时不会触发。如果它仍然困扰您,您只能通过不更改 BorderStyle 属性来消除一次性闪烁。

    【讨论】:

    • 感谢您提供有用的信息。这东西对我有帮助。
    【解决方案2】:

    发生这种情况是因为您更改了边框样式。不要问我为什么,我不知道。如果您删除tb.BorderStyle = XXX,它将起作用。我猜(!)更改边框样式会使控件失去其 fokus(并再次获得它)

    编辑:汉斯更快,解释更好:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 2012-08-13
      • 1970-01-01
      相关资源
      最近更新 更多