当前位置 : 主页 > 编程语言 > c语言 >

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

来源:互联网 收集:自由互联 发布时间:2023-02-01
目录 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 TANX
目录
  • 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 <iostream>
        #endif
        
        #ifndef VECTOR//检查是否已经包含VECTOR
        #define VECTOR
        #include <vector>
        #endif
        
        #ifndef CONIO_H//检查是否已经包含CONIO_H
        #define CONIO_H
        #include <conio.h>
        #endif
        
        #ifndef IOMANIP//检查是否已经包含IOMANIP
        #define IOMANIP
        #include <iomanip>
        #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::vector<Function>SonList;
        };
        
        //第二级别的物品结构
        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::vector<Function>SonList;
        };
        
        //第一级别的主要物品类
        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::vector<Main_Function>SonList;
        	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);
        			else
        				Col(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);
        					else
        						Col(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<int>(key - 48) >= 0 && static_cast<int>(key - 48) <= 9)//判断是否是从零到九的数字
        	{
        		if (static_cast<int>(key - 48) <= List_Size)//如果是,且小于等于选项总数则直接指定这个选项
        			*Action_Num = static_cast<int>(key - 48) - 1;
        		else
        			*Action_Num = static_cast<int>(List_Size) - 1;//如果超出了最大值,则指向最大值
        		*Action_Bol = true;
        	}
        	else if (key == 'w' || key == 'W' || key == 72)//如果输入了大小写的W或者上箭头,则执行MoveUp函数
        		*Action_Num = *Action_Num == 0 ? static_cast<int>(List_Size) - 1 : -- * Action_Num;
        	else if (key == 's' || key == 'S' || key == 80)//如果输入了大小写的S或者下箭头,则执行MoveDown函数
        		*Action_Num = *Action_Num == static_cast<int>(List_Size) - 1 ? 0 : ++ * Action_Num;
        	else if (key == 'a' || key == 'A' || key == 75)//如果输入了大小写的A或者左箭头,则执行向上翻页函数
        		*Action_Num = *Action_Num - static_cast<int>(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<int>(List_Size) - 1 ? static_cast<int>(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();
        }

        TANXL_CONSOLE_LIST.H VERSION_1_5

        再次对几乎所有函数进行重写,为了操作的一致性移除了三级物品的设定,统一由类来进行管理。通过递归的方法实现输出列表,理论上能无限扩展深度。

        三级列表

        六级列表

        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 <iostream>
        #endif
        
        #ifndef VECTOR//检查是否已经包含VECTOR
        #define VECTOR
        #include <vector>
        #endif
        
        #ifndef CONIO_H//检查是否已经包含CONIO_H
        #define CONIO_H
        #include <conio.h>
        #endif
        
        #ifndef IOMANIP//检查是否已经包含IOMANIP
        #define IOMANIP
        #include <iomanip>
        #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::vector<CONSOLE>SonList;
        
        	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);
        		else
        			Col(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();
        		}
        		else
        			Cover = 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<int>(key - 48) >= 0 && static_cast<int>(key - 48) <= 9)//判断是否是从零到九的数字
        	{
        		if (static_cast<int>(key - 48) <= static_cast<int>(List_Size))//如果是,且小于等于选项总数则直接指定这个选项
        			*Action_Num = static_cast<int>(key - 48) - 1;
        		else
        			*Action_Num = static_cast<int>(List_Size) - 1;//如果超出了最大值,则指向最大值
        		*Action_Bol = true;
        	}
        	else if (key == 'w' || key == 'W' || key == 72)//如果输入了大小写的W或者上箭头,则执行MoveUp函数
        		*Action_Num = *Action_Num == 0 ? static_cast<int>(List_Size) - 1 : -- * Action_Num;
        	else if (key == 's' || key == 'S' || key == 80)//如果输入了大小写的S或者下箭头,则执行MoveDown函数
        		*Action_Num = *Action_Num == static_cast<int>(List_Size) - 1 ? 0 : ++ * Action_Num;
        	else if (key == 'a' || key == 'A' || key == 75)//如果输入了大小写的A或者左箭头,则执行向上翻页函数
        		*Action_Num = *Action_Num - static_cast<int>(SSpace & 0x0000ff) < 0 ? 0 : *Action_Num - (SSpace & 0x0000ff);
        	else if (key == 'd' || key == 'D' || key == 77)//如果输入了大小写的D或者右箭头,则执行向下翻页函数
        		*Action_Num = *Action_Num + static_cast<int>(SSpace & 0x0000ff) > static_cast<int>(List_Size) - 1 ? static_cast<int>(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;
        				else
        					return 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

        细节调整

        #ifndef TANXL_CONSOLE_LIST
        #define TANXL_CONSOLE_LIST
        
        #ifndef IOSTREAM//检查是否已经包含IOSTREAM
        #define IOSTREAM
        #include <iostream>
        #endif
        
        #ifndef VECTOR//检查是否已经包含VECTOR
        #define VECTOR
        #include <vector>
        #endif
        
        #ifndef CONIO_H//检查是否已经包含CONIO_H
        #define CONIO_H
        #include <conio.h>
        #endif
        
        #ifndef IOMANIP//检查是否已经包含IOMANIP
        #define IOMANIP
        #include <iomanip>
        #endif
        
        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 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::vector<CONSOLE>SonList;
        
        	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);
        		else
        			Col(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();
        		}
        		else
        			Cover = 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<int>(key - 48) >= 0 && static_cast<int>(key - 48) <= 9)//判断是否是从零到九的数字
        	{
        		if (static_cast<int>(key - 48) <= static_cast<int>(List_Size))//如果是,且小于等于选项总数则直接指定这个选项
        			*Action_Num = static_cast<int>(key - 48) - 1;
        		else
        			*Action_Num = static_cast<int>(List_Size) - 1;//如果超出了最大值,则指向最大值
        		*Action_Bol = true;
        	}
        	else if (key == 'w' || key == 'W' || key == 72)//如果输入了大小写的W或者上箭头,则执行MoveUp
        		*Action_Num = *Action_Num == 0 ? static_cast<int>(List_Size) - 1 : -- * Action_Num;
        	else if (key == 's' || key == 'S' || key == 80)//如果输入了大小写的S或者下箭头,则执行MoveDown
        		*Action_Num = *Action_Num == static_cast<int>(List_Size) - 1 ? 0 : ++ * Action_Num;
        	else if (key == 'a' || key == 'A' || key == 75)//如果输入了大小写的A或者左箭头,则执行向上翻页
        		*Action_Num = *Action_Num - static_cast<int>(SSpace & 0x0000ff) < 0 ? 0 : *Action_Num - (SSpace & 0x0000ff);
        	else if (key == 'd' || key == 'D' || key == 77)//如果输入了大小写的D或者右箭头,则执行向下翻页
        		*Action_Num = *Action_Num + static_cast<int>(SSpace & 0x0000ff) > static_cast<int>(List_Size) - 1 ? static_cast<int>(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;
        				else
        					return SonList.at(i).Locate(-1);
        		}
        		return this;
        	}
        }
        

        以上为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。

        上一篇:一文快速掌握C++双端数组容器deque的使用
        下一篇:没有了
        网友评论