在 Windows 窗体中,用户输入以 Windows 消息的形式发送到应用程序。 一系列可重写的方法在应用程序、窗体和控件级别处理这些消息。 当这些方法接收到键盘消息时,它们会触发事件,这些事件可以处理以获取有关键盘输入的具体信息。 在许多情况下,Windows 窗体应用程序只需处理这些事件即可处理所有用户输入。 在其他情况下,应用程序可能需要重写处理消息的方法之一,以便在应用程序、窗体或控件接收消息之前拦截特定消息。
键盘事件
所有 Windows 窗体控件都继承一组与鼠标和键盘输入相关的事件。 例如,控件可以处理 KeyPress 事件,以确定按下的键的字符代码。 有关详细信息,请参阅 “使用键盘事件”。
处理用户输入消息的方法
窗体和控件可以访问 IMessageFilter 接口和一组可重写的方法,这些方法可在消息队列中的不同位置处理 Windows 消息。 这些方法都有一个 Message 参数,该参数封装了 Windows 消息的低级别详细信息。 你可以实现或重写这些方法来检查消息,然后处理消息或将其传递给消息队列中的下一个使用者。 下表列出了用于处理 Windows 窗体中所有 Windows 消息的方法。
方法 | 注释 |
---|---|
PreFilterMessage | 此方法在应用程序级别截获排队的(也称为已发布的)Windows 消息。 |
PreProcessMessage | 此方法在 Windows 消息被处理之前,会在窗体和控件级别拦截它们。 |
WndProc | 此方法在窗体和控件级别处理 Windows 消息。 |
DefWndProc | 此方法在窗体和控件级别执行 Windows 消息的默认处理。 这提供了窗口的最小功能。 |
OnNotifyMessage | 此方法在消息经过处理之后,在窗体和控件级别截获这些消息。 必须设置 EnableNotifyMessage 样式位才能调用此方法。 |
键盘和鼠标消息通过一组额外的可重写方法来处理,这些方法专用于处理这些类型的消息。 有关详细信息,请参阅 “预处理密钥 ”部分。
密钥类型
Windows 窗体将键盘输入识别为虚拟键代码,这些代码由按位枚举 Keys 来表示。 Keys通过枚举,可以将一系列按下的键组合在一起,以生成单个值。 这些值对应于 WM_KEYDOWN 和 WM_SYSKEYDOWN Windows 消息附带的值。 可以通过处理 KeyDown 或 KeyUp 事件来检测大多数物理按键。 字符键是枚举的Keys子集,对应于WM_CHAR和WM_SYSCHAR Windows 消息附带的值。 如果按键组合产生一个字符,可以通过处理 KeyPress 事件来检测该字符。 或者,可以使用由 Visual Basic 编程接口公开的Keyboard来探测按下的按键并发送按键。 有关详细信息,请参阅访问键盘(Visual Basic)。
键盘事件的顺序
如前所述,控件上可能发生三个键盘相关事件。 以下序列显示事件的一般顺序:
- 用户推送 A 密钥、密钥预处理、调度和 KeyDown 事件发生。
- 用户按住 A 键,按键进行了预处理和调度,并且发生了KeyPress事件。 当用户保存密钥时,会发生多次此事件。
- 用户释放A键,该键经过预处理和调度后,KeyUp事件发生。
预处理密钥
与其他消息一样,键盘消息在窗体或控件的方法中 WndProc 进行处理。 但是,在处理键盘消息之前,该方法 PreProcessMessage 将调用一个或多个可重写的方法来处理特殊字符键和物理键。 可以在控件处理消息之前重写这些方法来检测和筛选某些键。 下表显示了正在执行的操作以及发生的相关方法,按方法发生的顺序排列。
KeyDown 事件的预处理
行动 | 相关方法 | 注释 |
---|---|---|
检查命令键(如快捷键或菜单快捷方式)。 | ProcessCmdKey | 此方法处理一个优先于常规键的命令键。 如果此方法返回 true ,则不会调度密钥消息,并且不会发生键事件。 如果返回 false , IsInputKey 则调用. |
检查需要预处理或正常字符键的特殊键,该键应引发 KeyDown 事件并调度到控件。 | IsInputKey | 如果该方法返回 true ,这意味着控件是常规字符,并会引发 KeyDown 事件。 如果 false 调用 ,则为 ProcessDialogKey 。 注意:若要确保控件获取某个键或组合键,可以处理PreviewKeyDown事件,并设置PreviewKeyDownEventArgs的IsInputKey为true ,用于您想要的键或键组合。 |
检查导航键(ESC、TAB、返回或箭头键)。 | ProcessDialogKey | 此方法处理在控件中使用特殊功能的物理键,例如在控件与其父项之间切换焦点。 如果即时控件不处理键,则会在父控件上调用ProcessDialogKey,依次直到调用层次结构中最顶层的控件。 如果此方法返回 true ,则预处理已完成,并且不会生成键事件。 如果返回 false ,则会发生一个 KeyDown 事件。 |
KeyPress事件的预处理
行动 | 相关方法 | 注释 |
---|---|---|
检查键是否为控件应处理的正常字符 | IsInputChar | 如果字符是普通字符,则此方法返回 true , KeyPress 将引发该事件,并且不会进一步进行预处理。 否则 ProcessDialogChar ,将调用。 |
检查字符是否是助记符(如按钮上的 &OK) | ProcessDialogChar | 此方法类似于 ProcessDialogKey,称为在控件层次结构中向上调用。 如果控件是容器控件,则通过调用 ProcessMnemonic 来检查自身及其子控件的助记符。 如果 ProcessDialogChar 返回 true , KeyPress 则不会发生事件。 |
处理键盘消息
键盘消息到达 WndProc 窗体或控件的方法后,会由一组可重写的方法进行后续处理。 每个方法都返回一个 Boolean 值,该值指定是否已由控件处理和使用键盘消息。 如果其中一种方法返回 true
,则消息被视为已处理,并且不会传递给控件的基或父级以进一步处理。 否则,消息将保留在消息队列中,并可能在控件的基类或父类的其他方法中处理。 下表显示了处理键盘消息的方法。
方法 | 注释 |
---|---|
ProcessKeyMessage | 此方法处理控件 WndProc 方法接收的所有键盘消息。 |
ProcessKeyPreview | 此方法将键盘消息发送到控件的父级。 如果 ProcessKeyPreview 返回 true ,则不生成任何键事件,否则 ProcessKeyEventArgs 将调用。 |
ProcessKeyEventArgs | 此方法会相应地引发KeyDown和KeyPressKeyUp事件。 |
重写键盘方法
在预处理和处理键盘消息时,有许多方法可用于重写;但是,某些方法比其他方法更好的选择。 下表显示了你可能想要完成的任务,以及替代键盘方法的最佳方法。 有关重写方法的详细信息,请参阅 继承(C# 编程指南) 或 继承(Visual Basic)
任务 | 方法 |
---|---|
截获导航键并引发 KeyDown 事件。 例如,您希望在文本框中处理 Tab 和 Enter 。 | 替代 IsInputKey。 或者,你可以处理PreviewKeyDown事件,并为所需的密钥或键设置PreviewKeyDownEventArgs的IsInputKey为true 。 |
对控件执行特殊输入或导航处理。 例如,你希望使用列表控件中的箭头键来更改所选项。 | 覆盖 ProcessDialogKey |
截获导航键并引发 KeyPress 事件。 例如,在旋转框控件中,希望按多个箭头键加速项目进度。 | 替代 IsInputChar。 |
在 KeyPress 事件期间执行特殊的输入或导航处理。 例如,在列表控件中按住 R 键可以跳过那些以字母 r 开头的项。 | 覆盖 ProcessDialogChar |
执行自定义助记符处理;例如,您希望在工具栏中处理自绘按钮的助记符。 | 替代 ProcessMnemonic。 |