控制台函数及事件类型与事件常量的整合

参考文章如下:
https://www.cnblogs.com/lxl0928/p/3807262.html
https://www.cnblogs.com/tocy/p/Console-Introduction.html
https://www.cnblogs.com/tocy/p/console_intro_sample.html
https://www.cnblogs.com/tocy/p/console_io_function_intro.html
https://blog.csdn.net/gzzheyi/article/details/7190143
https://blog.csdn.net/ccfxue/article/details/52788199
https://zhidao.baidu.com/question/304673144230099084.html

注意:

本文主要将个人认为常用或重要的知识整合成文,有所省略。

更多详情内容,有意请前往上述参考文章。

HANDLE stdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE); //获取标准输入设备句柄
HANDLE stdInHandle = GetStdHandle(STD_INPUT_HANDLE);  //获取标准输入设备句柄 
INPUT_RECORD inRec;//设置获取事件的变量
DWORD numRead; //返回已读取的记录数
ReadConsoleInput(hInput, &inRec, 1, &numRead); //读取1个输入事件//这是一个非阻塞的函数
CreateConsoleScreenBuffer函数为控制台创建新的屏幕缓冲。
SetConsoleActiveScreenBuffer 函数将屏幕缓冲设置为活动屏幕缓冲,达到显示的目的。
不管是什么类型的屏幕缓冲(活动或者非活动)都可以直接读写。

GetConsoleCursorInfo		获取光标外观及显示或隐藏属性。
SetConsoleCursorInfo		设置光标外观及显示或隐藏属性。
SetConsoleCursorPosition	设置屏幕缓冲的光标位置

GetConsoleSelectionInfo		获取控制台中实际选择的字符区域和位置
GetConsoleScreenBufferInfo	获取窗口大小、屏幕缓冲大小和颜色属性,光标位置,屏幕缓冲字符属性,屏幕缓冲窗口RECT
SetConsoleWindowInfo		设置控制台位置及大小。
							注意调整活动屏幕缓冲的窗口大小会影响实际显示的控制台窗口大小。
SetConsoleScreenBufferSize	设置控制台屏幕缓冲大小。
							其不会触发缓冲区缩放事件
							使用它必须保证设置的屏幕缓冲大小不小于屏幕缓冲窗口大小。
SetConsoleTextAttribute		设置控制台字符属性
GetCurrentConsoleFont		获取控制台当前显示的字体属性可以通过函数
SetConsoleTitle			设置控制台标题
GetConsoleTitle			获取控制台标题
GetConsoleMode			获取控制台模式
SetConsoleMode			设置控制台模式

控制台在创建时会默认启用以下输入模式:
行输入模式(ENABLE_LINE_INPUT
自动处理输入模式(ENABLE_PROCESSED_INPUT
输入回显模式(ENABLE_ECHO_INPUT

自动启用以下输出模式:
自动处理输出模式(ENABLE_PROCESSED_OUTPUT
自动换行模式(ENABLE_WRAP_AT_EOL_OUTPUT

其余模式描述:
ENABLE_PROCESSED_INPUT。 自动处理输入模式,用于控制是否将系统控制键及系统事件放到输出缓冲中。
ENABLE_LINE_INPUT。 自动换行模式。用于控制台输入函数响应方式。
ENABLE_ECHO_INPUT。 输入回显模式
ENABLE_PROCESSED_OUTPUT。 自动处理输出模式
ENABLE_WRAP_AT_EOL_OUTPUT。 输出自动换行模式
ENABLE_MOUSE_INPUT。 使能鼠标输入
ENABLE_WINDOW_INPUT。 用于控制是否在输入缓冲中记录窗口缩放事件。
ENABLE_PROCESSED_INPUT。 用于控制高层控制台输入输出函数。

高层控制台I/O仅有四个函数:ReadFileWriteFileReadConsoleWriteConsole
这两组函数功能相似,主要有两个区别。

  1. -ReadConsole和WriteConsole函数支持ANSI和UNICODE;
    -ReadFile和WriteFile函数仅支持ANSI。
  2. -ReadFile和WriteFile函数支持文件、管道、串口通信等机制;
    - ReadConsole和WriteConsole函数仅支持控制台句柄,不能使用重定向之后的句柄。
    对于需要重定向输入输出的应用建议慎重选择。

函数介绍:

ReadConsoleInput		从输入缓冲中读取并移除输入记录
PeekConsoleInput		从输入缓冲中读取输入记录,但不移除输入记录
GetNumberOfConsoleInputEvents	获取输入缓冲中未读取的输入记录的个数
WriteConsoleInput		在输入缓冲尾部添加一个新的输入记录
FlushConsoleInputBuffer		清空输入缓冲中所有的输入记录

底层输出函数
底层输出函数可以直接访问控制台屏幕缓冲的字符。主要包含以下几个函数:

ReadConsoleOutputCharacter	从屏幕缓冲中读入ANSI或UNICODE字符串。
WriteConsoleOutputCharacter	向屏幕缓冲中写入ANSI或UNICODE字符串。
ReadConsoleOutputAttribute	从屏幕缓冲中复制包含文本属性的字符串。
WriteConsoleOutputAttribute	向屏幕缓冲中写入包含文本属性的字符串。
FillConsoleOutputCharacter	向屏幕缓冲中连续写入多个ANSI或UNICODE字符。
FillConsoleOutputAttribute	向屏幕缓冲中连续写入多个包含文本属性的字符。
ReadConsoleOutput			从屏幕缓冲中读取指定区域的字符(包含文本属性)。
WriteConsoleOutput			向屏幕缓冲中写入指定区域的字符(包含文本属性)。

上面函数中读取指定区域的函数,把屏幕缓冲、源缓冲、目标缓冲当成是由CHAR_INFO结构构成的二维数组,
区域以字符宽度为单位长度,区域使用SMALL_RECT结构体标记。


CTRL+C组合键可以通过以下方式修改控制台的响应处理:

使用函数SetConsoleMode禁用ENABLE_PROCESSED_INPUT输入模式,可以让系统把CTRL+C作为键盘输入而不是终止信号。
使用SetConsoleCtrlHandler 函数可让程序忽略CTRL+C的终止信号。

下面展示相关结构体以及对应事件常量:

COORD pos = {0,0};//设置坐标类
pos = inRec.Event.MouseEvent.dwMousePosition;//获取鼠标位置

typedef struct _KEY_EVENT_RECORD {//键盘事件
  BOOL  bKeyDown; 			// 键位是被按下还是释放
  WORD  wRepeatCount; 		// 重复按键次数,大于1表示键位被按下未释放
  WORD  wVirtualKeyCode; 	// 设备无关的虚拟键码
  WORD  wVirtualScanCode; 	// 设备相关的虚拟扫描码
  union { 					// 转换后的ASCII码或者UNICODE码
    WCHAR UnicodeChar; 
    CHAR  AsciiChar;
  } uChar;
  DWORD dwControlKeyState; 	// 控制键状态,ctrl、shift、alt、caps Lock等
}KEY_EVENT_RECORD,*PKEY_EVENT_RECORD;
//
// ControlKeyState flags
//

#define RIGHT_ALT_PRESSED     0x0001 // 键盘右Alt键被按
#define LEFT_ALT_PRESSED      0x0002 // 键盘左Alt键被按
#define RIGHT_CTRL_PRESSED    0x0004 // 键盘右Ctrl键被按
#define LEFT_CTRL_PRESSED     0x0008 // 键盘左Ctrl键被按
#define SHIFT_PRESSED         0x0010 // 键盘Shift键被按
#define NUMLOCK_ON            0x0020 // 数字锁定被打开
#define SCROLLLOCK_ON         0x0040 //  滚动锁定被打开
#define CAPSLOCK_ON           0x0080 // 大写锁定被打开
#define ENHANCED_KEY          0x0100 // the key is enhanced.//经查找,得知是万国商业机器公司的键盘.属于硬件普通101键或102键
#define NLS_DBCSCHAR          0x00010000 // DBCS for JPN: SBCS/DBCS mode.
#define NLS_ALPHANUMERIC      0x00000000 // DBCS for JPN: Alphanumeric mode.
#define NLS_KATAKANA          0x00020000 // DBCS for JPN: Katakana mode.
#define NLS_HIRAGANA          0x00040000 // DBCS for JPN: Hiragana mode.
#define NLS_ROMAN             0x00400000 // DBCS for JPN: Roman/Noroman mode.
#define NLS_IME_CONVERSION    0x00800000 // DBCS for JPN: IME conversion.
#define ALTNUMPAD_BIT         0x04000000 // AltNumpad OEM char (copied from ntuser\inc\kbd.h) ;internal_NT
#define NLS_IME_DISABLE       0x20000000 // DBCS for JPN: IME enable/disable.

typedef struct _MOUSE_EVENT_RECORD {//鼠标事件
  COORD dwMousePosition; 	// 基于字符的屏幕坐标位置
  DWORD dwButtonState; 		// 鼠标按键标志
  DWORD dwControlKeyState;	// 控制键状态标志
  DWORD dwEventFlags; 		// 鼠标事件标志,单击、双击、按下、弹起、鼠标移动、滚轮事件
} MOUSE_EVENT_RECORD,*PMOUSE_EVENT_RECORD;

//
// ButtonState flags
//

#define FROM_LEFT_1ST_BUTTON_PRESSED    0x0001//最左边按键,理解为鼠标左键单击
#define RIGHTMOST_BUTTON_PRESSED        0x0002//最右边按键,理解为鼠标右键单击
#define FROM_LEFT_2ND_BUTTON_PRESSED    0x0004//左起第二个按键
#define FROM_LEFT_3RD_BUTTON_PRESSED    0x0008//左起第三个按键
#define FROM_LEFT_4TH_BUTTON_PRESSED    0x0010//左起第四个按键
//
// EventFlags
//

#define MOUSE_MOVED   0x0001//移动
#define DOUBLE_CLICK  0x0002//双击
#define MOUSE_WHEELED 0x0004//滚轮滚动->垂直鼠标滚轮滚动
#if(_WIN32_WINNT >= 0x0600)//如果系统版本高于Windows Server 2008
#define MOUSE_HWHEELED 0x0008//水平鼠标滚轮移动 
#endif /* _WIN32_WINNT >= 0x0600 */

typedef struct _INPUT_RECORD {//输入事件:用来存储获得的事件
    WORD EventType;//事件类型
    union {
        KEY_EVENT_RECORD KeyEvent;						//键盘信息
        MOUSE_EVENT_RECORD MouseEvent;					//鼠标信息
        WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;//窗口变更信息
        MENU_EVENT_RECORD MenuEvent;					//菜单信息
        FOCUS_EVENT_RECORD FocusEvent;					//焦点信息
    } Event;//一个共用体成员变量
} INPUT_RECORD, *PINPUT_RECORD;
//
//  EventType flags:
//

KEY_EVENT         			0x0001 //键盘事件
MOUSE_EVENT       			0x0002 //鼠标事件
WINDOW_BUFFER_SIZE_EVENT	0x0004 //窗口变更事件
MENU_EVENT 					0x0008 //菜单事件
FOCUS_EVENT 				0x0010 //焦点变更事件

typedef struct _WINDOW_BUFFER_SIZE_RECORD {//缓冲区缩放事件
    COORD dwSize;
} WINDOW_BUFFER_SIZE_RECORD, *PWINDOW_BUFFER_SIZE_RECORD;

typedef struct _MENU_EVENT_RECORD {//屏幕事件
    UINT dwCommandId;
} MENU_EVENT_RECORD, *PMENU_EVENT_RECORD;

typedef struct _FOCUS_EVENT_RECORD {//焦点事件
    BOOL bSetFocus;
} FOCUS_EVENT_RECORD, *PFOCUS_EVENT_RECORD;

typedef struct _CHAR_INFO {//屏幕中单个元素的信息
    union {//显示字符
        WCHAR UnicodeChar;
        CHAR   AsciiChar;
    } Char;
    WORD Attributes;//字符前景色,背景色
} CHAR_INFO, *PCHAR_INFO;

typedef struct _CONSOLE_FONT_INFO {//字体属性设置
  DWORD nFont;		//系统默认字体索引
  COORD dwFontSize;	//字符大小,宽x高
} CONSOLE_FONT_INFO, *PCONSOLE_FONT_INFO;

typedef struct _CONSOLE_SCREEN_BUFFER_INFO {//屏幕缓冲信息和窗口信息
	COORD dwSize; 			// 缓冲区大小
	COORD dwCursorPosition; // 当前光标位置
	WORD wAttributes; 		// 字符属性
	SMALL_RECT srWindow; 	// 当前窗口显示的大小和位置
	COORD dwMaximumWindowSize; // 最大的窗口缓冲区大小
} CONSOLE_SCREEN_BUFFER_INFO, *PCONSOLE_SCREEN_BUFFER_INFO;

最后,附上一个可执行实例:

#include <Windows.h>
#include <iostream>
using std::wcout;//开放宽字节输出流
using std::endl;//开放回车
int main() {
	std::wcout.imbue(std::locale("chs"));//设置为中文输出
	HANDLE stdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);  /*  获取标准输入设备句柄 */
	HANDLE stdInHandle = GetStdHandle(STD_INPUT_HANDLE);  /*  获取标准输入设备句柄 */
	DWORD numRead; /*  返回已读取的记录数 */

	INPUT_RECORD inRec;//输入事件-它的成员就包含了下列5类事件,一般只需要定义这个,无需独立定义五个
	KEY_EVENT_RECORD keyEveRec;//键盘事件
	MOUSE_EVENT_RECORD mouEveRec;//鼠标事件
	WINDOW_BUFFER_SIZE_RECORD winBufSizRec;//缓冲区缩放事件
	MENU_EVENT_RECORD menEveRec;//屏幕事件
	FOCUS_EVENT_RECORD focEveRec;//焦点事件

	CHAR_INFO charIn;//屏幕中单个元素的信息
	CONSOLE_FONT_INFO conFontIn;//字体属性
	CONSOLE_SCREEN_BUFFER_INFO conScrBufIn;//屏幕缓冲大小
	DWORD title_need_size = 256;//标题文本最大可存储长度
	//SetConsoleMode(stdInHandle, ENABLE_MOUSE_INPUT);//使得能够获得鼠标输入
	//SetConsoleMode(stdInHandle, ENABLE_WINDOW_INPUT);//使得能够获取窗口缩放事件
	/*其余模式描述
	ENABLE_PROCESSED_INPUT。自动处理输入模式,用于控制是否将系统控制键及系统事件放到输出缓冲中。
	ENABLE_LINE_INPUT。自动换行模式。用于控制台输入函数响应方式。
	ENABLE_ECHO_INPUT。输入回显模式
	ENABLE_PROCESSED_OUTPUT。自动处理输出模式
	ENABLE_WRAP_AT_EOL_OUTPUT。输出自动换行模式
	ENABLE_MOUSE_INPUT。使能鼠标输入
	ENABLE_WINDOW_INPUT。用于控制是否在输入缓冲中记录窗口缩放事件。
	ENABLE_PROCESSED_INPUT。用于控制高层控制台输入输出函数。
	详情:https://www.cnblogs.com/tocy/p/console_io_function_intro.html
	*/
	TCHAR * console_title = new TCHAR[title_need_size + 1];//获取用来存储标题文本的内存指针
	memset(console_title, 0, (title_need_size + 1) * sizeof(TCHAR));
	//以0为值将该内存块(console_title)中的((title_need_size + 1) * sizeof(TCHAR))个字节给初始化
	DWORD title_size = GetConsoleTitle(console_title, title_need_size);//获取控制台标题
	if (0 == title_size)//判断获取控制台标题是否出错
	{
		wcout << "调用GetConsoleTitle异常,错误码" << GetLastError() << endl;
		//GetLastError()输出返回的错误码
		delete[] console_title;//释放内存
		return 0;//异常退出程序
	}
	wcout << "控制台标题栏" << console_title << endl;
	SetConsoleTitle(TEXT("ShowConsoleInfo"));//设置新的控制台标题
	// 获取屏幕缓冲信息
	memset(&conScrBufIn, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFO));//初始化
	if (GetConsoleScreenBufferInfo(stdOutHandle, &conScrBufIn))
	{
		wcout << TEXT("屏幕缓冲大小:列数x行数") << conScrBufIn.dwSize.X
			<< TEXT("x") << conScrBufIn.dwSize.Y << endl;
		wcout << TEXT("控制台光标位置(x,y):(") << conScrBufIn.dwCursorPosition.X
			<< TEXT(",") << conScrBufIn.dwCursorPosition.Y << TEXT(")") << endl;
		wcout << TEXT("屏幕缓冲字符属性: ") << conScrBufIn.wAttributes << endl;
		wcout << TEXT("屏幕缓冲显示窗口位置:") << endl
			<< TEXT(" left:") << conScrBufIn.srWindow.Left << endl
			<< TEXT(" Right:") << conScrBufIn.srWindow.Right << endl
			<< TEXT(" Top:") << conScrBufIn.srWindow.Top << endl
			<< TEXT(" Bottom:") << conScrBufIn.srWindow.Bottom << endl;
		wcout << TEXT("最大显示窗口大小:") << conScrBufIn.dwMaximumWindowSize.X
			<< TEXT("x") << conScrBufIn.dwMaximumWindowSize.Y << endl;
	}
	// 红色前景色,绿色背景色
	SetConsoleTextAttribute(stdOutHandle, FOREGROUND_RED | BACKGROUND_GREEN);//颜色设置
	wcout << TEXT("设置红色前景色,绿色背景色") << endl;
	wcout << TEXT("测试字符串,ABCabc123*&@!") << endl << endl;

	CONSOLE_CURSOR_INFO cursor_info;
	memset(&cursor_info, 0, sizeof(cursor_info));
	if (GetConsoleCursorInfo(stdOutHandle, &cursor_info))
	{
		wcout << TEXT("光标可见:") << (cursor_info.bVisible ? TEXT("是") : TEXT("否")) << endl;
		wcout << TEXT("光标占位比例 :") << cursor_info.dwSize << TEXT("%") << endl;

		cursor_info.bVisible = TRUE;
		cursor_info.dwSize = 100;
		SetConsoleCursorInfo(stdOutHandle, &cursor_info);
		wcout << TEXT("设置100%光标占比(回车继续)") << endl;

		getchar();

		// 获取光标位置使用GetConsoleScreenBufferInfo函数
		COORD cursor_pos = { 0, 15 };
		SetConsoleCursorPosition(stdOutHandle, cursor_pos);//这里是移动了光标到指定位置

		cursor_info.dwSize = 50;
		SetConsoleCursorInfo(stdOutHandle, &cursor_info);
		wcout << TEXT("设置50%光标占比 (回车继续)") << endl;
	}
	getchar();

	/*
	gotoxy函数实现:
	void gotoxy(int x,int y){
	COORD pos;
	pos.X = x - 1;
	pos.Y = y - 1;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
	*/

	// 下面设置需要将控制台屏幕缓冲窗口下移一行,用于移除关于设置控制台标题提示
	SMALL_RECT sRect;
	sRect.Left = 0;
	sRect.Right = 0;
	sRect.Top = 1;
	sRect.Bottom = 1;
	if (!SetConsoleWindowInfo(stdOutHandle, FALSE, &sRect))//设置控制台位置及大小。
	{
		wcout << "调用SetConsoleWindowInfo失败,错误码" << GetLastError() << endl;
		return 0;
	}
	{
		COORD pos;
		pos.X = pos.Y = 0;
		// 向窗口中填充字符以获得清屏的效果
		FillConsoleOutputCharacter(stdOutHandle, ' ', conScrBufIn.dwSize.X * conScrBufIn.dwSize.Y, pos, NULL);
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);//将光标移动到起始处
	}
	getchar();
	ReadConsoleInput(stdInHandle, &inRec, 1, &numRead); /* 读取1个输入事件 *///这是一个非阻塞的函数
	// 关闭标准输出设备句柄
	CloseHandle(stdOutHandle);
	// 关闭标准输入设备句柄
	CloseHandle(stdInHandle);
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
控制台程序事件是指在控制台应用程序中发生的各种事件。在控制台应用程序中,用户可以通过输入命令来与程序进行交互。控制台程序事件包括用户输入事件和程序输出事件。 用户输入事件是指用户在控制台中输入命令或数据的事件控制台应用程序通常会等待用户输入,一旦用户输入命令或数据,程序会根据用户的输入来执行相应的操作。用户输入事件可以包括键盘输入事件和鼠标输入事件。键盘输入事件包括按下某个键、释放某个键和输入某个字符等事件。鼠标输入事件包括鼠标移动事件和鼠标点击事件等。 程序输出事件是指程序在控制台中输出信息的事件。当程序执行某个操作时,可能会输出一些信息供用户查看。程序输出事件可以包括打印文本信息、显示错误信息和展示执行结果等。控制台程序通常将输出信息显示在控制台窗口中,用户可以通过滚动条来查看全部输出信息。 控制台程序事件的处理是通过事件处理机制来实现的。当用户输入事件发生时,操作系统会将相关信息传递给控制台程序,并触发对应的事件处理函数控制台程序必须注册事件处理函数,并在函数中对事件进行处理。事件处理函数可以根据事件类型来执行不同的操作,比如根据用户输入执行相应的命令或更新界面展示。 总而言之,控制台程序事件是指在控制台应用程序中发生的用户输入事件和程序输出事件。通过事件处理机制,程序可以对这些事件进行处理,并与用户进行交互。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值