在.NET中,KeyDown和KeyPress有什么区别?

208

.NET中KeyDownKeyPress事件有什么区别?

10个回答

353
显然,这方面存在很多误解!在实践中,“KeyDown”和“KeyPress”的唯一实际区别是,“KeyPress”会传递按键产生的字符,并且只在有字符时调用。
换句话说,如果您在键盘上按下“A”,您将获得以下事件序列:
1. KeyDown: KeyCode=Keys.A, KeyData=Keys.A, Modifiers=Keys.None 2. KeyPress: KeyChar='a' 3. KeyUp: KeyCode=Keys.A
但是,如果您按下“Shift”+“A”,您将获得:
1. KeyDown: KeyCode=Keys.ShiftKey, KeyData=Keys.ShiftKey, Shift, Modifiers=Keys.Shift 2. KeyDown: KeyCode=Keys.A, KeyData=Keys.A | Keys.Shift, Modifiers=Keys.Shift 3. KeyPress: KeyChar='A' 4. KeyUp: KeyCode=Keys.A 5. KeyUp: KeyCode=Keys.ShiftKey
如果您按住键一段时间,您将获得类似以下的结果:
1. KeyDown: KeyCode=Keys.ShiftKey, KeyData=Keys.ShiftKey, Shift, Modifiers=Keys.Shift 2. KeyDown: KeyCode=Keys.ShiftKey, KeyData=Keys.ShiftKey, Shift, Modifiers=Keys.Shift 3. KeyDown: KeyCode=Keys.ShiftKey, KeyData=Keys.ShiftKey, Shift, Modifiers=Keys.Shift 4. KeyDown: KeyCode=Keys.ShiftKey, KeyData=Keys.ShiftKey, Shift, Modifiers=Keys.Shift 5. KeyDown: KeyCode=Keys.ShiftKey, KeyData=Keys.ShiftKey, Shift, Modifiers=Keys.Shift 6. KeyDown: KeyCode=Keys.A, KeyData=Keys.A | Keys.Shift, Modifiers=Keys.Shift 7. KeyPress: KeyChar='A' 8. KeyDown: KeyCode=Keys.A, KeyData=Keys.A | Keys.Shift, Modifiers=Keys.Shift 9. KeyPress: KeyChar='A' 10. KeyDown: KeyCode=Keys.A, KeyData=Keys.A | Keys.Shift, Modifiers=Keys.Shift 11. KeyPress: KeyChar='A' 12. KeyDown: KeyCode=Keys.A, KeyData=Keys.A | Keys.Shift, Modifiers=Keys.Shift 13. KeyPress: KeyChar='A' 14. KeyDown: KeyCode=Keys.A, KeyData=Keys.A | Keys.Shift, Modifiers=Keys.Shift 15. KeyPress: KeyChar='A' 16. KeyUp: KeyCode=Keys.A 17. KeyUp: KeyCode=Keys.ShiftKey
请注意,KeyPress 发生在 KeyDownKeyUp 之间,不是KeyUp 之后,与其他答案所述的相反,当未生成字符时,不会调用 KeyPress,而且在按住键时会重复调用 KeyDown,这也与其他答案相反。
以下是不会直接导致调用 KeyPress 的按键示例:
  • ShiftCtrlAlt
  • F1F12
  • 方向键
以下是导致调用 KeyPress 的按键示例:
  • AZ09
  • 空格键
  • Tab(KeyChar='\t',ASCII 9)
  • 回车键(KeyChar='\r',ASCII 13)
  • Esc(KeyChar='\x1b',ASCII 27)
  • 退格键(KeyChar='\b',ASCII 8)
好奇的人可以了解一下,KeyDown 大致对应于 WM_KEYDOWNKeyPress 对应于 WM_CHARKeyUp 对应于 WM_KEYUPWM_KEYDOWN 可以少于按键重复次数,但它会发送一个重复计数,我记得 WinForms 使用该计数生成每个重复的 KeyDown。

2
非常好的解释,谢谢。不过有一个注意事项,Escape键在Chrome上不会触发KeyPress事件(其他浏览器我不确定)。 - Barney Szabolcs
3
Chrome 运行 .NET? - P Daddy
@PDaddy,我知道默认情况下至少Tab不会触发KeyDown或KeyUp。 - PsychoData
@PsychoData:这是因为Tab键会改变焦点,所以它不会被处理为输入。如果你重写ProcessDialogKey方法,并在keyDataKeys.TabKeys.Shift | Keys.Tab时返回false,那么你就可以在(On)Key(Down|Press|Up)中看到Tab键的输入了。 - P Daddy
@PDaddy 我处理了 PreviewKeyDown 事件。它现在可以工作了,我不会再去碰它了。 - PsychoData
显示剩余3条评论

80

18
其他答案大多存在错误,但是这个答案最接近实际情况。KeyPress事件仅针对字符键触发,并且遵循键盘输入延迟/重复设置。实际事件顺序为:1)KeyDown 2)对于字符键KeyPress事件会触发一次或多次(取决于系统设置和按键按住的时间长度)3)KeyUp。 - Filip Navara
我没有足够的声望来做这件事,但是有人能否编辑维基并将上面评论和被接受的答案的内容合并在一起? - Josh Kodroff
12
Filip Navara的评论并不完全正确。如果按键被按住,你将会收到KeyDown、KeyPress、KeyDown、KeyPress、KeyDown、KeyPress、KeyUp。KeyDown会在每次重复时被调用。 - P Daddy

9

KeyPress事件仅在可打印字符时触发,并在KeyDown事件之后触发。根据输入延迟设置,可能会有多个KeyDown和KeyPress事件,但只有一个KeyUp事件。

KeyDown
KeyPress
KeyUp


你接近了,但是序列有些错误。 - P Daddy
@P Daddy - 我已经更正了,应该在从记忆中转移之前进行双重检查。 - stevehipwell
@Stevo3000,提醒一下:非可打印的Unicode字符也会触发KeyPress事件。我有一个应用程序,可以将条形码读取器插入文本框中读取的数据,并且读取器包括非可打印的Unicode字符。 - Jeff LaFay
@jlafay - 根据MSDN的说法,非字符键不会触发KeyPress事件;但是,非字符键会触发KeyDown和KeyUp事件。 - stevehipwell
@Stevo3000,我不确定条形码扫描器如何将文本输入到文本框中,但是它发送的特殊字符会触发KeyPress事件。该值以不可打印字符开头,并以不可打印字符结束。因此,如果这是真的,我不确定它是如何触发的。也许我可以使用IL Spy查看包含事件的.Net程序集,以更好地了解实际检测到的内容。 - Jeff LaFay

5

KeyPress是比KeyDown(和KeyUp)更高级的抽象层。KeyDown和KeyUp与硬件相关:键盘上按键的实际动作。而KeyPress更多地表示“我从键盘接收到了一个字符”。


4

按下键盘按键并没有松开称为KeyDown,Keypress是完整的按下和释放循环。

换句话说,KeyDown + KeyUp = Keypress


3
根据MSDN的说明,事件顺序为:KeyDown、KeyPress、KeyUp。(http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress(VS.71).aspx) - Nathan Koop
@RobCowell 此外,正如jlafay所指出的,KeyPress与KeyDown或KeyUp没有任何依赖关系。 - PsychoData

4

来自MSDN:

按键事件按以下顺序发生:

  1. KeyDown

  2. KeyPress

  3. KeyUp

此外,KeyPress允许您将操作声明为“已处理”,以防止其执行任何操作。


FYI,KeyDown和KeyUp也有一个Handled属性,您可以设置它,以便它不会在KeyPress和其他键事件之间发生冲突。 - Jeff LaFay
顺便提一下,虽然 KeyUp 和 KeyDown 一样都会得到一个 KeyEventArgs 参数,但是对于 KeyUp,其 Handled 属性是无效的(SuppressKeyPress 也是无效的)。 - JonP

3

2
Blogging Developer网站得知:
要理解keydown和keypress之间的区别,有必要了解"字符""键"之间的区别。一个"键"是计算机键盘上的物理按钮,而一个"字符"是通过按下按钮来输入的符号。理论上,keydown和keyup事件代表按下或释放,而keypress事件代表输入字符。然而,这个理论在所有浏览器中的实现并不相同。 注意:你也可以尝试使用上述网站提供的Key Event Tester来理解这个概念。

链接失效,请查看其他答案。 - Pang

1

无论按键按下多长时间,KEYUP事件只会在释放按键时捕获一次,因此如果您想捕获这样的按压事件,KEYUP是适合的事件。


KeyPress事件会在每次输入生成字符时触发,无论是响应物理按键还是由于自动重复功能而产生的字符。键盘输入工作原理文档记录了这种行为。 - IInspectable
你说得对。我会更新我的答案。正确的答案是使用KEYUP,它将在释放一个或多个按键时触发一次。 - Michael Haephrati
虽然不再是错误的,但它仍然没有回答所提出的问题。这并不有用。 - IInspectable

0
最简单的解释:
我按住“d”键一秒钟,然后松开。

dddddd

在第一个d出现在屏幕上之前,keydown事件只发生了一次,keypress事件发生了6次,而keyup事件则是在最后一个d出现后才发生。


该死,我读错了问题,以为他是指JavaScript。 - Stephen Lacy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接