控制台输入缓冲区

每个控制台都有一个包含输入事件记录队列的输入缓冲区。 当控制台的窗口获得键盘焦点时,控制台会将每个输入事件(例如单次击键、鼠标移动或鼠标按钮单击)设置为它放置在控制台输入缓冲区中的输入记录。

应用程序可以使用高级控制台 I/O 函数间接访问控制台的输入缓冲区,或者使用低级控制台输入函数直接访问控制台的输入缓冲区。 高级输入函数筛选并处理输入缓冲区中的数据,只返回输入字符流。 低级输入函数使应用程序可以直接从控制台的输入缓冲区读取输入记录,或将输入记录放入输入缓冲区。 若要打开控制台输入缓冲区的句柄,请在对 CreateFile 函数的调用中指定 CONIN$ 值。

输入记录是一种结构体,包含有关所发生事件的类型的信息(键盘、鼠标、窗口调整大小、焦点或菜单事件)以及有关事件的特定详细信息。 INPUT_RECORD 结构中的 EventType 成员指示记录中包含哪种类型的事件。

焦点和菜单事件放置在控制台的输入缓冲区中,供系统内部使用,应用程序应将其忽略。

键盘事件

按下或松开任何键时,将生成键盘事件;这包括控制键。 但是,在不与其他字符组合的情况下按下和松开 Alt 键时,对系统具有特殊意义,并且不会传递到应用程序。 此外,如果输入句柄处于已处理模式,则不会传递 Ctrl+C 组合键。

如果输入事件是击键,则 INPUT_RECORD 中的 Event 成员是包含以下信息的 KEY_EVENT_RECORD 结构:

  • 一个布尔值,指示键是按下还是松开。
  • 当某个键被按住时,重复计数可以大于 1。
  • 虚拟键代码,以独立于设备的方式标识给定键。
  • 虚拟扫描代码,指示键盘硬件生成的设备依赖值。
  • 转换后的 Unicode™ 或 ANSI 字符。
  • 一个标志变量,指示控制键(ALT、CTRL、SHIFT、NUM LOCK、SCROLL LOCK 和 CAPS LOCK 键)的状态以及指示是否按下了增强键。 对于 IBM® 101 键和 102 键键盘,增强键是数字键盘区左侧键群中的 INS、DEL、HOME、END、PAGE UP、PAGE DOWN 和箭头键,以及数字键盘区中的斜杠 (/) 和 ENTER 键。

鼠标事件

每当用户移动鼠标或者按下或松开鼠标按钮之一时,就会生成鼠标事件。 仅当满足以下条件时,鼠标事件才会放置在输入缓冲区中:

  • 控制台输入模式设置为 ENABLE_MOUSE_INPUT(默认模式)。
  • 控制台窗口具有键盘焦点。
  • 鼠标指针位于控制台窗口的边框内。

如果输入事件是鼠标事件,则 INPUT_RECORD 中的 Event 成员是包含以下信息的 MOUSE_EVENT_RECORD 结构:

  • 鼠标指针的坐标基于控制台屏幕缓冲区坐标系中的字符单元格行和列来确定。
  • 指示鼠标按钮状态的标志变量。
  • 一个标志变量,指示控制键(ALT、CTRL、SHIFT、NUM LOCK、SCROLL LOCK 和 CAPS LOCK)的状态以及指示是否按下了增强键。 对于 IBM 101 键和 102 键键盘,增强键是数字键盘区左侧键群中的 INS、DEL、HOME、END、PAGE UP、PAGE DOWN 和箭头键,以及数字键盘区中的斜杠 (/) 和 ENTER 键。
  • 一个标志变量,指示事件是普通的按钮按下或按钮松开事件、鼠标移动事件还是双击事件的第二次点击。

注意

鼠标位置坐标基于控制台屏幕缓冲区(而不是控制台窗口)确定。 屏幕缓冲区可能相对窗口已经滚动过,因此窗口左上角不一定是控制台屏幕缓冲区的 (0,0) 坐标。 若要确定鼠标相对于窗口坐标系的坐标,请从鼠标位置坐标中减去窗口原点坐标。 使用 GetConsoleScreenBufferInfo 函数确定窗口原点坐标。

MOUSE_EVENT_RECORD 结构的 dwButtonState 成员有一个指示每个鼠标按钮的位。 如果按下按钮,则该位为 1;如果松开按钮,则为 0。 按钮松开事件由 MOUSE_EVENT_RECORDdwEventFlags 成员的 0 值以及按钮位从 1 更改为 0 来检测。 GetNumberOfConsoleMouseButtons 函数检索鼠标上的按钮数。

缓冲区重设大小事件

控制台窗口的菜单使用户能够更改活动屏幕缓冲区的大小;此更改生成缓冲区重设大小事件。 如果将控制台的输入模式设置为 ENABLE_WINDOW_INPUT(即禁用默认模式),缓冲区重设大小事件将放置在输入缓冲区中。

如果输入事件是缓冲区重设大小事件,则 INPUT_RECORDEvent 成员是包含控制台屏幕缓冲区的新大小的 WINDOW_BUFFER_SIZE_RECORD 结构,以字符单元列和行表示。

如果用户减小了控制台屏幕缓冲区的大小,则缓冲区的丢弃部分中的任何数据都将丢失。

由于应用程序调用 SetConsoleScreenBufferSize 函数而对控制台屏幕缓冲区大小产生的更改不会生成为缓冲区大小调整事件。