C++控制台强化实现一定界面效果 V1.8

此版本已经过多次调试测试,后续大概率不会再进行更新,目前唯一能想到的改进方案是添加项目函数(Append_Item)的最后一个参数(Ids,这个参数用于指定当前添加物品的层级,是一个int类型的数组。例如[0,0]代表该物品为第一层第一个的子列表下的第二层第一个、[1,2]代表该物品为第一层第二个的子列表下的第二层第三个。),这个参数需要在函数外先初始化一个数组再作为入参使用,实际使用中可能需要初始化大量数组。

作为控制台简易界面效果的最后一个版本,此版本摒弃了之前巨量的设置与获取接口,仅向用户提供最基本的添加与显示接口,用户并不需要了解内部的实现原理,防止误用的同时也降低了使用的学习成本。

添加物品的参数 New_Item为此物品的显示名称,Space为选项和标题的空格数 AA-BB-CC AA左空格 BB右空格 CC页面物品限制数量。FunC为选定此物品后执行的函数。Depth为深度,Ids为深度对应的层级,例如[0,0]的Ids对应的就是两层深度[1,2,3,4]对应为四层深度,如深度与层级不一致可能导致未定义错误。

显示物品函数无任何参数,调用后会进入显示绘制的死循环,此项目的按键操作在代码中有详细介绍。

TANXL_CONSOLE_LIST.H VERSION_1_8

//_VERSION_1_8_ UPDATE LOG
// LAST_UPDATE 2023-01-05 16:44

#pragma once

#ifndef _TANXL_CONSOLE_LIST_
#define _TANXL_CONSOLE_LIST_

#include <iostream>
#include <vector>
#include <conio.h>
#include <iomanip>

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)() = nullptr);

	const std::string Get_Version();

	void Display_Once();

	void Append_Item(std::string New_Item, unsigned Space = 0x171109, void(*FunC)() = nullptr, int Depth = 0, int* Ids = nullptr);

private:
	void Display(int Depth = 0, unsigned Def_Col = FONT_COLOR_WHITE | BACK_COLOR_RED, unsigned Real_Sel = FONT_COLOR_WHITE | BACK_COLOR_PURPLE);

	bool Insert_Action(unsigned* Action_Num, bool* Action_Bol, size_t List_Size);

	CONSOLE* Locate(int Target = 0);

	std::string _Name;

	// _Selector 用于记录当前列表指向的选项序号
	unsigned _Selector;
	// _Page 用于记录当前指定的页面序号
	int _Page;
	// _Is_Selected 用于记录当前是否已选定此选项
	bool _Is_Selected;
	bool _Is_Funcwork;

	std::vector<CONSOLE> _SonList;

	void (*_Func)();

	unsigned _SSpace;// { 0x171109 }选项和标题的空格数 AA-BB-CC AA左空格 BB右空格 CC页面物品限制数量
	
	const std::string _Version{ "1.8" };
};

#endif

TANXL_CONSOLE_LIST.CPP VERSION_1_8

#pragma once

#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 == nullptr)
		this->_Is_Funcwork = false;
}

//添加函数
void CONSOLE::Append_Item(std::string New_Item, unsigned Space, void (*FunC)(), int Depth, int* Ids)
{
	if (Depth == 0)
		this->_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 };
	this->_Page = this->_Selector / (_SSpace & 0x00ff);
	for (int i = this->_Page * (_SSpace & 0x00ff); (i < _SonList.size()) && (i < (this->_Page + 1) * static_cast<int>(this->_SSpace & 0x00ff)); ++i)
	{
		for (int j{ Depth }; j > 0; j--)
			std::cout << "\t";
		if (i == this->_Selector)
			Col(Real_Sel);
		else
			Col(Def_Col);
		std::cout << std::setw((this->_SSpace & 0xff0000) >> 16) << this->_SonList.at(i)._Name << std::setw((this->_SSpace & 0x00ff00) >> 8) << " " << std::endl;
		Col();
		if ((this->_SonList.at(i)._SonList.size() == 0) && (this->_Is_Selected == true) && (this->_Selector == i))//在包含子项目为0时自动退出
		{
			if (this->_SonList.at(i)._Is_Funcwork)
				this->_SonList.at(i)._Func();
			this->_Is_Selected = false;
		}
		if ((this->_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) << 4) + ((Def_Col & 0xf0) >> 4), Real_Sel);
			Is_Line_Need = 1;
		}
		if (!Is_Line_Need)
			std::cout << std::endl;
		if (Is_Line_Need)
			Is_Line_Need = false;
		Col();
	}
}

const std::string CONSOLE::Get_Version()
{
	return this->_Version;
}

void CONSOLE::Display_Once()
{
	static bool Insert{ true };
	bool Cover{ false };
	unsigned* 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);
		break;
	}
}

bool CONSOLE::Insert_Action(unsigned* Action_Num, bool* Action_Bol, size_t List_Size)
{
	char key = _getch();
	if ((key == 'c') || (key == 'C'))//如果输入了大小写的C则返回上一级
	{
		*Action_Bol = false;
		return false;
	}
	if ((key >= 48) && (key <= 57))//判断是否是从零到九的数字 
	{//(static_cast<int>(key - 48) >= 0) && (static_cast<int>(key - 48) <= 9)
		if (key <= List_Size + 48)//如果是,且小于等于选项总数则直接指定这个选项
			*Action_Num = key - 49;
		else
			*Action_Num = static_cast<unsigned>(List_Size) - 1;//如果超出了最大值,则指向最大值
		*Action_Bol = true;
	}
	else if ((key == 'w') || (key == 'W') || (key == 72))//如果输入了大小写的W或者上箭头,则执行MoveUp
		*Action_Num = *Action_Num == 0 ? static_cast<unsigned>(List_Size) - 1 : -- * Action_Num;
	else if ((key == 's') || (key == 'S') || (key == 80))//如果输入了大小写的S或者下箭头,则执行MoveDown
		*Action_Num = *Action_Num == List_Size - 1 ? 0 : ++ * Action_Num;
	else if ((key == 'a') || (key == 'A') || (key == 75))//如果输入了大小写的A或者左箭头,则执行向上翻页
		*Action_Num = *Action_Num - (this->_SSpace & 0x0000ff) < 0 ? 0 : *Action_Num - (this->_SSpace & 0x0000ff);
	else if ((key == 'd') || (key == 'D') || (key == 77))//如果输入了大小写的D或者右箭头,则执行向下翻页
		*Action_Num = *Action_Num + (this->_SSpace & 0x0000ff) > static_cast<unsigned>(List_Size) - 1 ? static_cast<unsigned>(List_Size) - 1 : *Action_Num + (this->_SSpace & 0x0000ff);
	else if (key == '\r')//回车确认
		*Action_Bol = true;
	return true;
}

CONSOLE* CONSOLE::Locate(int Target)
{
	if (Target == 0)
	{
		for (int i{ 0 }; i < this->_SonList.size(); ++i)
		{
			if ((i == this->_Selector) && (this->_Is_Selected == true))
				return this->_SonList.at(i).Locate();
		}
		return this;
	}
	else
	{
		for (int i{ 0 }; i < _SonList.size(); ++i)
		{
			if ((i == this->_Selector) && (this->_Is_Selected == true) && (this->_SonList.at(i)._SonList.size() != 0))
				if (this->_SonList.at(i)._Is_Selected == false)
					return this;
				else
					return this->_SonList.at(i).Locate(-1);
		}
		return this;
	}
}

例程同之前的1.5版本。
C++控制台强化实现一定界面效果(简洁版)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WiChP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值