使用键盘概述

在 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_KEYDOWNWM_SYSKEYDOWN Windows 消息附带的值。 可以通过处理 KeyDownKeyUp 事件来检测大多数物理按键。 字符键是枚举的Keys子集,对应于WM_CHAR和WM_SYSCHAR Windows 消息附带的值。 如果按键组合产生一个字符,可以通过处理 KeyPress 事件来检测该字符。 或者,可以使用由 Visual Basic 编程接口公开的Keyboard来探测按下的按键并发送按键。 有关详细信息,请参阅访问键盘(Visual Basic)。

键盘事件的顺序

如前所述,控件上可能发生三个键盘相关事件。 以下序列显示事件的一般顺序:

  1. 用户推送 A 密钥、密钥预处理、调度和 KeyDown 事件发生。
  2. 用户按住 A 键,按键进行了预处理和调度,并且发生了KeyPress事件。 当用户保存密钥时,会发生多次此事件。
  3. 用户释放A键,该键经过预处理和调度后,KeyUp事件发生。

预处理密钥

与其他消息一样,键盘消息在窗体或控件的方法中 WndProc 进行处理。 但是,在处理键盘消息之前,该方法 PreProcessMessage 将调用一个或多个可重写的方法来处理特殊字符键和物理键。 可以在控件处理消息之前重写这些方法来检测和筛选某些键。 下表显示了正在执行的操作以及发生的相关方法,按方法发生的顺序排列。

KeyDown 事件的预处理

行动 相关方法 注释
检查命令键(如快捷键或菜单快捷方式)。 ProcessCmdKey 此方法处理一个优先于常规键的命令键。 如果此方法返回 true,则不会调度密钥消息,并且不会发生键事件。 如果返回 falseIsInputKey 则调用.
检查需要预处理或正常字符键的特殊键,该键应引发 KeyDown 事件并调度到控件。 IsInputKey 如果该方法返回 true,这意味着控件是常规字符,并会引发 KeyDown 事件。 如果 false调用 ,则为 ProcessDialogKey 。 注意:若要确保控件获取某个键或组合键,可以处理PreviewKeyDown事件,并设置PreviewKeyDownEventArgsIsInputKeytrue,用于您想要的键或键组合。
检查导航键(ESC、TAB、返回或箭头键)。 ProcessDialogKey 此方法处理在控件中使用特殊功能的物理键,例如在控件与其父项之间切换焦点。 如果即时控件不处理键,则会在父控件上调用ProcessDialogKey,依次直到调用层次结构中最顶层的控件。 如果此方法返回 true,则预处理已完成,并且不会生成键事件。 如果返回 false,则会发生一个 KeyDown 事件。

KeyPress事件的预处理

行动 相关方法 注释
检查键是否为控件应处理的正常字符 IsInputChar 如果字符是普通字符,则此方法返回 trueKeyPress 将引发该事件,并且不会进一步进行预处理。 否则 ProcessDialogChar ,将调用。
检查字符是否是助记符(如按钮上的 &OK) ProcessDialogChar 此方法类似于 ProcessDialogKey,称为在控件层次结构中向上调用。 如果控件是容器控件,则通过调用 ProcessMnemonic 来检查自身及其子控件的助记符。 如果 ProcessDialogChar 返回 trueKeyPress 则不会发生事件。

处理键盘消息

键盘消息到达 WndProc 窗体或控件的方法后,会由一组可重写的方法进行后续处理。 每个方法都返回一个 Boolean 值,该值指定是否已由控件处理和使用键盘消息。 如果其中一种方法返回 true,则消息被视为已处理,并且不会传递给控件的基或父级以进一步处理。 否则,消息将保留在消息队列中,并可能在控件的基类或父类的其他方法中处理。 下表显示了处理键盘消息的方法。

方法 注释
ProcessKeyMessage 此方法处理控件 WndProc 方法接收的所有键盘消息。
ProcessKeyPreview 此方法将键盘消息发送到控件的父级。 如果 ProcessKeyPreview 返回 true,则不生成任何键事件,否则 ProcessKeyEventArgs 将调用。
ProcessKeyEventArgs 此方法会相应地引发KeyDownKeyPressKeyUp事件。

重写键盘方法

在预处理和处理键盘消息时,有许多方法可用于重写;但是,某些方法比其他方法更好的选择。 下表显示了你可能想要完成的任务,以及替代键盘方法的最佳方法。 有关重写方法的详细信息,请参阅 继承(C# 编程指南)继承(Visual Basic)

任务 方法
截获导航键并引发 KeyDown 事件。 例如,您希望在文本框中处理 TabEnter 替代 IsInputKey。 或者,你可以处理PreviewKeyDown事件,并为所需的密钥或键设置PreviewKeyDownEventArgsIsInputKeytrue
对控件执行特殊输入或导航处理。 例如,你希望使用列表控件中的箭头键来更改所选项。 覆盖 ProcessDialogKey
截获导航键并引发 KeyPress 事件。 例如,在旋转框控件中,希望按多个箭头键加速项目进度。 替代 IsInputChar
KeyPress 事件期间执行特殊的输入或导航处理。 例如,在列表控件中按住 R 键可以跳过那些以字母 r 开头的项。 覆盖 ProcessDialogChar
执行自定义助记符处理;例如,您希望在工具栏中处理自绘按钮的助记符。 替代 ProcessMnemonic

另请参阅