C++控制台强化如何实现一定界面效果(简洁版)

目录

  • TANXL_CONSOLE_LIST VERSION_1_4
    • TANXL_CONSOLE_LIST.H VERSION_1_4
  • TANXL_CONSOLE_LIST.H VERSION_1_5
    • TANXL_CONSOLE_LIST.H VERSION_1_5
    • TANXL_CONSOLE_LIST.CPP VERSION_1_5
    • Main.CPP(测试用)
  • TANXL_CONSOLE_LIST.H VERSION_1_5+_Final
    • TANXL_CONSOLE_LIST.H VERSION_1_5++_Final
      • TANXL_CONSOLE_LIST.CPP VERSION_1_5++_Final

        TANXL_CONSOLE_LIST VERSION_1_4 在完成了游戏存档模块的开发之后,我试图用之前制作的Console_List头文件为基础,制作一个命令行上的数据管理器,但是在实际使用中我发现了Console_List的各种不足。
        比如提供了接口之后还需要用户输入大量的代码来完成表格的输出,明显不能做到让接口容易被正确使用,不易被误用。
        于是在这个背景下,我对Console_List进行了完全重写,在比前几代代码减少2/3的情况下,功能大幅加强,同时只需要一次物品初始化,一次调用显示函数,明显更加容易使用。

        TANXL_CONSOLE_LIST.H VERSION_1_4
        #ifndef TANXL_CONSOLE_LIST#define TANXL_CONSOLE_LIST#ifndef TANXL_LIST//检查是否使用了其他版本的TANXL_CONSOLE_LIST#define TANXL_LIST#define LIST 1#endif#endif#if LIST#ifndef IOSTREAM//检查是否已经包含IOSTREAM#define IOSTREAM#include #endif#ifndef VECTOR//检查是否已经包含VECTOR#define VECTOR#include #endif#ifndef CONIO_H//检查是否已经包含CONIO_H#define CONIO_H#include #endif#ifndef IOMANIP//检查是否已经包含IOMANIP#define IOMANIP#include #endif//void Col是原Console_List的核心功能,使用了Linux控制台的指令void Col(unsigned ColN = NULL, bool Under_Line = false)//设置自定义行的背景颜色{ if (ColN == NULL)std::cout << "\033[0m"; //清除颜色 else {if (Under_Line == true)std::cout << "\033[7m"; std::cout << "\033[4; 1; m"; if (((ColN & 0xf0) >> 4) > 0 && ((ColN & 0xf0) >> 4) <= 7)std::cout << "\033[3" << ((ColN & 0xf0) >> 4) << "m"; else if ((ColN & 0xf0) >> 4 == 0); //值为0不作修改else//字体颜色: 1红色 2绿色 3橙色 4蓝色 5紫色 6淡蓝 7白色std::cout << "\033[3" << rand() % 7 + 1 << "m"; if ((ColN & 0x0f) > 0 && ((ColN & 0x0f) <= 7))std::cout << "\033[4" << (ColN & 0x0f) << "m"; else if ((ColN & 0x0f) == 0); //值为0不作修改else//背景颜色: 1红色 2绿色 3橙色 4蓝色 5紫色 6淡蓝 7白色std::cout << "\033[4" << rand() % 7 + 1 << "m"; }}//第三级别的物品结构struct Function{ //void Page_Info() { Col(); std::cout << "This: " << Selector << " - Total: " << SonList.size() << " - Max: " << (SSpace & 0x0000ff) << std::endl; } Function() :Name("NULL"), /*SonList(NULL),*/ Func(NULL) {}; Function(std::string N, void(*F)()) :Name(N),/* SonList(NULL),*/ Func(F) {}; //int Selector{ 0 }; //bool Is_Selected{ false }; std::string Name; void(*Func)(); unsigned SSpace{ 0x171109 }; //选项和标题的空格数 AA-BB-CC AA左空格 BB右空格 CC页面物品限制数量 //std::vectorSonList; }; //第二级别的物品结构struct Main_Function{ void Page_Info() { Col(); std::cout << "This: " << Selector << " - Total: " << SonList.size() << " - Max: " << (SSpace & 0x0000ff) << std::endl; } Main_Function(std::string N = "NULL") :Name(N), SonList(NULL) {}; Main_Function(std::string N, void(*F)()) :Name(N), SonList(NULL), Func(F) {}; int Selector{ 0 }; bool Is_Selected{ false }; std::string Name; void(*Func)() { NULL }; unsigned SSpace{ 0x171109 }; //选项和标题的空格数 AA-BB-CC AA左空格 BB右空格 CC页面物品限制数量 std::vectorSonList; }; //第一级别的主要物品类class CONSOLE_LIST{public: void Display(); void Append_Item(std::string New_Item) { SonList.push_back(Main_Function(New_Item)); }; //添加二级物品作为选项 //At用于指定第几个二级物品,后续两个量用于生成一个新的三级物品 void Append_Svec(int At, std::string Name, void(*Func)()) { SonList.at(At).SonList.push_back(Function(Name, Func)); }; //添加二级物品下的三级物品,同时绑定一个void类型的函数private: void Page_Info() { Col(); std::cout << "This: " << Selector << " - Total: " << SonList.size() << " - Max: " << (SSpace & 0x0000ff) << std::endl; }//输出当前页面信息 bool Insert_Action(int* Action_Num, bool* Action_Bol, size_t List_Size); //输入操作 int Selector{ 0 }; int Pages{ 0 }; bool Is_Selected{ false }; std::vectorSonList; unsigned SSpace{ 0x171109 }; //选项和标题的空格数 AA-BB-CC AA左空格 BB右空格 CC页面物品限制数量}; void CONSOLE_LIST::Display(){ Col(); bool flag{ true }; bool brea{ false }; while (true) {if (!flag){Is_Selected = false; flag = true; continue; }system("cls"); int* Num{ &Selector }; bool* Bol{ &Is_Selected }; size_t Siz{ SonList.size() }; for (int i = 0; i < SonList.size(); i++){if (i == Selector)Col(0x71); elseCol(0x17); std::cout << std::setw((SSpace & 0xff0000) >> 16) << SonList.at(i).Name << std::setw((SSpace & 0x00ff00) >> 8) << " " << std::endl; if (i == Selector && Is_Selected == true){Pages = SonList.at(i).Selector / (SSpace & 0x0000ff); for (int j = Pages * (SSpace & 0x0000ff), count = 0; j < SonList.at(i).SonList.size() && count < (SSpace & 0x0000ff); j++&& count++){if (j == SonList.at(i).Selector)Col(0x71); elseCol(0x17); std::cout << std::setw((SSpace & 0xff0000) >> 16) << SonList.at(i).SonList.at(j).Name << std::setw((SSpace & 0x00ff00) >> 8) << " " << std::endl; if (SonList.at(i).Is_Selected == true && j == SonList.at(i).Selector){SonList.at(i).SonList.at(j).Func(); SonList.at(i).Is_Selected = false; brea = true; break; }}SonList.at(i).Page_Info(); if (brea)break; Num = &SonList.at(i).Selector; Bol = &SonList.at(i).Is_Selected; Siz = SonList.at(i).SonList.size(); }std::cout << std::endl; }Page_Info(); if (brea){brea = false; continue; }Col(); flag = Insert_Action(Num, Bol, Siz); //等待输入 }}bool CONSOLE_LIST::Insert_Action(int* Action_Num, bool* Action_Bol, size_t List_Size){ char key = _getch(); if (key == 'c' || key == 'C')//如果输入了大小写的C则返回上一级 {*Action_Bol = false; return false; } if (static_cast(key - 48) >= 0 && static_cast(key - 48) <= 9)//判断是否是从零到九的数字 {if (static_cast(key - 48) <= List_Size)//如果是,且小于等于选项总数则直接指定这个选项*Action_Num = static_cast(key - 48) - 1; else*Action_Num = static_cast(List_Size) - 1; //如果超出了最大值,则指向最大值*Action_Bol = true; } else if (key == 'w' || key == 'W' || key == 72)//如果输入了大小写的W或者上箭头,则执行MoveUp函数*Action_Num = *Action_Num == 0 ? static_cast(List_Size) - 1 : -- * Action_Num; else if (key == 's' || key == 'S' || key == 80)//如果输入了大小写的S或者下箭头,则执行MoveDown函数*Action_Num = *Action_Num == static_cast(List_Size) - 1 ? 0 : ++ * Action_Num; else if (key == 'a' || key == 'A' || key == 75)//如果输入了大小写的A或者左箭头,则执行向上翻页函数*Action_Num = *Action_Num - static_cast(SSpace & 0x0000ff) < 0 ? 0 : *Action_Num - (SSpace & 0x0000ff); else if (key == 'd' || key == 'D' || key == 77)//如果输入了大小写的D或者右箭头,则执行向下翻页函数*Action_Num = *Action_Num + (SSpace & 0x0000ff) > static_cast(List_Size) - 1 ? static_cast(List_Size) - 1 : *Action_Num + (SSpace & 0x0000ff); else if (key == '\r')//回车确认*Action_Bol = true; return true; }#endif

        以下为使用例:
        Main.cpp
        #include "TANXL_CONSOLE_LIST.h"void say(){Col(); system("cls"); std::cout << "wdnmd"; system("pause"); }int main(){CONSOLE_LIST TSM; TSM.Append_Item("数据管理"); TSM.Append_Svec(0, "数据管理1", &say); TSM.Append_Svec(0, "数据管理2", &say); TSM.Append_Svec(0, "数据管理3", &say); TSM.Append_Svec(0, "数据管理4", &say); TSM.Append_Svec(0, "数据管理5", &say); TSM.Append_Svec(0, "数据管理6", &say); TSM.Append_Svec(0, "数据管理7", &say); TSM.Append_Svec(0, "数据管理8", &say); TSM.Append_Svec(0, "数据管理9", &say); TSM.Append_Svec(0, "数据管理10", &say); TSM.Append_Svec(0, "数据管理11", &say); TSM.Append_Svec(0, "数据管理12", &say); TSM.Append_Svec(0, "数据管理13", &say); TSM.Append_Svec(0, "数据管理14", &say); TSM.Append_Svec(0, "数据管理15", &say); TSM.Append_Item("添加数据"); TSM.Append_Svec(1, "添加数据1", &say); TSM.Append_Svec(1, "添加数据2", &say); TSM.Append_Svec(1, "添加数据3", &say); TSM.Append_Item("查看数据"); TSM.Append_Svec(2, "查看数据1", &say); TSM.Append_Svec(2, "查看数据2", &say); TSM.Append_Svec(2, "查看数据3", &say); TSM.Append_Item("修改数据"); TSM.Append_Svec(3, "修改数据1", &say); TSM.Append_Svec(3, "修改数据2", &say); TSM.Append_Svec(3, "修改数据3", &say); TSM.Append_Item("退出程序"); TSM.Append_Svec(4, "_-确认-_", &say); TSM.Append_Svec(4, "_-取消-_", &say); TSM.Display(); }

        C++控制台强化如何实现一定界面效果(简洁版)
        文章图片

        C++控制台强化如何实现一定界面效果(简洁版)
        文章图片

        C++控制台强化如何实现一定界面效果(简洁版)
        文章图片


        TANXL_CONSOLE_LIST.H VERSION_1_5 再次对几乎所有函数进行重写,为了操作的一致性移除了三级物品的设定,统一由类来进行管理。通过递归的方法实现输出列表,理论上能无限扩展深度。
        三级列表
        C++控制台强化如何实现一定界面效果(简洁版)
        文章图片

        六级列表
        C++控制台强化如何实现一定界面效果(简洁版)
        文章图片


        TANXL_CONSOLE_LIST.H VERSION_1_5
        // 移除Main_Function Function并将功能整合至CONSOLE类// 绝大多数函数重写以支持多于一层的表格输出

        #ifndef TANXL_CONSOLE_LIST#define TANXL_CONSOLE_LIST#ifndef TANXL_LIST//检查是否使用了其他版本的TANXL_CONSOLE_LIST#define TANXL_LIST#define LIST 1#endif#endif#if LIST#ifndef IOSTREAM//检查是否已经包含IOSTREAM#define IOSTREAM#include #endif#ifndef VECTOR//检查是否已经包含VECTOR#define VECTOR#include #endif#ifndef CONIO_H//检查是否已经包含CONIO_H#define CONIO_H#include #endif#ifndef IOMANIP//检查是否已经包含IOMANIP#define IOMANIP#include #endif//void Col是原Console_List的核心功能,使用了Linux控制台的指令void Col(unsigned ColN = NULL, bool Under_Line = false); //设置自定义行的背景颜色//物品类class CONSOLE{public: explicit CONSOLE(std::string Name = "UNdefined", unsigned Space = 0x171109, void(*FunC)() = NULL); void Display(int Depth = 0, unsigned Def_Col = 0x71, unsigned Real_Sel = 0x75); void MainLoop(); void Append_Item(std::string New_Item, unsigned Col, void(*FunC)(), int Depth = 0, int* Ids = 0); private: bool Insert_Action(int* Action_Num, bool* Action_Bol, size_t List_Size); CONSOLE* Locate(int Target = 0); std::string Name; int Selector; int Page; bool Is_Selected; bool Is_Funcwork; std::vectorSonList; void (*Func)(); unsigned SSpace; // { 0x171109 }选项和标题的空格数 AA-BB-CC AA左空格 BB右空格 CC页面物品限制数量}; #endif


        TANXL_CONSOLE_LIST.CPP VERSION_1_5
        #include "TANXL_CONSOLE_LIST.h"//void Col是原Console_List的核心功能,使用了Linux控制台的指令void Col(unsigned ColN, bool Under_Line)//设置自定义行的背景颜色{ if (ColN == NULL)std::cout << "\033[0m"; //清除颜色 else {if (Under_Line == true)std::cout << "\033[7m"; std::cout << "\033[4; 1; m"; if (((ColN & 0xf0) >> 4) > 0 && ((ColN & 0xf0) >> 4) <= 7)std::cout << "\033[3" << ((ColN & 0xf0) >> 4) << "m"; else if ((ColN & 0xf0) >> 4 == 0); //值为0不作修改else//字体颜色: 1红色 2绿色 3橙色 4蓝色 5紫色 6淡蓝 7白色std::cout << "\033[3" << rand() % 7 + 1 << "m"; if ((ColN & 0x0f) > 0 && ((ColN & 0x0f) <= 7))std::cout << "\033[4" << (ColN & 0x0f) << "m"; else if ((ColN & 0x0f) == 0); //值为0不作修改else//背景颜色: 1红色 2绿色 3橙色 4蓝色 5紫色 6淡蓝 7白色std::cout << "\033[4" << rand() % 7 + 1 << "m"; }}//构造函数CONSOLE::CONSOLE(std::string NamE, unsigned Space, void(*FunC)()) :Selector(0), Is_Selected(false), SonList(NULL), SSpace(Space), Func(FunC), Is_Funcwork(true), Name(NamE),Page(0){ if (Func == NULL)Is_Funcwork = false; }//添加函数void CONSOLE::Append_Item(std::string New_Item, unsigned Col, void (*FunC)(), int Depth, int* Ids){ if (Depth == 0)SonList.push_back(CONSOLE(New_Item, Col, FunC)); else {CONSOLE* CP{ this }; for (int i = 0; i < Depth; i++)CP = &CP->SonList.at(Ids[i]); CP->SonList.push_back(CONSOLE(New_Item, Col, FunC)); }}void CONSOLE::Display(int Depth, unsigned Def_Col, unsigned Real_Sel){ Col(); bool Is_Line_Need{ false }; Page = this->Selector / (SSpace & 0x00ff); for (int i = Page * (SSpace & 0x00ff); i < SonList.size() && i < (Page+1)*(SSpace & 0x00ff); i++) {for (int j = Depth; j > 0; j--)std::cout << "\t"; if (i == Selector)Col(Real_Sel); elseCol(Def_Col); std::cout << std::setw((SSpace & 0xff0000) >> 16) << SonList.at(i).Name << std::setw((SSpace & 0x00ff00) >> 8) << " " << std::endl; Col(); if (SonList.at(i).SonList.size() == 0 && this->Is_Selected == true && this->Selector == i)//在包含子项目为0时自动退出{if (SonList.at(i).Is_Funcwork)SonList.at(i).Func(); this->Is_Selected = false; }if (SonList.at(i).SonList.size() != 0 && this->Is_Selected == true && this->Selector == i){std::cout << std::endl; this->SonList.at(i).Display(Depth + 1, (Def_Col & 0x0f) * 16 + (Def_Col & 0xf0) / 16, Real_Sel); Is_Line_Need = 1; }if (!Is_Line_Need)std::cout << std::endl; if (Is_Line_Need)Is_Line_Need = false; Col(); }}void CONSOLE::MainLoop()//主循环{ bool Insert{ true }; bool Cover{ false }; int* Action_Num { &Locate()->Selector}; bool* Action_Bol{ &Locate()->Is_Selected }; size_t List_Size{ Locate()->SonList.size() }; while (1) {system("cls"); this->Display(); if (!Cover){Action_Num = &Locate()->Selector; Action_Bol = &Locate()->Is_Selected; List_Size = Locate()->SonList.size(); }elseCover = false; if (!Insert){Action_Num = &Locate(-1)->Selector; Action_Bol = &Locate(-1)->Is_Selected; List_Size = Locate(-1)->SonList.size(); Locate(-1)->Is_Selected = false; Insert = true; Cover = true; continue; }Insert = Insert_Action(Action_Num, Action_Bol, List_Size); }}bool CONSOLE::Insert_Action(int* Action_Num, bool* Action_Bol, size_t List_Size){ char key = _getch(); if (key == 'c' || key == 'C')//如果输入了大小写的C则返回上一级 {*Action_Bol = false; return false; } if (static_cast(key - 48) >= 0 && static_cast(key - 48) <= 9)//判断是否是从零到九的数字 {if (static_cast(key - 48) <= static_cast(List_Size))//如果是,且小于等于选项总数则直接指定这个选项*Action_Num = static_cast(key - 48) - 1; else*Action_Num = static_cast(List_Size) - 1; //如果超出了最大值,则指向最大值*Action_Bol = true; } else if (key == 'w' || key == 'W' || key == 72)//如果输入了大小写的W或者上箭头,则执行MoveUp函数*Action_Num = *Action_Num == 0 ? static_cast(List_Size) - 1 : -- * Action_Num; else if (key == 's' || key == 'S' || key == 80)//如果输入了大小写的S或者下箭头,则执行MoveDown函数*Action_Num = *Action_Num == static_cast(List_Size) - 1 ? 0 : ++ * Action_Num; else if (key == 'a' || key == 'A' || key == 75)//如果输入了大小写的A或者左箭头,则执行向上翻页函数*Action_Num = *Action_Num - static_cast(SSpace & 0x0000ff) < 0 ? 0 : *Action_Num - (SSpace & 0x0000ff); else if (key == 'd' || key == 'D' || key == 77)//如果输入了大小写的D或者右箭头,则执行向下翻页函数*Action_Num = *Action_Num + static_cast(SSpace & 0x0000ff) > static_cast(List_Size) - 1 ? static_cast(List_Size) - 1 : *Action_Num + (SSpace & 0x0000ff); else if (key == '\r')//回车确认*Action_Bol = true; return true; }CONSOLE* CONSOLE::Locate(int Target){ if (Target == 0) {for (int i = 0; i < SonList.size(); i++){if (i == Selector && Is_Selected == true)return SonList.at(i).Locate(); }return this; } else {for (int i = 0; i < SonList.size(); i++){if (i == Selector && Is_Selected == true && SonList.at(i).SonList.size() != 0)if (SonList.at(i).Is_Selected == false)return this; elsereturn SonList.at(i).Locate(-1); }return this; }}


        Main.CPP(测试用)
        #include "Tanxl_Console_List.h"void say(){Col(); std::cout << "\t\tDefault Function Called" << std::endl; }int main(){CONSOLE TSM; TSM.Append_Item("数据管理", 0x171109, &say); TSM.Append_Item("添加数据", 0x171109, &say); TSM.Append_Item("查看数据", 0x171109, &say); TSM.Append_Item("修改数据", 0x171109, &say); TSM.Append_Item("退出程序", 0x171109, &say); int a[] = { 2 }; int b[] = { 2,1 }; TSM.Append_Item("数据管理1-", 0x171109, &say, 1, a); TSM.Append_Item("数据管理2-", 0x171109, &say, 1, a); TSM.Append_Item("数据管理3-", 0x171109, &say, 1, a); TSM.Append_Item("数据管理4-", 0x171109, &say, 1, a); TSM.Append_Item("数据管理5-", 0x171109, &say, 1, a); TSM.Append_Item("数据管理6-", 0x171109, &say, 1, a); TSM.Append_Item("数据管理7-", 0x171109, &say, 1, a); TSM.Append_Item("数据管理8-", 0x171109, &say, 1, a); TSM.Append_Item("数据管理9-", 0x171109, &say, 1, a); TSM.Append_Item("数据管理10-", 0x171109, &say, 1, a); TSM.Append_Item("数据管理11-", 0x171109, &say, 1, a); TSM.Append_Item("数据管理2-1", 0x171109, &say, 2, b); TSM.Append_Item("数据管理2-2", 0x171109, &say, 2, b); TSM.Append_Item("数据管理2-3", 0x171109, &say, 2, b); TSM.Append_Item("数据管理2-4", 0x171109, &say, 2, b); TSM.Append_Item("数据管理2-5", 0x171109, &say, 2, b); TSM.Append_Item("数据管理2-6", 0x171109, &say, 2, b); TSM.MainLoop(); return 0; }


        TANXL_CONSOLE_LIST.H VERSION_1_5+_Final
        // 加入枚举类型用于颜色设置 使之表现更加直观enum EFont_Color{ FONT_UNDEFINED= 0x00, FONT_COLOR_RED= 0x10, FONT_COLOR_GREEN= 0x20, FONT_COLOR_ORANGE= 0x30, FONT_COLOR_BLUE= 0x40, FONT_COLOR_PURPLE= 0x50, FONT_COLOR_LIGHTBLUE = 0x60, FONT_COLOR_WHITE= 0x70}; enum EBack_Color{ BACK_UNDEFINED= 0x00, BACK_COLOR_RED= 0x01, BACK_COLOR_GREEN= 0x02, BACK_COLOR_ORANGE= 0x03, BACK_COLOR_BLUE= 0x04, BACK_COLOR_PURPLE= 0x05, BACK_COLOR_LIGHTBLUE = 0x06, BACK_COLOR_WHITE= 0x07};

        void Display(int Depth = 0, unsigned Def_Col = 0x71, unsigned Real_Sel = 0x75); //可以改为更直观的 ↓void Display(int Depth = 0, unsigned Def_Col = FONT_COLOR_WHITE | BACK_COLOR_RED, unsigned Real_Sel = FONT_COLOR_WHITE | BACK_COLOR_PURPLE); Col(0x71); /*等价于*/ Col(FONT_COLOR_WHITE | BACK_COLOR_RED); Col(0x75); /*等价于*/ Col(FONT_COLOR_WHITE | BACK_COLOR_PURPLE);


        TANXL_CONSOLE_LIST.H VERSION_1_5++_Final 【C++控制台强化如何实现一定界面效果(简洁版)】细节调整
        #ifndef TANXL_CONSOLE_LIST#define TANXL_CONSOLE_LIST#ifndef IOSTREAM//检查是否已经包含IOSTREAM#define IOSTREAM#include #endif#ifndef VECTOR//检查是否已经包含VECTOR#define VECTOR#include #endif#ifndef CONIO_H//检查是否已经包含CONIO_H#define CONIO_H#include #endif#ifndef IOMANIP//检查是否已经包含IOMANIP#define IOMANIP#include #endifenum EFont_Color{ FONT_UNDEFINED= 0x00, FONT_COLOR_RED= 0x10, FONT_COLOR_GREEN= 0x20, FONT_COLOR_ORANGE= 0x30, FONT_COLOR_BLUE= 0x40, FONT_COLOR_PURPLE= 0x50, FONT_COLOR_LIGHTBLUE = 0x60, FONT_COLOR_WHITE= 0x70}; enum EBack_Color{ BACK_UNDEFINED= 0x00, BACK_COLOR_RED= 0x01, BACK_COLOR_GREEN= 0x02, BACK_COLOR_ORANGE= 0x03, BACK_COLOR_BLUE= 0x04, BACK_COLOR_PURPLE= 0x05, BACK_COLOR_LIGHTBLUE = 0x06, BACK_COLOR_WHITE= 0x07}; //void Col是原Console_List的核心功能,使用了Linux控制台的指令void Col(unsigned ColN = NULL, bool Under_Line = false); //设置自定义行的背景颜色//物品类class CONSOLE{public: explicit CONSOLE(std::string Name = "UNdefined", unsigned Space = 0x171109, void(*FunC)() = NULL); void Display(int Depth = 0, unsigned Def_Col = FONT_COLOR_WHITE | BACK_COLOR_RED, unsigned Real_Sel = FONT_COLOR_WHITE | BACK_COLOR_PURPLE); void MainLoop(unsigned Def_Col = FONT_COLOR_WHITE | BACK_COLOR_RED, unsigned Real_Sel = FONT_COLOR_WHITE | BACK_COLOR_PURPLE); void Append_Item(std::string New_Item, unsigned Space = 0x171109, void(*FunC)() = NULL, int Depth = 0, int* Ids = 0); private: bool Insert_Action(int* Action_Num, bool* Action_Bol, size_t List_Size); CONSOLE* Locate(int Target = 0); std::string Name; int Selector; int Page; bool Is_Selected; bool Is_Funcwork; std::vectorSonList; void (*Func)(); unsigned SSpace; // { 0x171109 }选项和标题的空格数 AA-BB-CC AA左空格 BB右空格 CC页面物品限制数量}; #endif


        TANXL_CONSOLE_LIST.CPP VERSION_1_5++_Final
        #include "TANXL_CONSOLE_LIST.h"//void Col是原Console_List的核心功能,使用了Linux控制台的指令void Col(unsigned ColN, bool Under_Line)//设置自定义行的背景颜色{ if (ColN == NULL)std::cout << "\033[0m"; //清除颜色 else {if (Under_Line == true)std::cout << "\033[7m"; std::cout << "\033[4; 1; m"; if (((ColN & 0xf0) >> 4) > 0 && ((ColN & 0xf0) >> 4) <= 7)std::cout << "\033[3" << ((ColN & 0xf0) >> 4) << "m"; else if ((ColN & 0xf0) >> 4 == 0); //值为0不作修改else//字体颜色: 1红色 2绿色 3橙色 4蓝色 5紫色 6淡蓝 7白色std::cout << "\033[3" << rand() % 7 + 1 << "m"; if ((ColN & 0x0f) > 0 && ((ColN & 0x0f) <= 7))std::cout << "\033[4" << (ColN & 0x0f) << "m"; else if ((ColN & 0x0f) == 0); //值为0不作修改else//背景颜色: 1红色 2绿色 3橙色 4蓝色 5紫色 6淡蓝 7白色std::cout << "\033[4" << rand() % 7 + 1 << "m"; }}//构造函数CONSOLE::CONSOLE(std::string NamE, unsigned Space, void(*FunC)()) :Selector(0), Is_Selected(false), SonList(NULL), SSpace(Space), Func(FunC), Is_Funcwork(true), Name(NamE),Page(0){ if (Func == NULL)Is_Funcwork = false; }//添加函数void CONSOLE::Append_Item(std::string New_Item, unsigned Space, void (*FunC)(), int Depth, int* Ids){ if (Depth == 0)SonList.push_back(CONSOLE(New_Item, Space, FunC)); else {CONSOLE* CP{ this }; for (int i = 0; i < Depth; i++)CP = &CP->SonList.at(Ids[i]); CP->SonList.push_back(CONSOLE(New_Item, Space, FunC)); }}void CONSOLE::Display(int Depth, unsigned Def_Col, unsigned Real_Sel){ Col(); bool Is_Line_Need{ false }; Page = this->Selector / (SSpace & 0x00ff); for (int i = Page * (SSpace & 0x00ff); i < SonList.size() && i < (Page+1)*(SSpace & 0x00ff); i++) {for (int j = Depth; j > 0; j--)std::cout << "\t"; if (i == Selector)Col(Real_Sel); elseCol(Def_Col); std::cout << std::setw((SSpace & 0xff0000) >> 16) << SonList.at(i).Name << std::setw((SSpace & 0x00ff00) >> 8) << " " << std::endl; Col(); if (SonList.at(i).SonList.size() == 0 && this->Is_Selected == true && this->Selector == i)//在包含子项目为0时自动退出{if (SonList.at(i).Is_Funcwork)SonList.at(i).Func(); this->Is_Selected = false; }if (SonList.at(i).SonList.size() != 0 && this->Is_Selected == true && this->Selector == i){std::cout << std::endl; this->SonList.at(i).Display(Depth + 1, (Def_Col & 0x0f) * 16 + (Def_Col & 0xf0) / 16, Real_Sel); Is_Line_Need = 1; }if (!Is_Line_Need)std::cout << std::endl; if (Is_Line_Need)Is_Line_Need = false; Col(); }}void CONSOLE::MainLoop(unsigned Def_Col, unsigned Real_Sel){ bool Insert{ true }; bool Cover{ false }; int* Action_Num{ &Locate()->Selector }; bool* Action_Bol{ &Locate()->Is_Selected }; size_t List_Size{ Locate()->SonList.size() }; while (1) {system("cls"); this->Display(); if (!Cover){Action_Num = &Locate()->Selector; Action_Bol = &Locate()->Is_Selected; List_Size = Locate()->SonList.size(); }elseCover = false; if (!Insert){Action_Num = &Locate(-1)->Selector; Action_Bol = &Locate(-1)->Is_Selected; List_Size = Locate(-1)->SonList.size(); Locate(-1)->Is_Selected = false; Insert = true; Cover = true; continue; }Insert = Insert_Action(Action_Num, Action_Bol, List_Size); }}bool CONSOLE::Insert_Action(int* Action_Num, bool* Action_Bol, size_t List_Size){ char key = _getch(); if (key == 'c' || key == 'C')//如果输入了大小写的C则返回上一级 {*Action_Bol = false; return false; } if (static_cast(key - 48) >= 0 && static_cast(key - 48) <= 9)//判断是否是从零到九的数字 {if (static_cast(key - 48) <= static_cast(List_Size))//如果是,且小于等于选项总数则直接指定这个选项*Action_Num = static_cast(key - 48) - 1; else*Action_Num = static_cast(List_Size) - 1; //如果超出了最大值,则指向最大值*Action_Bol = true; } else if (key == 'w' || key == 'W' || key == 72)//如果输入了大小写的W或者上箭头,则执行MoveUp*Action_Num = *Action_Num == 0 ? static_cast(List_Size) - 1 : -- * Action_Num; else if (key == 's' || key == 'S' || key == 80)//如果输入了大小写的S或者下箭头,则执行MoveDown*Action_Num = *Action_Num == static_cast(List_Size) - 1 ? 0 : ++ * Action_Num; else if (key == 'a' || key == 'A' || key == 75)//如果输入了大小写的A或者左箭头,则执行向上翻页*Action_Num = *Action_Num - static_cast(SSpace & 0x0000ff) < 0 ? 0 : *Action_Num - (SSpace & 0x0000ff); else if (key == 'd' || key == 'D' || key == 77)//如果输入了大小写的D或者右箭头,则执行向下翻页*Action_Num = *Action_Num + static_cast(SSpace & 0x0000ff) > static_cast(List_Size) - 1 ? static_cast(List_Size) - 1 : *Action_Num + (SSpace & 0x0000ff); else if (key == '\r')//回车确认*Action_Bol = true; return true; }CONSOLE* CONSOLE::Locate(int Target){ if (Target == 0) {for (int i = 0; i < SonList.size(); i++){if (i == Selector && Is_Selected == true)return SonList.at(i).Locate(); }return this; } else {for (int i = 0; i < SonList.size(); i++){if (i == Selector && Is_Selected == true && SonList.at(i).SonList.size() != 0)if (SonList.at(i).Is_Selected == false)return this; elsereturn SonList.at(i).Locate(-1); }return this; }}

        以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

          推荐阅读