c# - 获得焦点和失去焦点这两个事件在处理多个文本框的获得和失去焦点事件时重复调用它进入无限循环

标签 c# .net winforms events

以下是我的代码,用于处理表单中所有可用文本框的 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 键转到下一个文本框时,它会重复调用这两个事件,文本框的行为就像闪烁一样。一段时间后,错误消息显示在如下代码中:

A callback was made on a garbage collected delegate of type 'System.Windows.Forms!System.Windows.Forms.NativeMethods+WndProc::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.

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

最佳答案

   c.LostFocus += new System.EventHandler(this.txtLostfocus);

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

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

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

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

关于c# - 获得焦点和失去焦点这两个事件在处理多个文本框的获得和失去焦点事件时重复调用它进入无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22505667/

相关文章:

c# - 在 .NET 中使用 Firebase

.net - VB.net不一致的线程 sleep 定时器

c# - 调整窗口大小时如何很好地制作标签和文本框布局?

c# - 创建 XLSX 文件需要更多时间来记录 100000 条记录并占用最大 RAM 内存

c# - 如何在 ASP.NET 中使用时区?

c# - 如何将 LINQ 支持添加到我的库中?

.net - 使用线程VB调用Web服务时,发生InvalidOperationException。网

vb.net - 在设计器中打开 VB.NET Windows 窗体时出现错误 "Value cannot be null. Parameter name: objectType"

c# - Awesomium 弹出窗口 - ShowCreatedWebView 示例

c# - 在 C# 中更改数据而不重新编译