以下是我的代码,用于处理表格中所有文本框的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”的垃圾收集委托进行了回调。这可能会导致应用程序崩溃,损坏和数据丢失。将委托传递给非托管代码时,托管应用程序必须将它们保持活动状态,直到确保它们永远不会被调用为止。
代码有什么问题?有没有解决方案?
答案 0 :(得分:20)
c.LostFocus += new System.EventHandler(this.txtLostfocus);
LostFocus是一个危险的事件,Control.LostFocus的MSDN Library文章对此发出警告,强烈建议使用Leave事件。您可以在设计器中看到这一点,在表单上放置一个TextBox,然后单击“属性”窗口中的闪电图标。请注意GotFocus和LostFocus事件如何不可见。您必须改为使用Enter和Leave事件。
有关此处发生的事情的一些背景知识。您的程序会因为分配BorderStyle属性而爆炸。那是一个很难的"属性,它是影响窗口样式标志的属性,是传递给本机CreateWindowEx()函数的标志。因此,更改边框样式需要Winforms再次创建本机窗口。这就是导致你看到闪烁的原因,文本框被破坏并重新创建,然后重新绘制。你看到了。
但是除了闪烁之外还有副作用,它还会导致低级别的GotFocus和LostFocus事件被触发。因为被破坏的窗户当然也失去了焦点。由于LostFocus事件处理程序再次更改BorderStyle,因此会在程序中进行非常差的交互,从而迫使Winforms再次重新创建窗口。并触发GotFocus事件,您再次更改BorderStyle。这反复重复,你看到文本框快速闪烁。这不会无休止地进行,经过10,000次创建窗口后,操作系统会拔出插件,并且不会让您的程序创建另一个。窗口程序的严重崩溃就是结果。
Enter和Leave事件没有问题,他们不能使用低级Windows通知,因此在重新创建文本框窗口时不要触发。如果它仍然困扰你,你只能通过不改变BorderStyle属性来摆脱一次性闪烁。
答案 1 :(得分:3)
这会导致您更改bordertyle。不要问我为什么,我不知道。如果您删除tb.BorderStyle = XXX
,它将有效。我猜(!)更改bordertyle使控件松散其fokus(再次获得)
编辑:汉斯更快,有更好的解释:)