按下文本框中的某个键,KeyDown事件发生在KeyPress之前。
我使用了计数和消息框来查看会发生什么。
以下是我的代码:
int Ncount = 0;
private void Textbox_KeyDown(object sender, KeyEventArgs e)
{
Ncount += 1;
MessageBox.Show("KeyDown's Ncount : " + Ncount.ToString());
}
private void Textbox_KeyPress(object sender, KeyPressEventArgs e)
{
Ncount += 1;
MessageBox.Show("KeyPress's Ncount : " + Ncount.ToString());
}
按下某个键时,会先显示...
KeyPress's Ncount : 2
......紧随其后:
KeyDown's Ncount : 1
KeyDown消息框(带有NCount 1)是否应该在KeyPress消息框(Ncount 2)之前显示?
答案 0 :(得分:3)
简短版本:MessageBox.Show()是绵羊衣服中臭名昭着的Application.DoEvents狼。绝对比DoEvents更温和,但它并没有解决像这样的重入问题。如果要显示调试信息,请始终使用.NET中的Debug
类。
更长版本:要了解这种行为,首先必须了解一个小事实:当您获得KeyDown事件时,操作系统已经生成了KeyPress通知。它耐心地坐在消息队列中,等待您的应用程序恢复调度程序循环。这将是你得到的下一个活动。除非您将e.Handled
设置为true,否则Winforms会查看消息队列并清除KeyPress通知,以便事件不会被触发。
下一个factoid:为了使MessageBox成为模态,或者对于任何ShowDialog()调用,它需要运行一个调度程序循环本身。这确保了基本的东西仍然发生,比如绘制窗口和MessageBox识别OK按钮点击并且用户被叮叮当当!当他点击消息框以外的任何其他内容时。
也许你现在可以连接点,MessageBox中的调度程序循环将在队列中看到KeyPress通知。并导致您的KeyPress事件处理程序运行。所以你显示另一个消息框,它必然位于第一个消息框之上。
这里显着错误,副作用就是盒子的Z顺序不是你想要的那个。如果你设置e.Handled = true并期望它能够工作,你会得到更多的戏剧性。它没有赢。它不可能。它已经在您的KeyDown事件处理程序完成时处理。
没有简单的解决方法。但是,一个人,不要使用它。始终使用Debug类生成调试信息。 MessageBox有太多的副作用。
答案 1 :(得分:1)
KeyPressEventArgs指定用户按下键时组成的字符。例如,当用户按下SHIFT + K时,KeyChar属性返回一个大写的K。
当用户按下某个键时会发生KeyPress事件。与KeyPress事件密切相关的两个事件是KeyUp和KeyDown。当用户按下键时,KeyDown事件在每个KeyPress事件之前,当用户释放键时发生KeyUp事件。当用户按下某个键时,每次重复该字符时都会发生重复的KeyDown和KeyPress事件。一个KeyUp事件在发布时生成。
每个KeyPress事件都会传递一个KeyPressEventArgs。 KeyEventArgs与每个KeyDown和KeyUp事件一起传递。 KeyEventArgs指定是否按下任何修改键(CTRL,SHIFT或ALT)和另一个键。 (此修饰符信息也可以通过Control类的ModifierKeys属性获得。)
将Handled设置为true可取消KeyPress事件。这使得控件无法处理按键操作。“
但是也请注意 -
“某些控件将处理KeyDown上的某些击键。例如,RichTextBox在调用KeyPress之前处理Enter键。在这种情况下,您无法取消KeyPress事件,而必须取消KeyDown中的击键。”< / p>
文档很清楚,KeyDown会在KeyPress之前触发,你可以通过这样的编码来显示它:
Private Sub TextBox1_KeyDown(sender As Object, e As KeyEventArgs) _
Handles TextBox1.KeyDown
Debug.Print("Down")
MessageBox.Show("Down")
e.Handled = True
End Sub
Private Sub TextBox1_KeyPress(sender As Object, e As KeyPressEventArgs) _
Handles TextBox1.KeyPress
Debug.Print("Press")
MessageBox.Show("Press")
End Sub
运行它会看到Debug在“按下”之前写入“Down”。你也可以在两个处理程序中断点,看看KeyDown在KeyPress之前触发。
您还会看到“Press”MessageBox在“Down”MessageBox之前显示。这很奇怪,如果有人可以解释,我会感兴趣。