你能解释一下为什么会发生这种事吗?下面是重现异常的步骤:
代码只是在HideSelection聚焦而失去焦点时使textBox相应地改变。
更新
我不知道为什么这么不稳定,我创建了另一个项目,现在问题不一样了,没有例外,只有一个不确定的循环,使文本框闪烁,表单似乎没有响应,CPU使用率高达17%-20%。最后一个演示仍然是打开的,而且该演示仍然抛出了Win32Exception。一点线索都没有。现在这两个项目的代码是相同的,但问题是不同的。
发布于 2013-06-06 07:12:24
嗯,有几件事要注意。
首先,HideSelection不隐藏或取消隐藏所选内容。它指定控件失去焦点时是否隐藏所选内容。因此,当TextBox成为焦点时,改变它是没有意义的。
您在LostFocus中所做的是默认的,顺便说一句。我想,为什么GotFocus中有一个异常被埋在Windows中。当HideSelection检查焦点内部的某个未定义状态时,可能会更改事件,无论TextBox是否有焦点,或者试图隐藏未显示的选择。编辑:这不是第一手的Windows,而是框架。它试图在HideSelection的设置器中“重新创建句柄”,如果它被更改(还不知道为什么--必须分析源),并且似乎失败了(也不知道为什么)。Edit2:最后,Win32 DestroyWindow中存在一些问题--这会导致跳过新窗口的创建。也许是因为旧的“正在使用”的焦点改变事件?
有趣的是,一旦异常发生(对我来说),就会触发LostFocus事件,紧接着是引发另一个异常a.s.o的GotFocus。这样就阻塞了GUI。两个分配给HideSelection的任务都会引发异常。
此外,当您单击TextBox时,任何选择都会自动取消。但是,这不是问题的原因,因为如果通过按Tab更改焦点(其正常行为是恢复焦点),则会引发异常。但这可能是相关的(国家问题)。
如果您真的想恢复所选内容,您可以这样做:
int selStart;
int selLen;
void textBox1_LostFocus(object sender, EventArgs e)
{
selStart = textBox1.SelectionStart;
selLen = textBox1.SelectionLength;
}
void textBox1_GotFocus(object sender, EventArgs e)
{
BeginInvoke((Action)(() =>
{
textBox1.SelectionStart = selStart;
textBox1.SelectionLength = selLen;
}));
}发布于 2013-06-06 08:07:04
我复制了这次坠机。通过在事件处理程序上设置断点,您可以很容易地看到它出错,请注意它们是如何在程序爆炸之前一次又一次地发射的。这个解释有点长,我先给出一个简短的版本。MSDN文档为LostFocus事件发出了严厉的警告,既警告也警告,指出这是一个低级别的事件,是危险的。因此,这些事件也隐藏在“属性”窗口中。使用Enter和Leave事件来修复您的问题。
长版本: TextBox.HideSelection属性非常特殊。它与本机Windows控件上某些属性的指定方式有关。这些控件是用CreateWindowEx() winapi函数创建的,它使用一个dwExStyle和dwStyle参数,标志指定窗口的样式选项。HideSelection属性就是这样一个样式标志,ES_NOHIDESEL。
当您想要更改属性时,就会出现问题。困难,因为它只能在创建本机控件时指定。Winforms做了一些非常英勇的事情来解决这个限制,它破坏了本机控制并重新创建了它。
这可能会有相当有趣的副作用,可以温和地说。大多数都是不可观察的,但您确实可以看到屏幕上的窗口被破坏和重新创建。这就是它闪烁的原因。您的代码的核心问题不可避免地是,因为本机窗口正在被破坏,它也失去了焦点。因此,LostFocus事件会立即触发,就在您得到GotFocus事件之后。这做了一些不幸的事情,它再次改变了HideSelection属性。这迫使Winforms再次重新创建本机控件。
当您的GotFocus事件处理程序再次为新的本机控件运行时,这会一次又一次地重复。这最终会在Windows停止并且不允许创建更多的本机窗口时结束,一段时间后,它会在10,000个控件上拔出插头。它生成“创建窗口句柄错误”异常。
输入和离开事件应该始终用于聚焦事件,只有当用户实际移动焦点时才会触发,并且由于其他原因而不触发,比如这个原因。另外值得注意的是,像您这样更改HideSelection属性是没有意义的,只有当TextBox没有焦点时,属性才会产生影响。当选择有焦点时,它永远不会被隐藏。因此,正确的修复方法是删除这些事件处理程序,并将属性窗口中的HideSelection属性设置为True。默认值。
发布于 2013-06-06 07:09:52
不能为我复制这幅作品:
private void textBox1_Leave(object sender, EventArgs e)
{
((TextBox)sender).HideSelection = false;
}
private void textBox1_Enter(object sender, EventArgs e)
{
((TextBox)sender).HideSelection = true;
}https://stackoverflow.com/questions/16955270
复制相似问题