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 Library文章警告这一点,强烈建议使用Leave事件.您可以在设计器中看到这一点,在表单上放置一个TextBox,然后单击“属性”窗口中的闪电图标.请注意GotFocus和LostFocus事件都不可见.您必须改为使用Enter和Leave事件.
关于这里发生了什么的一些背景知识.您的程序会因为分配BorderStyle属性而爆炸.这是一个“困难”属性,它会影响窗口的样式标志,即传递给本机CreateWindowEx()函数的标志.因此,更改边框样式需要Winforms再次创建本机窗口.这就是导致你看到闪烁的原因,文本框被破坏并重新创建,然后重新绘制.你看到了.
但是它具有超出闪烁的副作用,它还会导致低级别的GotFocus和LostFocus事件被触发.因为被破坏的窗户当然也失去了焦点.由于LostFocus事件处理程序再次更改BorderStyle,因此会在程序中进行非常差的交互,从而迫使Winforms再次重新创建窗口.并触发GotFocus事件,您再次更改BorderStyle.这反复重复,你看到文本框快速闪烁.这不会无休止地进行,在创建窗口10,000次之后,操作系统会拔出插件并且不会让程序再创建另一个.窗口程序的严重崩溃是结果.
对于Enter和Leave事件没有问题,它们不能从低级Windows通知中工作,因此在重新创建文本框窗口时不要触发.你只能通过不改变BorderStyle属性来摆脱一次性闪烁,如果它仍然困扰你.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。