控制台 订阅
控制台可以指:控制室内的专业家具;控制面板,Windows图形用户界面的一部分;命令行界面(CLI),也有人称之为字符用户界面(CUI);机械控制台,如交通工具的驾驶舱; 展开全文
控制台可以指:控制室内的专业家具;控制面板,Windows图形用户界面的一部分;命令行界面(CLI),也有人称之为字符用户界面(CUI);机械控制台,如交通工具的驾驶舱;
信息
外文名
Console
领    域
工程
中文名
控制台
控制台控制台
控制台(英语:Console),在运行关键任务的控制室当中,根据特殊的人体工程学设计制造的,为操作和调度人员提供可以承载各种办公设备和专用设备的专业家具。控制台应用范围非常广泛,涵盖电力生产和电力调度中心,核工业设施运行中心,能源生产中心,交通运行监控中心,航空航天任务监控中心,公共安全任务监控中心,金融交易中心监控中心,广播电视监控中心,工厂中控室等等非常多的应用场景,这些类型的控制室,监控中心,控制中心都属于关键任务控制环境(Mission Critical Control Environment),影响着经济与社会的有序运作。
收起全文
精华内容
参与话题
问答
  • C++控制台操作(基本操作的代码)

    万次阅读 多人点赞 2012-06-08 13:35:03
    控制台窗口界面编程控制 〇、摘要 一、概述 二、控制台文本窗口的一般控制步骤 三、控制台窗口操作 四、文本属性操作 五、文本输出 六、文本操作示例 七、滚动和移动 八、光标操作 九、读取键盘...

    控制台窗口界面编程控制

    〇、摘要

    一、概述

    二、控制台文本窗口的一般控制步骤

    三、控制台窗口操作

    四、文本属性操作

    五、文本输出

    六、文本操作示例

    七、滚动和移动

    八、光标操作

    九、读取键盘信息

    十、读取鼠标信息

    十一、结语

    补充篇--经典程序(Internet资源)

    摘要:

    文本界面的控制台应用程序开发是深入学习C++、掌握交互系统的实现方法的最简单的一种手段。然而,Visual C++的C++专用库却没有TC所支持的文本(字符)屏幕控制函数,为此本系列文章从一般控制步骤、控制台窗口操作、文本(字符)控制、滚动和移动光标、键盘和鼠标等几个方面讨论控制台窗口界面的编程控制方法。

    在众多C++开发工具中,由于Microsoft本身的独特优势,选用 Visual C++已越来越被众多学习者所接受。显然,现今如果还再把TC作为开发环境的话,不仅没有必要,而且也不利于向Windows应用程序开发的过渡。然而,Visual C++的C++专用库却没有TC所支持的文本屏幕(控制台窗口)控制函数(相应的头文件是conio.h)。这必然给C++学习者在文本界面设计和编程上带来诸多不便。要知道,文本界面设计是一种深入学习C++、掌握交互系统的实现方法的最简单的一种手段,它不像C++的Windows图形界面应用 程序,涉及知识过多。为此,本系列文章来讨论在Visual C++ 6.0开发环境中,如何编写具有美观清晰的控制台窗口界面的C++应用程序。


    (一) 概述操作

    所谓控制台应用程序,就是指那些需要与传统DOS操作系统保持某种程序的兼容,同时又不需要为用户提供完善界面的程序。简单地讲,就是指在Windows环境下运行的DOS程序。一旦控制台应用程序在Windows操作系统中运行后,就会弹出一个窗口。例如下列代码:

    #include <stdio.h>

    int main(int argc,char *argv[])

    {

           printf("Hello, Console!\n");

           return 0;

    }

    单击小型编译工具栏中的“Build”按钮或按F7键,系统出现一个对话框,询问是否将此项目的工作文件夹设定源文件所在的文件夹,单击[是]按钮,系统开始编译。 单击小型编译工具栏中的“Execute Program”按钮或按Ctrl+F5键,运行刚才的程序。 程序运行后,弹出下图的窗口:

     

    这就是控制台窗口,与传统的DOS屏幕窗口相比最主要的区别有:

    (1) 默认的控制台窗口有系统菜单和标题,它是一个内存缓冲区窗口,缓冲区大小取决于Windows操作系统的分配;而DOS屏幕是一种物理窗口,不具有Windows窗口特性,其大小取决于ROM BIOS分配的内存空间。

    (2) 控制台窗口的文本操作是调用低层的Win32 APIs,而DOS屏幕的文本操作是通过调用BIOS的16(10h)中断而实现的。

    (3) 默认的控制台窗口可以接收键盘和鼠标的输入信息,设备驱动由Windows管理,而DOS屏幕窗口接收鼠标时需要调用33h中断,且鼠标设备驱动程序由自己安装。


    (二)    控制台文本窗口的一般控制步骤

    在Visual C++ 6.0中,控制台窗口界面的一般编程控制步骤如下:调用GetStdHandle获取当前的标准输入(STDIN)和标准输出(STDOUT)设备句柄。函数原型为:

    HANDLE GetStdHandle( DWORD nStdHandle );

    其中,nStdHandle可以是STD_INPUT_HANDLE(标准输入设备句柄)、STD_OUTPUT_HANDLE(标准输出设备句柄)和 STD_ERROR_HANDLE(标准错误句柄)。

    需要说明的是,“句柄”是Windows最常用的概念。它通常用来标识Windows资源(如菜单、 图标、窗口等)和设备等对象。虽然可以把句柄理解为是一个指针变量类型,但它不是对象所在的地址指针,而是作为Windows系统内部表的索引值来使用 的。调用相关文本界面控制的API函数。这些函数可分为三类。一是用于控制台窗口操作的函数(包括窗口的缓冲区大小、窗口前景字符和背景颜色、窗口标题、大小和位置等);二是用于控制台输入输出的函数(包括字符属性操作函数);其他的函数并为最后一类。 调用CloseHandle()来关闭输入输出句柄。 注意,在程序中还必须包含头文件windows.h。下面看一个程序:

    #include <windows.h>

    #include <stdio.h>

    #include <conio.h>

    int main(void)

    {

           HANDLE hOut;

           CONSOLE_SCREEN_BUFFER_INFO bInfo; // 存储窗口信息

           COORD pos = {0, 0};

           // 获取标准输出设备句柄

           hOut = GetStdHandle(STD_OUTPUT_HANDLE);

           // 获取窗口信息

           GetConsoleScreenBufferInfo(hOut, &bInfo );

           printf("\n\nThe soul selects her own society\n");

           printf("Then shuts the door\n");

           printf("On her devine majority\n");

           printf("Obtrude no more\n\n");

           _getch();

           // 向窗口中填充字符以获得清屏的效果

           FillConsoleOutputCharacter(hOut,' ', bInfo.dwSize.X * bInfo.dwSize.Y, pos, NULL);

           // 关闭标准输出设备句柄

           CloseHandle(hOut);

           return 0;

    }

     

    程序中,COORD和CONSOLE_SCREEN_BUFFER_ INFO是wincon.h定义的控制台结构体类型,其原型如下:

    // 坐标结构体

    typedef struct _COORD {

    SHORT X;

    SHORT Y;

    } COORD;

    // 控制台窗口信息结构体

    typedef struct _CONSOLE_SCREEN_BUFFER_INFO {

    COORD dwSize; // 缓冲区大小

    COORD dwCursorPosition; // 当前光标位置

    WORD wAttributes; // 字符属性

    SMALL_RECT srWindow; // 当前窗口显示的大小和位置

    COORD dwMaximumWindowSize; // 最大的窗口缓冲区大小

    } CONSOLE_SCREEN_BUFFER_INFO ;

    还需要说明的是,虽然在C++中,iostream.h定义了cin和cout的标准输入和输出流对象。但它们只能实现基本的输入输出 操作,对于控制台窗口界面的控制却无能为力,而且不能与stdio.h和conio.h友好相处,因为iostream.h和它们是C++两套不同的输入 输出操作方式,使用时要特别注意。


    (三)   控制台窗口操作操作

    用于控制台窗口操作的API函数如下:

    GetConsoleScreenBufferInfo 获取控制台窗口信息

    GetConsoleTitle 获取控制台窗口标题

    ScrollConsoleScreenBuffer 在缓冲区中移动数据块

    SetConsoleScreenBufferSize 更改指定缓冲区大小

    SetConsoleTitle 设置控制台窗口标题

    SetConsoleWindowInfo 设置控制台窗口信息

    此外,还有窗口字体、显示模式等控制函数,这里不再细说。下列举一个示例,程序如下:

    #include <windows.h>

    #include <stdio.h>

    #include <conio.h>

    int main(void)

    {

           char strTitle[255];

           CONSOLE_SCREEN_BUFFER_INFO bInfo; // 窗口缓冲区信息

           COORD size = {80, 25};

           HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); // 获取标准输出设备句柄

           GetConsoleScreenBufferInfo(hOut, &bInfo ); // 获取窗口缓冲区信息

           GetConsoleTitle(strTitle, 255); // 获取窗口标题

           printf("当前窗口标题是:\n%s\n", strTitle);

           _getch();

           SetConsoleTitle("控制台窗口操作"); // 设置窗口标题

           GetConsoleTitle(strTitle, 255);

           printf("当前窗口标题是:\n%s\n", strTitle);

           _getch();

           SetConsoleScreenBufferSize(hOut,size); // 重新设置缓冲区大小

           _getch();

           SMALL_RECT rc = {0,0, 80-1, 25-1}; // 重置窗口位置和大小

           SetConsoleWindowInfo(hOut,true ,&rc);

           CloseHandle(hOut); // 关闭标准输出设备句柄

           return 0;

    }

    需要说明的是,控制台窗口的原点坐标是(0, 0),而最大的坐标是缓冲区大小减1,例如当缓冲区大小为80*25时,其最大的坐标是(79, 24)。


    (四) 文本属性操作操作

    与DOS字符相似,控制台窗口中的字符也有相应的属性。这些属性分为:文本的前景色、背景色和双字节字符集(DBCS)属性三种。事实上,我们最关心是文本颜色,这样可以构造出美观的界面。颜色属性都是一些预定义标识:

    FOREGROUND_BLUE 蓝色

    FOREGROUND_GREEN 绿色

    FOREGROUND_RED 红色

    FOREGROUND_INTENSITY 加强

    BACKGROUND_BLUE 蓝色背景

    BACKGROUND_GREEN 绿色背景

    BACKGROUND_RED 红色背景

    BACKGROUND_INTENSITY 背景色加强

    COMMON_LVB_REVERSE_VIDEO 反色

    与文本属性相关的主要函数有:

    BOOL FillConsoleOutputAttribute( // 填充字符属性

    HANDLE hConsoleOutput, // 句柄

    WORD wAttribute, // 文本属性

    DWORD nLength, // 个数

    COORD dwWriteCoord, // 开始位置

    LPDWORD lpNumberOfAttrsWritten // 返回填充的个数

    );

    BOOL SetConsoleTextAttribute( // 设置WriteConsole等函数的字符属性

    HANDLE hConsoleOutput, // 句柄

    WORD wAttributes // 文本属性

    );

    BOOL WriteConsoleOutputAttribute( // 在指定位置处写属性

    HANDLE hConsoleOutput, // 句柄

    CONST WORD *lpAttribute, // 属性

    DWORD nLength, // 个数

    COORD dwWriteCoord, // 起始位置

    LPDWORD lpNumberOfAttrsWritten // 已写个数

    );

    另外,获取当前控制台窗口的文本属性是通过调用函数GetConsoleScreenBufferInfo后,在CONSOLE_SCREEN_ BUFFER_INFO结构成员wAttributes中得到。


    (五) 文本输出

    操作文本输出函数有:

    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); // 已写个数

     

    可以看出:WriteConsoleOutput函数功能相当于SetConsoleTextAttribute和WriteConsole 的功能。而WriteConsoleOutputCharacter函数相当于SetConsoleCursorPosition(设置光标位置)和 WriteConsole的功能。不过在具体使用要注意它们的区别。


    (六) 文本操作示例操作

    下面看一个示例程序:

    // 在具有阴影效果的窗口中显示一行字符

    #include <windows.h>

    HANDLE hOut;

    void ShadowWindowLine(char *str);

    void DrawBox(bool bSingle, SMALL_RECT rc); // 绘制边框

    int main(void)

    {

           hOut = GetStdHandle(STD_OUTPUT_HANDLE); // 获取标准输出设备句柄

           SetConsoleOutputCP(437); // 设置代码页,这里如果设置成936(简体中文),那么程序会怎样?那样的话,将画不出边框。

           ShadowWindowLine("Display a line of words, and center the window with shadow.");

           CloseHandle(hOut); // 关闭标准输出设备句柄

           return 0;

    }

    void ShadowWindowLine(char *str)

    {

           SMALL_RECT rc;

           CONSOLE_SCREEN_BUFFER_INFO bInfo; // 窗口缓冲区信息

           WORD att0,att1,attText;

           int i, chNum = strlen(str);

           GetConsoleScreenBufferInfo( hOut, &bInfo ); // 获取窗口缓冲区信息

           // 计算显示窗口大小和位置

           rc.Left = (bInfo.dwSize.X - chNum)/2 - 2;

           rc.Top = 8; // 原代码段中此处为bInfo.dwSize.Y/2 - 2,但是如果您的DOS屏幕有垂直滚动条的话,还需要把滚动条下拉才能看到,为了方便就把它改为10

           rc.Right = rc.Left + chNum + 4;

           rc.Bottom = rc.Top + 4;

           att0 = BACKGROUND_INTENSITY; // 阴影属性

           att1 = FOREGROUND_RED |FOREGROUND_GREEN |FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE;// 文本属性

           attText = FOREGROUND_RED |FOREGROUND_INTENSITY; // 文本属性

           // 设置阴影然后填充

           COORD posShadow = {rc.Left+1, rc.Top+1}, posText = {rc.Left, rc.Top};

           for (i=0; i<5; i++)

           {

                  FillConsoleOutputAttribute(hOut, att0, chNum + 4, posShadow, NULL);

                  posShadow.Y++;

           }

           for (i=0;i<5;i++)

           {

                  FillConsoleOutputAttribute(hOut, att1,chNum + 4, posText, NULL);

                  posText.Y++;

           }

           // 写文本和边框

           posText.X = rc.Left + 2;

           posText.Y = rc.Top + 2;

           WriteConsoleOutputCharacter(hOut, str, strlen(str), posText, NULL);

           DrawBox(true, rc);

           SetConsoleTextAttribute(hOut, bInfo.wAttributes); // 恢复原来的属性

    }

    void DrawBox(bool bSingle, SMALL_RECT rc) // 函数功能:画边框

    {

           char chBox[6];

           COORD pos;

           if (bSingle)

           {

                  chBox[0] = (char)0xda; // 左上角点

                  chBox[1] = (char)0xbf; // 右上角点

                  chBox[2] = (char)0xc0; // 左下角点

                  chBox[3] = (char)0xd9; // 右下角点

                  chBox[4] = (char)0xc4; // 水平

                  chBox[5] = (char)0xb3; // 坚直

           } else {

                  chBox[0] = (char)0xc9; // 左上角点

                  chBox[1] = (char)0xbb; // 右上角点

                  chBox[2] = (char)0xc8; // 左下角点

                  chBox[3] = (char)0xbc; // 右下角点

                  chBox[4] = (char)0xcd; // 水平

                  chBox[5] = (char)0xba; // 坚直

           }

           // 画边框的上 下边界

           for(pos.X = rc.Left+1;pos.X<rc.Right-1;pos.X++)

           {    

                  pos.Y = rc.Top;

                  // 画上边界

                  WriteConsoleOutputCharacter(hOut, &chBox[4], 1, pos, NULL);

                  // 画左上角

                  if(pos.X == rc.Left+1)

                  {

                         pos.X--;

                         WriteConsoleOutputCharacter(hOut, &chBox[0],1, pos, NULL);

                         pos.X++;

                  }

                  // 画右上角

                  if(pos.X == rc.Right-2)

                  {

                         pos.X++;

                         WriteConsoleOutputCharacter(hOut, &chBox[1], 1, pos, NULL);

                         pos.X--;

                  }

                  pos.Y = rc.Bottom;

                  // 画下边界

                  WriteConsoleOutputCharacter(hOut, &chBox[4], 1, pos, NULL);

                  // 画左下角

                  if(pos.X == rc.Left+1)

                  {

                         pos.X--;

                         WriteConsoleOutputCharacter(hOut, &chBox[2], 1, pos, NULL);

                         pos.X++;

                  }

                  // 画右下角

                  if(pos.X==rc.Right-2)

                  {

                         pos.X++;

                         WriteConsoleOutputCharacter(hOut, &chBox[3], 1, pos, NULL);

                         pos.X--;

                  }

           }

           // 画边框的左右边界

           for (pos.Y = rc.Top+1; pos.Y<=rc.Bottom-1; pos.Y++)

           {

                  pos.X = rc.Left;

                  // 画左边界

                  WriteConsoleOutputCharacter(hOut, &chBox[5], 1, pos, NULL);

                  pos.X = rc.Right-1;

                  // 画右边界

                  WriteConsoleOutputCharacter(hOut, &chBox[5], 1, pos, NULL);

           }

    }

    程序运行结果如下图所示:

     

    需要说明的是:

    ①在上述例子中,如果调用DrawBox函数时,传递的第一个参数不是true而是false,那么画出来的边框将是双线的。运行结果如下:

     

    ②如果在上述程序无法编译通过,您可以这样修改,即程序中调用WriteConsoleOutputCharacter和FillConsoleOutputAttribute函数的时候,最后一个参数不用NULL,而是先定义一个变量:

    DWORD written;

    然后把 &written作为最后一个参数。

    ③上述程序在不同的字符代码页面(code page)下显示的结果是不同的。例如,中文Windows操作系统的默认代码页是简体中文(936),在该代码页面下值超过128的单字符在Windows NT/XP是显示不出来的。下表列出了可以使用的代码页。

    代码页(Code page)   说明

    1258       越南文

    1257       波罗的海文

    1256       阿拉伯文

    1255       希伯来文

    1254       土耳其语

    1253       希腊文

    1252       拉丁文(ANSI)

    1251       斯拉夫文

    1250       中欧文

    950  繁体中文

    949  韩文

    936  简体中文

    932  日文

    874  泰文

    850  使用多种语言(MS-DOS拉丁文)

    437  MS-DOS美语/英语

     

    (七) 滚动和移动操作

    ScrollConsoleScreenBuffer是实现文本区滚动和移动的API函数。它可以将指定的一块文本区域移动到另一个区域,被移空的那块区域由指定字符填充。函数的原型如下:

    BOOL ScrollConsoleScreenBuffer(

    HANDLE hConsoleOutput, // 句柄

    CONST SMALL_RECT* lpScrollRectangle, // 要滚动或移动的区域

    CONST SMALL_RECT* lpClipRectangle, // 裁剪区域

    COORD dwDestinationOrigin, // 新的位置

    CONST CHAR_INFO* lpFill // 填充字符

    );

    利用这个API函数还可以实现删除指定行的操作。下面来举一个例子,程序如下:

    #include <windows.h>

    #include <stdio.h>

    #include <conio.h>

    HANDLE hOut;

    void DeleteLine(int row); // 删除一行

    void MoveText(int x, int y, SMALL_RECT rc); // 移动文本块区域

    void ClearScreen(void); // 清屏

    int main(void)

    {

           hOut = GetStdHandle(STD_OUTPUT_HANDLE); // 获取标准输出设备句柄

           WORD att = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_BLUE;// 背景是蓝色,文本颜色是黄色

           SetConsoleTextAttribute(hOut, att);

           ClearScreen();

           printf("\n\nThe soul selects her own society\n");

           printf("Then shuts the door;\n");

           printf("On her devine majority;\n");

           printf("Obtrude no more.\n\n");

           COORD endPos = {0, 15};

           SetConsoleCursorPosition(hOut, endPos); // 设置光标位置

           SMALL_RECT rc = {0, 2, 40, 5};

           _getch();

           MoveText(10, 5, rc);

           _getch();

           DeleteLine(5);

           CloseHandle(hOut); // 关闭标准输出设备句柄

           return 0;

    }

    void DeleteLine(int row)

    {

           SMALL_RECT rcScroll, rcClip;

           COORD crDest = {0, row - 1};

           CHAR_INFO chFill;

           CONSOLE_SCREEN_BUFFER_INFO bInfo;

           GetConsoleScreenBufferInfo( hOut, &bInfo );

           rcScroll.Left = 0;

           rcScroll.Top = row;

           rcScroll.Right = bInfo.dwSize.X - 1;

           rcScroll.Bottom = bInfo.dwSize.Y - 1;

           rcClip = rcScroll;

           chFill.Attributes = bInfo.wAttributes;

           chFill.Char.AsciiChar = ' ';

           ScrollConsoleScreenBuffer(hOut, &rcScroll, &rcClip, crDest, &chFill);

    }

    void MoveText(int x, int y, SMALL_RECT rc)

    {

           COORD crDest = {x, y};

           CHAR_INFO chFill;

           CONSOLE_SCREEN_BUFFER_INFO bInfo;

           GetConsoleScreenBufferInfo( hOut, &bInfo );

           chFill.Attributes = bInfo.wAttributes;

           chFill.Char.AsciiChar = ' ';

           ScrollConsoleScreenBuffer(hOut, &rc, NULL, crDest, &chFill);

    }

    void ClearScreen(void)

    {

           CONSOLE_SCREEN_BUFFER_INFO bInfo;

           GetConsoleScreenBufferInfo( hOut, &bInfo );

           COORD home = {0, 0};

           WORD att = bInfo.wAttributes;

           unsigned long size = bInfo.dwSize.X * bInfo.dwSize.Y;

           FillConsoleOutputAttribute(hOut, att, size, home, NULL);

           FillConsoleOutputCharacter(hOut, ' ', size, home, NULL);

    }

    程序中,实现删除行的操作DeleteLine的基本原理是:首先将裁剪区域和移动区域都设置成指定行row(包括该行)以下的控制台窗口区域,然后将移动的位置指定为(0, row-1)。这样,超出裁剪区域的内容被裁剪掉,从而达到删除行的目的。

    需要说明的是,若裁剪区域参数为NULL,则裁剪区域为整个控制台窗口。


    (八) 光标操作操作

    控制台窗口中的光标反映了文本插入的当前位置,通过SetConsoleCursorPosition函数可以改变这个“当前”位置,这样就能控制字符(串)输出。事实上,光标本身的大小和显示或隐藏也可以通过相应的API函数进行设定。例如:

    BOOL SetConsoleCursorInfo( // 设置光标信息

    HANDLE hConsoleOutput, // 句柄

    CONST CONSOLE_CURSOR_INFO *lpConsoleCursorInfo // 光标信息

    );

    BOOL GetConsoleCursorInfo( // 获取光标信息

    HANDLE hConsoleOutput, // 句柄

    PCONSOLE_CURSOR_INFO lpConsoleCursorInfo // 返回光标信息

    );

    这两个函数都与CONSOLE_CURSOR_INFO结构体类型有关,其定义如下:

    typedef struct _CONSOLE_CURSOR_INFO {

    DWORD dwSize; // 光标百分比大小

    BOOL bVisible; // 是否可见

    } CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;

    需要说明的是,dwSize值反映了光标的大小,它的值范围为1-100;当为1时,光标最小,仅是一条最靠下的水平细线,当为100,光标最大,为一个字符大小的方块。

    (九) 读取键盘信息操作

      键盘事件通常有字符事件和按键事件,这些事件所附带的信息构成了键盘信息。它是通过API函数ReadConsoleInput来获取的,其原型如下:

    BOOL ReadConsoleInput(

    HANDLE hConsoleInput, // 输入设备句柄

    PINPUT_RECORD lpBuffer, // 返回数据记录

    DWORD nLength, // 要读取的记录数

    LPDWORD lpNumberOfEventsRead // 返回已读取的记录数

    );

    其中,INPUT_RECORD定义如下:

    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;

    与键盘事件相关的记录结构KEY_EVENT_RECORD定义如下:

    typedef struct _KEY_EVENT_RECORD {

    BOOL bKeyDown; // TRUE表示键按下,FALSE表示键释放

    WORD wRepeatCount; // 按键次数

    WORD wVirtualKeyCode; // 虚拟键代码

    WORD wVirtualScanCode; // 虚拟键扫描码

    union {

    WCHAR UnicodeChar; // 宽字符

    CHAR AsciiChar; // ASCII字符

    } uChar; // 字符

    DWORD dwControlKeyState; // 控制键状态

    } KEY_EVENT_RECORD;

    我们知道,键盘上每一个有意义的键都对应着一个唯一的扫描码,虽然扫描码可以作为键的标识,但它依赖于具体设备的。因此,在应用程序中,使用的往往是与具体设备无关的虚拟键代码。这种虚拟键代码是与设备无关的键盘编码。在Visual C++中,最常用的虚拟键代码已被定义在Winuser.h中,例如:VK_SHIFT表示SHIFT键,VK_F1表示功能键F1等。上述结构定义中,dwControlKeyState用来表示控制键状态,它可以是CAPSLOCK_ON(CAPS LOCK灯亮)、ENHANCED_KEY(按下扩展键)、LEFT_ALT_PRESSED(按下左ALT键)、 LEFT_CTRL_PRESSED(按下左CTRL键)、NUMLOCK_ON (NUM LOCK灯亮)、RIGHT_ALT_PRESSED(按下右ALT键)、RIGHT_CTRL_PRESSED(按下右CTRL键)、 SCROLLLOCK_ON(SCROLL LOCK灯亮)和SHIFT_PRESSED(按下SHIFT键)中的一个或多个值的组合。下面的程序是将用户按键的字符输入到一个控制台窗口的某个区域中,并当按下NUM LOCK、CAPS LOCK和SCROLL LOCK键时,在控制台窗口的最后一行显示这些键的状态。

    #include <windows.h>

    HANDLE hOut;

    HANDLE hIn;

    void DrawBox(bool bSingle, SMALL_RECT rc); // 这个自定义函数在第六章用过

    void ClearScreen(void);

    void CharWindow(char ch, SMALL_RECT rc); // 将ch输入到指定的窗口中

    void ControlStatus(DWORD state); // 在最后一行显示控制键的状态

    void DeleteTopLine(SMALL_RECT rc); // 删除指定窗口中最上面的行并滚动

    int main(void)

    {

           hOut = GetStdHandle(STD_OUTPUT_HANDLE); // 获取标准输出设备句柄

           hIn = GetStdHandle(STD_INPUT_HANDLE); // 获取标准输入设备句柄

           WORD att = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_BLUE ; // 背景是蓝色,文本颜色是黄色

           SetConsoleTextAttribute(hOut, att);

           ClearScreen(); // 清屏

           INPUT_RECORD keyRec;

           DWORD state = 0, res;

           char ch;

           SMALL_RECT rc = {20, 2, 40, 12};

           DrawBox(false, rc);

           COORD pos = {rc.Left+1, rc.Top+1};

           SetConsoleCursorPosition(hOut, pos); // 设置光标位置

           for(;;) // 循环

           {

                  ReadConsoleInput(hIn, &keyRec, 1, &res);

                  if (state != keyRec.Event.KeyEvent.dwControlKeyState)

                  {

                         state = keyRec.Event.KeyEvent.dwControlKeyState;

                         ControlStatus(state);

                  }

                  if (keyRec.EventType == KEY_EVENT)

                  {

                         if (keyRec.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)

                                break;

                         // 按ESC键退出循环

                         if (keyRec.Event.KeyEvent.bKeyDown)

                         {

                                ch = keyRec.Event.KeyEvent.uChar.AsciiChar;

                                CharWindow(ch, rc);

                         }

                  }

           }

           pos.X = 0; pos.Y = 0;

           SetConsoleCursorPosition(hOut, pos); // 设置光标位置

           CloseHandle(hOut); // 关闭标准输出设备句柄

           CloseHandle(hIn); // 关闭标准输入设备句柄

           return 0;

    }

     

    void CharWindow(char ch, SMALL_RECT rc) // 将ch输入到指定的窗口中

    {

           static COORD chPos = {rc.Left+1, rc.Top+1};

           SetConsoleCursorPosition(hOut, chPos); // 设置光标位置

           if ((ch<0x20)||(ch>0x7e)) // 如果是不可打印的字符,具体查看ASCII码表

                  return;

           WriteConsoleOutputCharacter(hOut, &ch, 1, chPos, NULL);

           if (chPos.X >= (rc.Right-2))

           {

                  chPos.X = rc.Left;

                  chPos.Y++;

           }

           if (chPos.Y>(rc.Bottom-1))

           {

                  DeleteTopLine(rc);

                  chPos.Y = rc.Bottom-1;

           }

           chPos.X++;

           SetConsoleCursorPosition(hOut, chPos); // 设置光标位置

    }

     

    void ControlStatus(DWORD state) // 在第一行显示控制键的状态

    {

           CONSOLE_SCREEN_BUFFER_INFO bInfo;

           GetConsoleScreenBufferInfo( hOut, &bInfo );

           COORD home = {0, 24}; // 原来此处为bInfo.dwSize.Y-1,但为了更便于观察,我把这里稍微修改了一下

           WORD att0 = BACKGROUND_INTENSITY ;

           WORD att1 = FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_RED;

           FillConsoleOutputAttribute(hOut, att0, bInfo.dwSize.X, home, NULL);

           FillConsoleOutputCharacter(hOut, ' ', bInfo.dwSize.X, home, NULL);

           SetConsoleTextAttribute(hOut, att1);

           COORD staPos = {bInfo.dwSize.X-16,24}; // 原来此处为bInfo.dwSize.Y-1

           SetConsoleCursorPosition(hOut, staPos);

           if (state & NUMLOCK_ON)

                  WriteConsole(hOut, "NUM", 3, NULL, NULL);

           staPos.X += 4;

           SetConsoleCursorPosition(hOut, staPos);

           if (state & CAPSLOCK_ON)

                  WriteConsole(hOut, "CAPS", 4, NULL, NULL);

           staPos.X += 5;

           SetConsoleCursorPosition(hOut, staPos);

           if (state & SCROLLLOCK_ON)

                  WriteConsole(hOut, "SCROLL", 6, NULL, NULL);

           SetConsoleTextAttribute(hOut, bInfo.wAttributes); // 恢复原来的属性

           SetConsoleCursorPosition(hOut, bInfo.dwCursorPosition); // 恢复原来的光标位置

    }

    void DeleteTopLine(SMALL_RECT rc)

    {

           COORD crDest;

           CHAR_INFO chFill;

           SMALL_RECT rcClip = rc;

           rcClip.Left++;

           rcClip.Right -= 2;

           rcClip.Top++;

           rcClip.Bottom--;

           crDest.X = rcClip.Left;

           crDest.Y = rcClip.Top - 1;

           CONSOLE_SCREEN_BUFFER_INFO bInfo;

           GetConsoleScreenBufferInfo( hOut, &bInfo );

           chFill.Attributes = bInfo.wAttributes;

           chFill.Char.AsciiChar = ' ';

           ScrollConsoleScreenBuffer(hOut, &rcClip, &rcClip, crDest, &chFill);

    }

    void ClearScreen(void)

    {

           CONSOLE_SCREEN_BUFFER_INFO bInfo;

           GetConsoleScreenBufferInfo( hOut, &bInfo );

           COORD home = {0, 0};

           WORD att = bInfo.wAttributes;

           unsigned long size = bInfo.dwSize.X * bInfo.dwSize.Y;

           FillConsoleOutputAttribute(hOut, att, size, home, NULL);

           FillConsoleOutputCharacter(hOut, ' ', size, home, NULL);

    }

    // 函数功能:画边框

    void DrawBox(bool bSingle, SMALL_RECT rc)

    {

           char chBox[6];

           COORD pos;

           if (bSingle)

           {

                  chBox[0] = (char)0xda; // 左上角点

                  chBox[1] = (char)0xbf; // 右上角点

                  chBox[2] = (char)0xc0; // 左下角点

                  chBox[3] = (char)0xd9; // 右下角点

                  chBox[4] = (char)0xc4; // 水平

                  chBox[5] = (char)0xb3; // 坚直

           }

           else

           {

                  chBox[0] = (char)0xc9; // 左上角点

                  chBox[1] = (char)0xbb; // 右上角点

                  chBox[2] = (char)0xc8; // 左下角点

                  chBox[3] = (char)0xbc; // 右下角点

                  chBox[4] = (char)0xcd; // 水平

                  chBox[5] = (char)0xba; // 坚直

           }

           // 画边框的上 下边界

           for(pos.X = rc.Left+1;pos.X<rc.Right-1;pos.X++)

           {    

                  pos.Y = rc.Top;

                  // 画上边界

                  WriteConsoleOutputCharacter(hOut, &chBox[4], 1, pos, NULL);

                  // 画左上角

                  if(pos.X == rc.Left+1)

                  {

                         pos.X--;

                         WriteConsoleOutputCharacter(hOut, &chBox[0],1, pos, NULL);

                         pos.X++;

                  }

                  // 画右上角

                  if(pos.X == rc.Right-2)

                  {

                         pos.X++;

                         WriteConsoleOutputCharacter(hOut, &chBox[1], 1, pos, NULL);

                         pos.X--;

                  }

                  pos.Y = rc.Bottom;

                  // 画下边界

                  WriteConsoleOutputCharacter(hOut, &chBox[4], 1, pos, NULL);

                  // 画左下角

                  if(pos.X == rc.Left+1)

                  {

                         pos.X--;

                         WriteConsoleOutputCharacter(hOut, &chBox[2], 1, pos, NULL);

                         pos.X++;

                  }

                  // 画右下角

                  if(pos.X==rc.Right-2)

                  {

                         pos.X++;

                         WriteConsoleOutputCharacter(hOut, &chBox[3], 1, pos, NULL);

                         pos.X--;

                  }

     

           }

           // 画边框的左右边界

           for (pos.Y = rc.Top+1; pos.Y<=rc.Bottom-1; pos.Y++)

           {

                  pos.X = rc.Left;

                  // 画左边界

                  WriteConsoleOutputCharacter(hOut, &chBox[5], 1, pos, NULL);

                  pos.X = rc.Right-1;

                  // 画右边界

                  WriteConsoleOutputCharacter(hOut, &chBox[5], 1, pos, NULL);

           }

    }

    当你输入画面中句子时,运行结果如下图:

     


    (十) 读取鼠标信息操作

    与读取键盘信息方法相似,鼠标信息也是通过ReadConsoleInput来获取的,其MOUSE_EVENT_RECORD具有下列定义:

    typedef struct _MOUSE_EVENT_RECORD {

    COORD dwMousePosition; // 当前鼠标位置

    DWORD dwButtonState; // 鼠标按钮状态

    DWORD dwControlKeyState; // 键盘控制键状态

    DWORD dwEventFlags; // 事件状态

    } MOUSE_EVENT_RECORD;

    其中,dwButtonState反映了用户按下鼠标按钮的情况,它可以是:

    FROM_LEFT_1ST_BUTTON_PRESSED(最 左边按钮)、RIGHTMOST_BUTTON_PRESSED(最右边按钮)、FROM_LEFT_2ND_BUTTON_PRESSED(左起第二个 按钮)、FROM_LEFT_3RD_BUTTON_PRESSED(左起第三个按钮)和FROM_LEFT_4TH_BUTTON_PRESSED (左起第四个按钮)。而dwEventFlags表示鼠标 的事件,如DOUBLE_CLICK(双击)、MOUSE_MOVED(移动)和 MOUSE_WHEELED(滚轮滚动,只适用于Windows 2000/XP)。dwControlKeyState的含义同前。

    下面举一个例子。这个例子能把鼠标的当前位置显示在控制台窗口的最后一行上,若单击鼠标左键,则在当前位置处写一个字符‘A’,若双击鼠标任一按钮,则程序终止。具体代码如下:

    #include <windows.h>

    #include <stdio.h>

    #include <string.h>

    HANDLE hOut;

    HANDLE hIn;

    void ClearScreen(void);

    void DispMousePos(COORD pos); // 在第24行显示鼠标位置

    int main()

    {

           hOut = GetStdHandle(STD_OUTPUT_HANDLE); // 获取标准输出设备句柄

           hIn = GetStdHandle(STD_INPUT_HANDLE); // 获取标准输入设备句柄

           WORD att = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_BLUE ;

           // 背景是蓝色,文本颜色是黄色

           SetConsoleTextAttribute(hOut, att);

           ClearScreen(); // 清屏

           INPUT_RECORD mouseRec;

           DWORD state = 0, res;

           COORD pos = {0, 0};

           for(;;) // 循环

           {

                  ReadConsoleInput(hIn, &mouseRec, 1, &res);

                  if (mouseRec.EventType == MOUSE_EVENT)

                  {

                         if (mouseRec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)

                                break; // 双击鼠标退出循环       

                         pos = mouseRec.Event.MouseEvent.dwMousePosition;

                         DispMousePos(pos);

                         if (mouseRec.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)

                                FillConsoleOutputCharacter(hOut, 'A', 1, pos, NULL);

                  }

           }

           pos.X = pos.Y = 0;

           SetConsoleCursorPosition(hOut, pos); // 设置光标位置

           CloseHandle(hOut); // 关闭标准输出设备句柄

           CloseHandle(hIn); // 关闭标准输入设备句柄

    }

    void DispMousePos(COORD pos) // 在第24行显示鼠标位置

    {

           CONSOLE_SCREEN_BUFFER_INFO bInfo;

           GetConsoleScreenBufferInfo( hOut, &bInfo );

           COORD home = {0, 24};

           WORD att0 = BACKGROUND_INTENSITY ;

           FillConsoleOutputAttribute(hOut, att0, bInfo.dwSize.X, home, NULL);

           FillConsoleOutputCharacter(hOut, ' ', bInfo.dwSize.X, home, NULL);

           char s[20];

           sprintf(s,"X = %2lu, Y = %2lu",pos.X, pos.Y);

           SetConsoleTextAttribute(hOut, att0);

           SetConsoleCursorPosition(hOut, home);

           WriteConsole(hOut, s, strlen(s), NULL, NULL);

           SetConsoleTextAttribute(hOut, bInfo.wAttributes); // 恢复原来的属性

           SetConsoleCursorPosition(hOut, bInfo.dwCursorPosition); // 恢复原来的光标位置

    }

    void ClearScreen(void)

    {

           CONSOLE_SCREEN_BUFFER_INFO bInfo;

           GetConsoleScreenBufferInfo( hOut, &bInfo );

           COORD home = {0, 0};

           unsigned long size = bInfo.dwSize.X * bInfo.dwSize.Y;

           FillConsoleOutputAttribute(hOut, bInfo.wAttributes, size, home, NULL);

           FillConsoleOutputCharacter(hOut, ' ', size, home, NULL);

    }

    如果你尝试在屏幕上写一个“Hello!”,将看到如下运行结果:

     


    (十一) 结语

    综上所述,利用控制台窗口的Widows API函数可以设计简洁美观的文本界面,使得用Visual C++ 6.0开发环境深入学习C++以及文本界面设计成为一件比较容易的事件。当然文本界面的设计还需要一定的方法和技巧,限于篇幅,这里不再阐述。

    补充篇--经典控制台程序

    下面是我在网上找到的几个经典代码,供大家学习!

    ①    输出各种彩带。来源:百度文库《在控制台窗口中输出彩带(含倾斜彩带)》

    源代码:

    #include <windows.h>

    #include <stdio.h>

    void shuiping();

    void chuizhi();

    void zuoqingxie();

    void youqingxie();

    void jiantou();

    void SetColor(unsigned short ForeColor,unsigned short BackGroundColor);

    int main()

    {

           int a;

           SMALL_RECT rc = {0,0,20,10};

           HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

           SetConsoleOutputCP(936);

           SetColor(14,3);

           printf("0:水平彩带,\n1:垂直彩带,\n2:右倾斜彩带,\n3:左倾斜彩带,\n4:箭头状彩带,\n5:水纹状彩带,\n其他输入退出\n");

           scanf("%d",&a);

           while(a==0||a==1||a==2||a==3||a==4||a==5)

           {

                  if(a==0)//实现水平彩带输出

                  {

                         shuiping();

                         SetColor(14,3); //刷新缓冲区,使字迹可见

                  }    

                  else if(a==1)//实现垂直彩带输出

                  {

                         chuizhi();

                         SetColor(14,3);

                  }

                  else if(a==2)//实现右倾斜彩带输出

                  {

                         youqingxie();

                         SetColor(14,3);

                  }

                  else if(a==3)//实现左倾斜彩带输出

                  {

                         zuoqingxie();

                         SetColor(14,3);

                  }

                  else if(a==4)//实现箭头状彩带输出

                  {

                         jiantou();

                         SetColor(14,3);

                  }

                  else if(a==5)//实现水纹状彩带输出

                  {

                         jiantou();

                         jiantou();

                         SetColor(14,3);

                  }

                  fflush(stdin);

                  printf("0:水平彩带,\n1:垂直彩带,\n2:右倾斜彩带,\n3:左倾斜彩带,\n4:箭头状彩带,\n5:水纹状彩带,\n其他输入退出\n");

                  scanf("%d",&a);

           }

           return 0;

          

    }

    void SetColor(unsigned short ForeColor,unsigned short BackGroundColor)

    {

           HANDLE hCon=GetStdHandle(STD_OUTPUT_HANDLE);

           SetConsoleTextAttribute(hCon,ForeColor+BackGroundColor*0x10);

    }

    //水平彩带函数

    void shuiping()

    {

           int i,j,k;

           for(i=0;i<25;++i)

           {

                  for(j=0;j<=79;++j)

                  {

                         k=i%16;

                         SetColor(k,k);

                         putchar('A');

                  }

           }

    }

     

    //垂直彩带函数

    void chuizhi()

    {

           int i,j,k;

           for(i=0;i<25;++i)

           {

                  for(j=0;j<40;++j)

                  {

                         k=j%16;

                         SetColor(k,k);

                         putchar('A');

                         putchar('A');

            }

                 

           }

    }

     

    //右倾斜彩带函数

    void youqingxie()

    {

           int i,j,k;

           for(i=0;i<25;++i)

           {

                  for(j=0;j<40;++j)

                  {

                         if(j-i>=0)

                                k=(j-i)%16;

                         else

                                k=(j-i)%16+16;

                         SetColor(k,k);

                         putchar('A');

                         putchar('A');

                  }

           }

    }

     

    //左倾斜彩带函数

    void zuoqingxie()

    {

           int i,j,k;

           for(i=0;i<25;++i)

           {

                  for(j=0;j<40;++j)

                  {

                         k=(i+j)%16;

                         SetColor(k,k);

                         putchar('A');

                         putchar('A');

                  }

           }

    }

    //箭头状彩带函数

    void jiantou()

    {

           int i,j,k;

           for(i=0;i<16;++i)

           {

                  for(j=0;j<40;++j)

                  {

                         k=(i+j)%16;

                         SetColor(k,k);

                         putchar('A');

                         putchar('A');

                  }

           }

           for(i=0;i<16;++i)

           {

                  for(j=0;j<40;++j)

                  {

                         if(j-i>=0)

                                k=(j-i)%16;

                         else

                                k=(j-i)%16+16;

                         SetColor(k,k);

                         putchar('A');

                         putchar('A');

                  }

           }

    }

    运行结果展示:

    水平彩带

          竖直彩带

    左倾斜彩带

          右倾斜彩带

    箭头状彩带

          水波状彩带

     


    ②输出颜色方阵

    出处: 百度知道《在控制台窗口中输出颜色方阵》

    作者:AlphaBlend

    #include <windows.h>

    #include <stdio.h>

    #include <conio.h>

     

    #define getrandom( min, max ) ((rand() % (int)(((max)+1) - (min))) + (min))

     

    void Init(void);

    void gotoxy(int x, int y);

    void regularcolor(void);

    void randomcolor(void);

    void Cls(HANDLE hConsole);

     

    HANDLE hOut;

    int forecolor[16];

    int backcolor[16];

     

    int main(void)

    {

           int i;

           int a;

          

           for (i = 0; i < 16; i++)

           {

                  forecolor[i] = i;

                  backcolor[i] = i << 4;

           }

           hOut = GetStdHandle(STD_OUTPUT_HANDLE);

          

           Init();

           while(1)

           {

                  a = getch();

                  if (a == 48)

                  {

                         Cls(hOut);

                         regularcolor();

                         getch();

                  } else if (a == 49) {

                         Cls(hOut);

                         randomcolor();

                         getch();

                  }  else {

                         Cls(hOut);

                         break;

                  }

                  Cls(hOut);

                  Init();

           }

          

          

           CloseHandle(hOut);

           return 0;

    }

    //---------------------------------------------------------------------------

     

    void gotoxy(int x, int y)

    {

           COORD pos = {x, y};

           SetConsoleCursorPosition(hOut, pos);

    }

     

    void regularcolor(void)

    {

           int i, j, x, y;

           int l = 8, t = 5;

           for (y = 0; y < 16; y++)

           {

                  gotoxy(l - 3, y + t);

                  SetConsoleTextAttribute(hOut, forecolor[15]|backcolor[0]);

                  printf("%d", y);

                  for (x = 0; x < 16; x++)

                  {

                         gotoxy(x * 4 + l, y + t);

                         SetConsoleTextAttribute(hOut, forecolor[y]|backcolor[x]);

                         printf("ZZZ");

                         if (y == 15)

                         {

                                gotoxy(x * 4 + l, 17 + t);

                                SetConsoleTextAttribute(hOut, forecolor[15]|backcolor[0]);

                                printf("%d", x);

                         }

                  }

           }

    }

     

    void randomcolor(void)

    {

           int i, j, x, y;

           int l = 8, t = 5;

           char s[4] = {"012"};

           rand();

           for (y = 0; y < 16; y++)

           {

                  for (x = 0; x < 16; x++)

                  {

                         s[0] = getrandom(32, 127);

                         s[1] = getrandom(32, 127);

                         s[2] = getrandom(32, 127);

                         gotoxy(x * 4 + l, y + t);

                         SetConsoleTextAttribute(hOut, forecolor[getrandom(0, 15)]|backcolor[getrandom(0, 15)]);

                         printf("%c", s[0]);

                         gotoxy(x * 4 + l + 1, y + t);

                         SetConsoleTextAttribute(hOut, forecolor[getrandom(0, 15)]|backcolor[getrandom(0, 15)]);

                         printf("%c", s[1]);

                         gotoxy(x * 4 + l + 2, y + t);

                         SetConsoleTextAttribute(hOut, forecolor[getrandom(0, 15)]|backcolor[getrandom(0, 15)]);

                         printf("%c", s[2]);

                  }

           }

    }

     

    void Cls(HANDLE hConsole)

    {

           COORD coordScreen = {0, 0};

          

           BOOL   bSuccess;

           DWORD  cCharsWritten;

           CONSOLE_SCREEN_BUFFER_INFO csbi;

           DWORD  dwConSize;

          

           SetConsoleTextAttribute(hOut, 0x0f|0);

           bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi);

           dwConSize = csbi.dwSize.X * csbi.dwSize.Y;

          

           bSuccess = FillConsoleOutputCharacter(hConsole, (TCHAR) '   ', dwConSize, coordScreen, &cCharsWritten);

           bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi);

           bSuccess = FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);

           bSuccess = SetConsoleCursorPosition(hConsole, coordScreen);

    }

     

    void Init(void)

    {

           gotoxy(30, 10);

           printf("0. Regular Color Array");

           gotoxy(30, 11);

           printf("1. Random Color Array");

           gotoxy(30, 12);

           printf("2. Quit");

    }

    展开全文
  • 认识控制台-什么是控制台

    千次阅读 2006-04-29 21:43:00
    控制台管理字符模式程序的输入和输出(程序不需要提供他们自己的图形用户界面)。 控制台函数使访问不同级别的控制台成为可能。高级控制台 I/O 函数使程序可以从标准输入来重新得到存储在控制台输入缓冲区中的键盘...

    控制台管理字符模式程序的输入和输出(程序不需要提供他们自己的图形用户界面)。

    控制台函数使访问不同级别的控制台成为可能。高级控制台 I/O 函数使程序可以从标准输入来重新得到存储在控制台输入缓冲区中的键盘输入;这些函数也能够是程序可以向标准输出写或将错误显示在标准的控制台缓冲区中。高级别的控制台函数也支持重定向标准的句柄和不同 I/O 功能的控制台模式。低级别的 I/O 函数能够使程序接收详细的键盘输入和鼠标事件,以及控制台窗口和用户交互的事件。低级函数也是输出到屏幕较大的控制。
    控制台对简单字符模式程序提供高级的支持,其通过读写标准输入和输出以及标准错误函数来和用户交互。控制台也提供复杂低级支持,例如:直接访问控制台屏幕缓冲区以及接收额外输入信息(例如鼠标输入)。

    什么是控制台?

    控制台是一个用来提供字符模式 I/O 的接口。这种处理器独立的机制使导入一个存在的字符模式程序或创建一个新的字符模式工具和程序变的容易。

    控制由输入缓冲区和一到多哥屏幕缓冲区组成。输入缓冲区包含一个输入记录的序列,序列中是输入事件的信息。输入队列也包含键按下和松开键事件。它也能包括鼠标事件(指针移动和鼠标键按下或释放)以及用来影响活动屏幕区域大小的用户动作。屏幕缓冲区是一个控制台窗口的二维的字符数组和彩色数据。所有的处理能共享一个控制台。

    系统在启动一个控制台程序的时候创建一个控制台,控制台程序是一个字符模式的程序,入口是 main 函数。例如,系统在其他命令处理器是会创建一个新的控制台。当命令处理器开始一个新的控制台程序时,用户能指定系统是否为新的程序创建一个新的控制台还是从命令处理器控制台继承。

    一个程序可以使用下面的方法来创建一个控制台:

    1.  GUI 或控制台程序可以使用 CreateProcess 函数并带有 CREATE_NEW_CONSOLE 来创建一个带有新控制台的控制台程序。(默认的,控制台程序从它的父控制台中继承并且不能保证输出可以被程序接收)

    2.  GUI 或控制台进程没有附着到一个控制台上的,可以使用 AllocConsole 函数来创建一个新的控制台( GUI 程序在创建的时候不附着到控制台上,控制台进程在使用 DETACHED_PROCESS 标志的 CreateProcess 函数创建的时候也不附着到控制台上。

    典型的情况,一个程序在错误发生并请求用户交互的时候使用 AllocConsole 来创建一个控制台。例如,一个 GUI 程序在阻止使用正常图形接口程序错误发生的时候能创建一个控制台,或一个控制台进程没有正常地和用户交互可以创建一个控制台来显示错误。

    进程可以在调用 CreateProcess 的时候指定 CREATE_NEW_COSOLE 标志来创建一个控制台。这个方法创建一个控制对子进程可访问,而对父进程不可访问。独立的控制台对于是父子进程与用户不冲突的交互成为可能。如果这个标志在一个控制台进程创建的时候没有指定,两个进程都附着到相同的控制台上,并且不能保证正确的进程能接收到提供给他的输入。程序可以在创建子进程的时候不继承输入缓冲区的句柄来避免这种迷惑的情况,或者同时只有一个子进程继承输入缓冲区句柄来组织父亲进程在子进程没有完成的时候读控制台输入。

    创建一个新的控制台结果是一个新的控制台窗口,同时也包括独立的屏幕缓冲区。和新控制台关联的进程可以使用 GetStdHandle 函数来得到新的控制台输入和屏幕缓冲区的句柄。这些句柄使进程可以访问控制台。

    当一个进程使用 CreateProcess ,它可以指定一个 STARTUPINFO 结构,该结构的成员控制为子进程创建的第一个新控制台的特性。如果 CREATE_NEW_CONSOLE 标志被指定, STARTUPINFO 结构在调用 CreateProcess 时候影响一个控制台的创建;它也影响子进程后来使用 AllocConsole 来创建控制台。下面的控制台特性可以指定:

    1.  新控制台窗口的大小,字符单元

    2.  新控制台窗口的位置,屏幕像素坐标

    3.  新控制台屏幕缓冲区的文本和背景颜色属性

    4.  新控制台窗口的 TITLE BAR 上的显示名字

    如果 STARTUPINFO 值没有指定,系统使用默认的值。子进程可以使用 GetStartupInfo 函数来判断 STARTUPINFO 结构中的值。

    进程不能改变控制台窗口在屏幕上的位置,但下面的控制台函数可以用来设置和获得 STARTUPINFO 结构的其他属性。

    函数

    描述

    GetConsoleScreenBufferInfo

    返回窗口大小、屏幕缓冲区大小和颜色属性

    SetConsoleWindowInfo

    改变控制台窗口的大小

    SetConsoleScreenBufferSize

    该表控制台屏幕缓冲区的大小

    SetConsoleTextAttribute

    设置颜色属性

    SetConsoleTitle

    设置控制台窗口的标题

    GetConsoleTitle

    获得控制窗口的标题

    进程可以使用 FreeConsole 函数来分离继承的控制台或通过 AllocConsole 创建的控制台。

    展开全文
  • 控制台

    2019-10-10 20:14:12
    控制台(Console)是JS开发里最重要的面板,主要作用是显示网页加载过程中产生各类信息。 之前的开发经常用Firebug进行JS代码调试,Firebug是firefox下的一个扩展,能够调试所有网站语言,如Html,Css等,最吸引人的...

    console简介

    控制台(Console)是JS开发里最重要的面板,主要作用是显示网页加载过程中产生各类信息。

    之前的开发经常用Firebug进行JS代码调试,Firebug是firefox下的一个扩展,能够调试所有网站语言,如Html,Css等,最吸引人的就是javascript调试功能,使用起来非常方便,而且在各种浏览器下正常使用,但是目前为止Firebug 官网宣布已停止开发更新。

    但目前的浏览器自带的开发者工具类似于FireBug,一样可以使用。
    console对象,提供5种方法,用来显示信息
    日志信息console.log()、一般信息console.info()
    除错信息console.debug()、警告提示console.warn()
    错误提示console.error()
    console对象,提供5种方法,用来显示信息
    日志信息console.log()、一般信息console.info()
    除错信息console.debug()、警告提示console.warn()
    错误提示console.error()

    在这里插入图片描述

    chrome浏览器

    在这里插入图片描述

    Firefox浏览器

    在这里插入图片描述

    占位符

    console对象的上面5种方法,都可以使用printf(格式化输出)风格的占位符。不过,占位符的种类比较少,只支持字符(%s)、整数(%d或%i)、浮点数(%f)和对象(%o)、CSS格式化样式(%c)五种。
    在这里插入图片描述
    在这里插入图片描述
    %o占位符,可以用来查看一个对象内部情况。比如,有这样一个对象,对它使用o%占位符:
    在这里插入图片描述

    丰富样式输出

    可以使用%c进行css样式格式化输出。常见的富样式输出有两种:文字样式、图片输出。
    (1)文字样式
    在这里插入图片描述

    (2)%c可以写在任何地方,不限于开头,然后%c后面所有的输出会应用我们指定的样式。如果想单独对中间某几个字进行样式处理呢?
    在这里插入图片描述
    在这里插入图片描述
    如果信息太多,可以分组显示,用到的方法是console.group()和console.groupEnd()。

    在这里插入图片描述
    在这里插入图片描述

    注意:点击组标题,该组信息会折叠或展开;可以用console.groupEnd()引起来,也可以不引起来或者最后引起。

    console.dir()可以显示一个对象所有的属性和方法。
    在这里插入图片描述
    在这里插入图片描述

    console.dirxml()用来显示网页的某个节点(node)所包含的html/xml代码。
    在这里插入图片描述
    在这里插入图片描述

    console.clear()清空控制台内容
    在这里插入图片描述
    在这里插入图片描述

    计时器

    console.time(),console.timeEnd()方法计算一个操作的执行的时间console.time()是开始,console.timeEnd()是结束。
    可以传一个参数,参数为计时器的名称。
    在这里插入图片描述
    在这里插入图片描述

    计数器

    console.count()方法用于计数,输出它被调用了多少次。
    在这里插入图片描述
    在这里插入图片描述

    表格化

    console.table()方法可以将传入的对象或数组这些复合数据以表格形式输出。
    在这里插入图片描述
    在这里插入图片描述

    控制台快捷键

    1、方向键盘的上下键,一用就知晓。比如用上键就相当于使用上次在控制台的输入符号。
    2、$_命令返回最近一次表达式执行的结果,功能跟按向上的方向键再回车是一样的

    在这里插入图片描述

    3、Chrome 控制台中原生支持类jQuery的选择器,也就是说你可以用cssDOM加上熟悉的css选择器来选择DOM节点。例如(‘body’)
    4、$ 简单理解就是 document.querySelector 。
    5、$$ 简单理解就是 document.querySelectorAll 。
    6、$_ 是上一个表达式的值
    7、dir 就是 console.dir

    展开全文
  • 00. 目录 文章目录00. 目录01. INPUT_RECORD结构02....描述控制台输入缓冲区中的输入事件。可以使用ReadConsoleInput或PeekConsoleInput函数从输入缓冲区读取这些记录,也可以使用WriteConsoleInput...

    00. 目录

    01. INPUT_RECORD结构

    描述控制台输入缓冲区中的输入事件。可以使用ReadConsoleInputPeekConsoleInput函数从输入缓冲区读取这些记录,也可以使用WriteConsoleInput函数将这些记录写入输入缓冲区。

    类型声明:

    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;
    

    EventType

    输入事件类型的句柄和存储在Event成员中的事件记录。

    该成员可以是以下值之一。

    含义
    FOCUS_EVENT 0x0010 事件成员包含一个FOCUS_EVENT_RECORD结构。这些事件在内部使用,应该被忽略。
    KEY_EVENT 0x0001 事件成员包含一个KEY_EVENT_RECORD结构有关键盘事件的信息。
    MENU_EVENT 0x0008 事件成员包含一个MENU_EVENT_RECORD结构。这些事件在内部使用,应该被忽略。
    MOUSE_EVENT 0x0002 所述事件构件包含MOUSE_EVENT_RECORD结构用约鼠标移动或按键按压事件的信息。
    WINDOW_BUFFER_SIZE_EVENT 0x0004 事件成员包含一个WINDOW_BUFFER_SIZE_RECORD结构有关控制台屏幕缓冲区的新大小信息。

    事件
    事件信息。此成员的格式取决于EventType成员指定的事件类型。

    02. MOUSE_EVENT_RECORD结构

    描述控制台INPUT_RECORD结构中的鼠标输入事件。

    类型声明:

    typedef struct _MOUSE_EVENT_RECORD {
      COORD dwMousePosition;
      DWORD dwButtonState;
      DWORD dwControlKeyState;
      DWORD dwEventFlags;
    } MOUSE_EVENT_RECORD;
    

    成员说明

    dwMousePosition
    一个COORD结构,它根据控制台屏幕缓冲区的字符单元格坐标包含光标的位置。

    dwButtonState
    鼠标按钮的状态。最低有效位对应于最左边的鼠标按钮。下一个最低有效位对应于最右边的鼠标按钮。下一位表示从左到右的鼠标按钮。然后,这些位从左到右对应鼠标按钮。如果按下按钮,则位为1。

    为前五个鼠标按钮定义了以下常量。

    含义
    FROM_LEFT_1ST_BUTTON_PRESSED 0x0001 最左边的鼠标按钮。一般来说鼠标左键
    FROM_LEFT_2ND_BUTTON_PRESSED 0x0004 左起第二个按钮。一般来说是鼠标中键,就是滚轮键
    FROM_LEFT_3RD_BUTTON_PRESSED 0x0008 左起第三个按钮。
    FROM_LEFT_4TH_BUTTON_PRESSED 0x0010 左起第四个按钮。
    RIGHTMOST_BUTTON_PRESSED 0x0002 最右边的鼠标按钮。一般来说鼠标右键

    dwControlKeyState
    控制键的状态。该成员可以是以下一个或多个值。

    含义
    CAPSLOCK_ON 0x0080 大写锁定被打开
    ENHANCED_KEY 0x0100 扩展键被按下
    LEFT_ALT_PRESSED 0x0002 按下左ALT键。
    LEFT_CTRL_PRESSED 0x0008 按下左CTRL键。
    NUMLOCK_ON 0x0020 数字锁定被打开
    RIGHT_ALT_PRESSED 0x0001 按下右ALT键。
    RIGHT_CTRL_PRESSED 0x0004 按下右CTRL键。
    SCROLLLOCK_ON 0x0040 滚动锁定被打开
    SHIFT_PRESSED 0x0010 按下SHIFT键。

    dwEventFlags
    鼠标事件的类型。如果此值为零,则表示正在按下或释放鼠标按钮。否则,此成员是以下值之一。

    含义
    DOUBLE_CLICK 0x0002 双击的第二次单击(按下按钮)发生。第一次单击作为常规按钮事件返回。
    MOUSE_HWHEELED 0x0008 水平鼠标滚轮被移动了。如果dwButtonState成员的高位字包含正值,则轮子向右旋转。否则,车轮向左旋转。
    MOUSE_MOVED 0x0001 发生了鼠标位置的变化。
    MOUSE_WHEELED 0x0004 垂直鼠标滚轮被移动。如果dwButtonState成员的高位字包含正值,则轮向前旋转,远离用户。否则,车轮向后旋转,朝向用户。

    03. ReadConsoleInput函数

    从控制台输入缓冲区读取数据并将其从缓冲区中删除。

    函数声明:

    BOOL WINAPI ReadConsoleInput(
      _In_  HANDLE        hConsoleInput,
      _Out_ PINPUT_RECORD lpBuffer,
      _In_  DWORD         nLength,
      _Out_ LPDWORD       lpNumberOfEventsRead
    );
    功能:
    	从控制台输入缓冲区读取数据并将其从缓冲区中删除。
    参数:
    	hConsoleInput 控制台输入缓冲区的句柄。句柄必须具有GENERIC_READ访问权限。
    	lpBuffer 指向接收输入缓冲区数据的INPUT_RECORD结构数组的指针。
    	nLength 数组元素中lpBuffer参数 指向的数组大小。
    	lpNumberOfEventsRead 指向接收读取的输入记录数的变量的指针。
    	
    返回值:
    	如果函数成功,则返回值为非零值。
    	如果函数失败,则返回值为零。要获取扩展错误信息,请调用GetLastError。
    

    官方参考网址:https://docs.microsoft.com/en-us/windows/console/readconsoleinput

    04. 示例程序

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    #include <Windows.h>
    #include <conio.h>
    
    
    int main(void)
    {
    	//定义句柄变量
    	HANDLE hOut = NULL;
    	HANDLE hIn = NULL;
    
    	//定义输入事件结构体
    	INPUT_RECORD mouseRecord;
    
    	//用于存储读取记录
    	DWORD res;
    
    	//用于存储鼠标当前位置
    	COORD pos;
    
    
    	//获取标准输出句柄
    	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    
    	//获取标准输入句柄
    	hIn = GetStdHandle(STD_INPUT_HANDLE);
    	
    	while (1)
    	{
    		//读取输入事件
    		ReadConsoleInput(hIn, &mouseRecord, 1, &res);
    
    		//获取鼠标当前位置
    		pos = mouseRecord.Event.MouseEvent.dwMousePosition;
    
    		//如果当前事件是鼠标事件
    		if (mouseRecord.EventType == MOUSE_EVENT)
    		{
    			//单击鼠标左键
    			if (mouseRecord.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
    			{
    				printf("鼠标左键单击 x: %d y: %d\n", pos.X, pos.Y);
    			}
    
    			//单击鼠标右键
    			if (mouseRecord.Event.MouseEvent.dwButtonState == RIGHTMOST_BUTTON_PRESSED)
    			{
    				printf("鼠标右键单击 x: %d y: %d\n", pos.X, pos.Y);
    			}
    
    			//如果是双击就退出循环
    			if (mouseRecord.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)
    			{
    				break;
    			}
    
    		}
    	}
    
    	//关闭句柄
    	CloseHandle(hOut);
    	CloseHandle(hIn);
    
    	//system("pause");
    	getchar();
    	return 0;
    }
    
    展开全文
  • 控制台和终端的区别

    千次阅读 2017-10-25 23:52:18
    直接连接到电脑上的键盘和显示器叫控制台,可显示系统消息; 控制台是基本设备,终端是附加设备,一台电脑可以有多个终端,但只有一个控制台控制台/终端:可输入命令行并显示程序运行过程的信息及程序运行结果的...
  • VS显示控制台窗口

    万次阅读 2018-09-27 09:03:03
    有的时候我们在完成编程后, 运行发现没有控制台窗口, 比如我们用Qt编写的界面软件, 又想看到我们在代码中添加的打印日志信息,这个时候加上控制台窗口就能实现 方法: 项目–&gt; 属性–&gt;链接器–&...
  • 什么是控制台应用程序

    千次阅读 2020-03-09 15:11:15
    控制台是? 黑色的这个窗口就是控制台了 那应用程序呢? 就是显示的文字指令和输入的文字指令构成的一个对话功能 怎么完成对话? Console.WriteLine();用来输出 将()内的字符串显示在控制台里面 字符串...
  • 介绍C#控制台程序开发的数据输入与获取、命令行参数解析、控制台窗口设置的相关细节
  • #pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" ) //不显示控制台,在代码前加上上述代码  
  • 关于IDEA启动tomcat报错��Ϣ

    千次阅读 2019-08-20 10:52:29
    这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、...
  • 控制台的常用命令

    千次阅读 2018-09-19 15:48:55
    控制台命令 控制台是程序员常用的一种工具,并以此来验证各种系统的配置是否成功,而常用的则是用控制台来验证jdk环境的配置是否成功。 验证jdk环境则要打开控制台进行操作。 而步骤则: 一: 点击界面的开始-&...
  • 带w:窗口 带f:全屏
  • 控制台小游戏

    2018-04-16 11:45:57
    自己编写的控制台小游戏 还在完善中希望大家能喜欢啦啦啦啦啦啦啦
  • IDEA解决控制台乱码问题

    千次阅读 2018-12-22 17:04:52
    直到很久以后,我换了电脑,当控制台再次出现该问题时,我就懒得解决了,毕竟在单元测试的时候是不走Tomcat的,也就是说不会出现这种乱码问题。   直到最近,我的同事在看到我控制台中中文乱码现象后一直提醒我...
  • windows常用控制台命令

    千次阅读 2018-02-11 10:44:45
    路径跳转:cd [path]; 如果要同时转换盘符: cd /d [path]; 文件夹下内容查看: dir; 当前计算机配置查看:systeminfo; 当前运行的进程列表:tasklist;...结束进程:taskkill /pid [pid]; 如果要强制结束进程:taskkill...
  • git 控制台命令

    千次阅读 2017-04-10 21:16:38
    mkdir 文件名 创建文件夹 pwd 显示当前目录 git init 把当前目录创建一个空的git仓库 ls -ah 查看隐藏文件夹 git add 文件 添加文件 ...git commit -m "commit file“ 提交文件 ...git log --pretty=onel
  • Unreal Engine 4 控制台命令参数合集

    千次阅读 2016-10-21 10:18:19
    他们也被称为控制台命令 ,因为它们通常在一个控制台窗口中运行。 要在游戏中执行命令,或〜,弹出控制台,键入命令,然后按Enter。这些命令不区分大小写。 要在编辑器中执行命令,可在主编辑器窗口的左下方...
  • Windows控制台命令大全

    2014-10-27 10:08:33
    windows 删除服务: 在控制台输入命令 sc delete fu
  • MYSQL 控制台命令

    万次阅读 2016-10-10 16:13:59
    导入导出sql文件,查看数据库,查看表等命令
  • UE4控制台命令

    2018-06-22 10:58:00
    修改分辨率的命令是:,但不能一开始就执行,可能会被配置文件里的设置顶替(可能是,再研究下) 其中w是指窗口,要全屏可改成f。 也可以在代码中修改分辨率,如下: void AHxVipPlayerManager::...

空空如也

1 2 3 4 5 ... 20
收藏数 904,448
精华内容 361,779
关键字:

控制台