zoukankan      html  css  js  c++  java
  • c/c++ console(控制台)编程详解

    前言:

    控制台文本窗口的控制是基于win32 api(win32 api可理解为微软给我们提供的一系列函数的集合)实现的;

    例1:

    #include <stdio.h>int main()
    {
        printf("Hello World!
    ");
        return 0;
    }

    运行结果:

    例1中,我们用printf()函数实现在控制台输出了hello world!然而当我们想要将之前输出的内容清除时,在stdio.h中的函数并不能满足我们的需求;这时我们就要借助于win32 api函数

    例2:

    #include <stdio.h>
    #include <windows.h>
    int main()
    {
        printf("Hello World!
    ");
        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();函数

    综合案例贪吃蛇,推箱子,俄罗斯方块(待续。。。)

  • 相关阅读:
    DataTable转换成IList<T>的简单实现
    websocket
    获取用户使用设备信息
    判断对象是否相等
    关于PC适配
    树形数据结构实现平铺展示
    埋点
    多层表单验证
    表格行拖动,数据中状态值不同的禁止拖拽
    element tree 深度查询
  • 原文地址:https://www.cnblogs.com/flowingwind/p/8159035.html
Copyright © 2011-2022 走看看