c/c++ console(控制台)编程详解
前言:
控制台文本窗口的控制是基于win32 api(win32 api可理解为微软给我们提供的一系列函数的集合)实现的;
例1:
#include <stdio.h>int main() { printf("Hello World!\n"); return 0; }
运行结果:
例1中,我们用printf()函数实现在控制台输出了hello world!然而当我们想要将之前输出的内容清除时,在stdio.h中的函数并不能满足我们的需求;这时我们就要借助于win32 api函数
例2:
#include <stdio.h> #include <windows.h> int main() { printf("Hello World!\n"); Sleep(1000); system("cls"); return 0; }
运行结果:
例2中,用到windows.h中的Sleep();system();函数,Sleep(1000)函数功能为延时1s后程序向下运行,system(“cls”)清除内容,所以在例2中,程序运行显示hello world!一秒后就清除
用于控制台窗口操作的API函数如下:
GetConsoleScreenBufferInfo 获取控制台窗口信息
GetConsoleTitle 获取控制台窗口标题
ScrollConsoleScreenBuffer 在缓冲区中移动数据块
SetConsoleScreenBufferSize 更改指定缓冲区大小
SetConsoleTitle 设置控制台窗口标题
SetConsoleWindowInfo 设置控制台窗口信息
例3:
#include <windows.h> #include <stdio.h> int main(void) { SetConsoleTitle(L"hello world!"); // 设置窗口标题 printf("hello world!"); return 0; }
运行结果:
在例3中,我们使用了setconsoletitle()函数;窗口标题已然改变成为hello world!了
关于其它函数的使用方法,可以度,这里暂且不做赘述了。。。。。
1.控制台初始化
#include <iostream> #include <windows.h> using namespace std; int main() { //设置控制台窗口标题 //SetConsoleTitle("更改标题字符串") SetConsoleTitleA("hello world!"); //获取控制台窗口信息; //GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, CONSOLE_SCREEN_BUFFER_INFO *bInfo) //第一个hConsoleOutput参数(标准控制句柄)通过GetStdHandle()函数返回值获得 //第二个参数CONSOLE_SCREEN_BUFFER_INFO 保存控制台信息结构体指针 /*数据成员如下: { COORD dwSize; // 缓冲区大小 COORD dwCursorPosition; //当前光标位置 WORD wAttributes; //字符属性 SMALL_RECT srWindow; //当前窗口显示的大小和位置 COORD dwMaximumWindowSize; //最大的窗口缓冲区大小 } */ HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO bInfo; GetConsoleScreenBufferInfo(hOutput, &bInfo); cout << "窗口缓冲区大小:" << bInfo.dwSize.X << ", " << bInfo.dwSize.Y << endl; cout << "窗口坐标位置:" << bInfo.srWindow.Left << ", " << bInfo.srWindow.Top << ", "<< bInfo.srWindow.Right << ", " << bInfo.srWindow.Bottom << endl; //设置显示区域坐标 //SetConsoleWindowInfo(HANDLE, BOOL, SMALL_RECT *); SMALL_RECT rc = {0,0, 79, 24}; // 坐标位置结构体初始化 SetConsoleWindowInfo(hOutput,true ,&rc); cout << "窗口显示坐标位置:" << bInfo.srWindow.Left << ", " << bInfo.srWindow.Top << ", "<< bInfo.srWindow.Right << ", " << bInfo.srWindow.Bottom << endl; //更改指定缓冲区大小 //SetConsoleScreenBufferSize(HANDLE hConsoleOutput, COORD dwSize) //COORD为一个数据结构体 COORD dSiz = {80, 25}; SetConsoleScreenBufferSize(hOutput, dSiz); cout << "改变后大小:" << dSiz.X << ", " << dSiz.Y << endl; //获取控制台窗口标题 //GetConsoleTitle(LPTSTR lpConsoleTitle, DWORD nSize) //lpConsoleTitle为指向一个缓冲区指针以接收包含标题的字符串;nSize由lpConsoleTitle指向的缓冲区大小 char cTitle[255]; GetConsoleTitleA(cTitle, 255); cout << "窗口标题:" << cTitle << endl; // 关闭标准输出设备句柄 CloseHandle(hOut); return 0; }
2.设置文本属性(文本颜色、移动控制)
#include <iostream> #include <windows.h> using namespace std; int main() { /*设置文本属 BOOL SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes);//句柄, 文本属性*/ HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); // 获取标准输出设备句柄 WORD wr1 = 0xfa;//定义颜色属性;第一位为背景色,第二位为前景色 SetConsoleTextAttribute(hOut, wr1); cout << "hello world!" << endl; WORD wr2 = FOREGROUND_RED | FOREGROUND_INTENSITY;//方法二用系统宏定义颜色属性 SetConsoleTextAttribute(hOut, wr2); cout << "hello world!" << endl; /*移动文本位置位置 BOOL ScrollConsoleScreenBuffer(HANDLE hConsoleOutput, CONST SMALL_RECT* lpScrollRectangle, CONST SMALL_RECT* lpClipRectangle, COORD dwDestinationOrigin,CONST CHAR_INFO* lpFill); // 句柄// 裁剪区域// 目标区域 // 新的位置// 填充字符*/ //输出文本 SetConsoleTextAttribute(hOut, 0x0f); cout << "01010101010101010101010101010" << endl; cout << "23232323232323232323232323232" << endl; cout << "45454545454545454545454545454" << endl; cout << "67676767676767676767676767676" << endl; SMALL_RECT CutScr = {1, 2, 10, 4}; //裁剪区域与目标区域的集合行成剪切区域 SMALL_RECT PasScr = {7, 2, 11, 9}; //可以是NULL,即全区域 COORD pos = {1, 8}; //起点坐标,与裁剪区域长宽构成的区域再与目标区域的集合为粘贴区 //定义填充字符的各个参数及属性 SetConsoleTextAttribute(hOut, 0x1); CONSOLE_SCREEN_BUFFER_INFO Intsrc; GetConsoleScreenBufferInfo(hOut, &Intsrc); CHAR_INFO chFill = {'A', Intsrc.wAttributes}; //定义剪切区域填充字符 ScrollConsoleScreenBuffer(hOut, &CutScr, &PasScr, pos, &chFill); //移动文本 CloseHandle(hOut); // 关闭标准输出设备句柄 return 0; }
运行结果:
WORD文本属性预定义宏:(可以直接用16进制表示,WORD w = 0xf0;前一位表示背景色,后一位代表前景色) FOREGROUND_BLUE 蓝色 FOREGROUND_GREEN 绿色 FOREGROUND_RED 红色 FOREGROUND_INTENSITY 加强 BACKGROUND_BLUE 蓝色背景 BACKGROUND_GREEN 绿色背景 BACKGROUND_RED 红色背景 BACKGROUND_INTENSITY 背景色加强 COMMON_LVB_REVERSE_VIDEO 反色 当前文本属性信息可通过调用函数GetConsoleScreenBufferInfo后,在CONSOLE_SCREEN_ BUFFER_INFO结构成员wAttributes中得到。
在指定位置处写属性 BOOL WriteConsoleOutputAttribute(HANDLE hConsoleOutput, CONST WORD *lpAttribute, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfAttrsWritten); //句柄, 属性, 个数, 起始位置, 已写个数*/ 填充指定数据的字符 BOOL FillConsoleOutputCharacter(HANDLE hConsoleOutput, TCHAR cCharacter,DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten); // 句柄, 字符, 字符个数, 起始位置, 已写个数*/ 在当前光标位置处插入指定数量的字符 BOOL WriteConsole(HANDLE hConsoleOutput, CONST VOID *lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten,LPVOID lpReserved); //句柄, 字符串, 字符个数, 已写个数, 保留*/ 向指定区域写带属性的字符 BOOL WriteConsoleOutput(HANDLE hConsoleOutput, CONST CHAR_INFO *lpBuffer, COORD dwBufferSize, COORD dwBufferCoord,PSMALL_RECT lpWriteRegion ); // 句柄 // 字符数据区// 数据区大小// 起始坐标// 要写的区域*/ 在指定位置处插入指定数量的字符 BOOL WriteConsoleOutputCharacter(HANDLE hConsoleOutput, LPCTSTR lpCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten); // 句柄// 字符串// 字符个数// 起始位置// 已写个数*/ 填充字符属性 BOOL FillConsoleOutputAttribute(HANDLE hConsoleOutput, WORD wAttribute,DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfAttrsWritten); //句柄, 文本属性, 个数, 开始位置, 返回填充的个数*/ // 设置代码页, SetConsoleOutputCP(437);如(简体中文) 设置成936
3.光标操作控制
#include <iostream> #include <windows.h> using namespace std; int main() { cout << "hello world!" << endl; //设置光标位置 //SetConsoleCursorPosition(HANDLE hConsoleOutput,COORD dwCursorPosition); //设置光标信息 //BOOL SetConsoleCursorInfo(HANDLE hConsoleOutput, PCONST PCONSOLE_CURSOR_INFO lpConsoleCursorInfo); //获取光标信息 //BOOL GetConsoleCursorInfo(HANDLE hConsoleOutput, PCONSOLE_CURSOR_INFO lpConsoleCursorInfo); //参数1:句柄;参数2:CONSOLE_CURSOR_INFO结构体{DWORD dwSize;(光标大小取值1-100)BOOL bVisible;(是否可见)} Sleep(2000);//延时函数 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); COORD w = {0, 0}; SetConsoleCursorPosition(hOut, w); CONSOLE_CURSOR_INFO cursorInfo = {1, FALSE}; Sleep(2000);//延时函数 SetConsoleCursorInfo(hOut, &cursorInfo); CloseHandle(hOut); // 关闭标准输出设备句柄 return 0; }
运行结果:
输出hello world!后延时两秒,光标从第二行移到行首,再2秒后光标隐藏不显示;
4.键盘操作控制
#include <iostream> #include <windows.h> #include <conio.h> using namespace std; HANDLE hOut; //清除函数 void cle(COORD ClPos) { SetConsoleCursorPosition(hOut, ClPos); cout << " " << endl; } //打印函数 void prin(COORD PrPos) { SetConsoleCursorPosition(hOut, PrPos); cout << "hello world!" << endl; } //移动函数 void Move(COORD *MoPos, int key) { switch(key) { case 72: MoPos->Y--;break; case 75: MoPos->X--;break; case 77: MoPos->X++;break; case 80: MoPos->Y++;break; default: break; } } int main() { cout << "用方向键移动下行输出内容" << endl; hOut = GetStdHandle(STD_OUTPUT_HANDLE);//取句柄 COORD CrPos = {0, 1};//保存光标信息 prin(CrPos);//打印 //等待键按下 while(1) { if(kbhit()) { cle(CrPos);//清除原有输出 Move(&CrPos, getch()); prin(CrPos); } } return 0; }
运行结果:
可以用方向键任意移动hello world!
注意区分 getch(); getche(); getcher();函数
综合案例贪吃蛇,推箱子,俄罗斯方块(待续。。。)