Windows C++控制台菜单库开发与源码展示

news2024/12/26 21:25:02

Windows C++控制台菜单库

  • 声明:
  • 演示视频:
  • 一、前言
  • 二、具体框架
  • 三、源码展示
    • console_screen_set.h
    • frame
      • console_screen_frame_base.h
      • console_screen_frame_char.h
      • console_screen_frame_wchar_t.h
      • console_screen_frame.h
    • menu
      • console_screen_menu_base.h
      • console_screen_menu_operate.h
      • console_screen_menu.h
    • text
      • console_screen_text_base.h
      • console_screen_text.h
  • 四、代码参考

声明:

开发环境为 VS2022 C++,菜单库源码(2200行左右)为本人独立制作,转载使用请标明出处,谢谢!

演示视频:

C++菜单库例子展示

一、前言

做控制台菜单的时候总感觉太耗时了,因为坐标不对需要修改,还要一个一个检查,以及颜色的处理。

具体操作可看这篇博客C语言伪图形与键盘操作加扫雷实例(写的太挫了),所以我想制作一个控制台菜单库,便于在菜单方面的快速开发。

二、具体框架

在这里插入图片描述
因为制作的时候是走一步看一步,导致设计十分冗余,后续有时间可能会更新调整。这里我列举一些里面的功能:

  1. set 包含常用的函数,例如光标移动、隐藏等等。
  2. menu(模板) 包含选项、框架、内置键盘操作、内置鼠标操作、打印、清除等等。
  3. text(模板) 包含打印、清除等等。

在使用宽字符(wchar_t)对应的类,如:wmenu、wtext、应该加上这一句:

	std::wcout.imbue(std::locale("zh_CN"));		

详细可参考 C++基础(十八)区域设置、locale、中文乱码、中文不输出 ,这里不赘述。

三、源码展示

console_screen_set.h

#pragma once

#include <CoreWindow.h>
#include <stdio.h>

namespace my
{
	inline void SetPos(int x, int y)
	{
		COORD pos = { x, y };
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
	}

	inline void HideCursor()
	{
		CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
		SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
	}

	inline void SetWordSize(int SizeX, int SizeY)
	{
		CONSOLE_FONT_INFOEX font_infoex;
		COORD pos = { SizeX, SizeY };
		font_infoex.cbSize = sizeof(CONSOLE_FONT_INFOEX);
		font_infoex.dwFontSize = pos;
		SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), false, &font_infoex);
	}

	inline void FlushBuffer()
	{
		FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
	}

	inline void SetScreenSize(short consoleWide, short consoleHigh)
	{
		char cmd[100];
		sprintf_s(cmd, "mode con cols=%d lines=%d", consoleWide, consoleHigh);
		system(cmd);
	}

	inline void GetMouseOperate()
	{
		if (!SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_EXTENDED_FLAGS | ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT))
		{
			fprintf(stderr, "%s\n", "SetConsoleMode");
		}
	}
}

frame

console_screen_frame_base.h

#pragma once

#include <CoreWindow.h>
#include <cassert>

namespace my
{
	template<class T>
	class console_screen_frame_base
	{
		template<class Type, class CH, class STRING>
		friend class console_screen_frame;

		template<class PFUNC, class MENU, class FRAME, class CHAR, class STRING>
		friend class console_screen_menu;

		template<class TEXTCHAR, class FRAME, class STRING, class CHAR>
		friend class console_screen_text;

	public:

		console_screen_frame_base(int x = 0, int y = 0, int high = 5, int wide = 10,
			T up = 0, T down = 0, T left = 0, T right = 0,
			T top_left = 0, T bottom_left = 0, T top_right = 0, T bottom_right = 0)
			:_x(x)
			, _y(y)
			, _high(high)
			, _wide(wide)
			, _up(up)
			, _down(down)
			, _left(left)
			, _right(right)
			, _top_left(top_left)
			, _bottom_left(bottom_left)
			, _top_right(top_right)
			, _bottom_right(bottom_right)
		{
			assert(x >= 0 && y >= 0);
			assert(high >= 0 && wide >= 0);
		}

		void changePos(int x, int y)
		{
			assert(x >= 0 && y >= 0);

			_x = x;
			_y = y;
		}

		void changeFrameSize(int high, int wide)
		{
			assert(high >= 0 && wide >= 0);

			_high = high;
			_wide = wide;
		}

		void changeSide(T up = 0, T down = 0, T left = 0, T right = 0)
		{
			_up = up == 0 ? _up : up;
			_down = down == 0 ? _down : down;
			_left = left == 0 ? _left : left;
			_right = right == 0 ? _right : right;
		}

		void changeCorner(T top_left = 0, T bottom_left = 0, T top_right = 0, T bottom_right = 0)
		{
			_top_left = top_left == 0 ? _top_left : top_left;
			_bottom_left = bottom_left == 0 ? _bottom_left : bottom_left;
			_top_right = top_right == 0 ? _top_right : top_right;
			_bottom_right = bottom_right == 0 ? _bottom_right : bottom_right;
		}

		void changeUp(T up)
		{
			_up = up;
		}

		void changeDown(T down)
		{
			_down = down;
		}

		void changeLeft(T left)
		{
			_left = left;
		}

		void changeRight(T right)
		{
			_right = right;
		}

		void changeTopLeft(T top_left)
		{
			_top_left = top_left;
		}

		void changeTopRight(T top_right)
		{
			_top_right = top_right;
		}

		void changeBottomLeft(T bottom_left)
		{
			_bottom_left = bottom_left;
		}

		void changeBottomRight(T bottom_right)
		{
			_bottom_right = bottom_right;
		}

	protected:

		void printFrame()
		{
			if (_up != 0)
			{
				printCharUp();
			}
			if (_down != 0)
			{
				printCharDown();
			}
			if (_left != 0)
			{
				printCharLeft();
			}
			if (_right != 0)
			{
				printCharRight();
			}
			if (_top_left != 0 ||
				_top_right != 0 ||
				_bottom_left != 0 ||
				_bottom_right != 0)
			{
				printCharCorner();
			}
		}

		virtual void printCharUp() = 0;

		virtual void printCharDown() = 0;

		virtual void printCharLeft() = 0;

		virtual void printCharRight() = 0;

		virtual void printCharCorner() = 0;

		void cleanFrame()
		{
			if (_up != 0)
			{
				cleanCharUp();
			}
			if (_down != 0)
			{
				cleanCharDown();
			}
			if (_left != 0)
			{
				cleanCharLeft();
			}
			if (_right != 0)
			{
				cleanCharRight();
			}
			if (_top_left != 0 ||
				_top_right != 0 ||
				_bottom_left != 0 ||
				_bottom_right != 0)
			{
				cleanCharCorner();
			}
		}

		virtual void cleanCharUp() = 0;

		virtual void cleanCharDown() = 0;

		virtual void cleanCharLeft() = 0;

		virtual void cleanCharRight() = 0;

		virtual void cleanCharCorner() = 0;

	protected:

		short _x;
		short _y;

		short _high;
		short _wide;

		T _up;
		T _down;
		T _left;
		T _right;

		T _top_left = 0;
		T _bottom_left = 0;
		T _top_right = 0;
		T _bottom_right = 0;
	};
}

console_screen_frame_char.h

#pragma once

#include "console_screen_frame_base.h"
#include "console_screen_set.h"
#include <iostream>

namespace my
{
	extern void SetPos(int x, int y);

	class console_screen_frame_char : public console_screen_frame_base<signed char>
	{
	public:

		console_screen_frame_char(int x, int y, int high, int wide,
			signed char up = 0, signed char down = 0,
			signed char left = 0, signed char right = 0,
			signed char top_left = 0, signed char bottom_left = 0,
			signed char top_right = 0, signed char bottom_right = 0)
			:console_screen_frame_base(x, y, high, wide, up, down, left, right,
				top_left, bottom_left, top_right, bottom_right)
		{
			;
		}

		void show()
		{
			printFrame();
		}

		void clean()
		{
			cleanFrame();
		}

	protected:

		void printCharUp()
		{
			SetPos(_x + 1, _y);
			for (int wide = 1; wide <= _wide - 2; ++wide)
			{
				std::cout << _up;
			}
		}

		void printCharDown()
		{
			SetPos(_x + 1, _y + _high - 1);
			for (int wide = 1; wide <= _wide - 2; ++wide)
			{
				std::cout << _down;
			}
		}

		void printCharLeft()
		{
			for (int high = 1; high <= _high - 2; ++high)
			{
				SetPos(_x, _y + high);

				std::cout << _left;
			}
		}

		void printCharRight()
		{
			for (int high = 1; high <= _high - 2; ++high)
			{
				SetPos(_x + _wide - 1, _y + high);

				std::cout << _right;
			}
		}

		void printCharCorner()
		{
			SetPos(_x, _y);
			std::cout << _top_left;

			SetPos(_x + _wide - 1, _y);
			std::cout << _top_right;

			SetPos(_x, _y + _high - 1);
			std::cout << _bottom_left;

			SetPos(_x + _wide - 1, _y + _high - 1);
			std::cout << _bottom_right;
		}

		void cleanCharUp()
		{
			signed char temp = _up;
			_up = ' ';
			printCharUp();
			_up = temp;
		}

		void cleanCharDown()
		{
			signed char temp = _down;
			_down = ' ';
			printCharDown();
			_down = temp;
		}

		void cleanCharLeft()
		{
			signed char temp = _left;
			_left = ' ';
			printCharLeft();
			_left = temp;
		}

		void cleanCharRight()
		{
			signed char temp = _right;
			_right = ' ';
			printCharRight();
			_right = temp;
		}

		void cleanCharCorner()
		{
			signed char temp1 = _top_left;
			signed char temp2 = _bottom_left;
			signed char temp3 = _top_right;
			signed char temp4 = _bottom_right;

			changeCorner(' ', ' ', ' ', ' ');
			printCharCorner();
			changeCorner(temp1, temp2, temp3, temp4);
		}
	};
}

console_screen_frame_wchar_t.h

#pragma once

#include "console_screen_frame_base.h"
#include "console_screen_set.h"
#include <iostream>

namespace my
{
	class console_screen_frame_wchar_t : public console_screen_frame_base<wchar_t>
	{
	public:

		console_screen_frame_wchar_t(int x, int y, int high, int wide,
			wchar_t up = 0, wchar_t down = 0,
			wchar_t left = 0, wchar_t right = 0,
			wchar_t top_left = 0, wchar_t bottom_left = 0,
			wchar_t top_right = 0, wchar_t bottom_right = 0)
			:console_screen_frame_base(x, y, high, wide, up, down, left, right,
				top_left, bottom_left, top_right, bottom_right)
		{
			;
		}

		void show()
		{
			printFrame();
		}

		void clean()
		{
			cleanFrame();
		}

	protected:

		void printCharUp()
		{
			for (int wide = 0; wide <= _wide - 6; wide += 2)
			{
				SetPos(_x + 2 + wide, _y);
				std::wcout << _up;
			}
		}

		void printCharDown()
		{
			for (int wide = 0; wide <= _wide - 6; wide += 2)
			{
				SetPos(_x + 2 + wide, _y + _high - 1);
				std::wcout << _down;
			}
		}

		void printCharLeft()
		{
			for (int high = 1; high <= _high - 2; ++high)
			{
				SetPos(_x, _y + high);

				std::wcout << _left;
			}
		}

		void printCharRight()
		{
			for (int high = 1; high <= _high - 2; ++high)
			{
				SetPos(_x + _wide - 2, _y + high);

				std::wcout << _right;
			}
		}

		void printCharCorner()
		{
			SetPos(_x, _y);
			std::wcout << _top_left;

			SetPos(_x + _wide - 2, _y);
			std::wcout << _top_right;

			SetPos(_x, _y + _high - 1);
			std::wcout << _bottom_left;

			SetPos(_x + _wide - 2, _y + _high - 1);
			std::wcout << _bottom_right;
		}

		void cleanCharUp()
		{
			SetPos(_x + 2, _y);
			for (int wide = 0; wide <= _wide - 4; ++wide)
			{
				std::cout << ' ';
			}
		}

		void cleanCharDown()
		{
			SetPos(_x + 2, _y + _high - 1);
			for (int wide = 0; wide <= _wide - 4; ++wide)
			{
				std::cout << ' ';
			}
		}

		void cleanCharLeft()
		{
			for (int high = 1; high <= _high - 2; ++high)
			{
				SetPos(_x, _y + high);

				std::cout << ' ' << ' ';
			}
		}

		void cleanCharRight()
		{
			for (int high = 1; high <= _high - 2; ++high)
			{
				SetPos(_x + _wide - 2, _y + high);

				std::cout << ' ' << ' ';
			}
		}

		void cleanCharCorner()
		{
			SetPos(_x, _y);
			std::cout << ' ' << ' ';

			SetPos(_x + _wide - 2, _y);
			std::cout << ' ' << ' ';

			SetPos(_x, _y + _high - 1);
			std::cout << ' ' << ' ';

			SetPos(_x + _wide - 2, _y + _high - 1);
			std::cout << ' ' << ' ';
		}
	};
}


console_screen_frame.h

#pragma once

#include "console_screen_frame_char.h"
#include "console_screen_frame_wchar_t.h"
#include <vector>
#include <utility>

namespace my
{
	enum FRAME_DIRECTION
	{
		Up = 0,
		Down,
		Left,
		Right
	};

	template<class T, class CH, class STRING>
	class console_screen_frame
	{
		template<class PFUNC, class MENU, class FRAME, class CHAR, class STRING>
		friend class console_screen_menu;

		template<class TEXTCHAR, class FRAME, class STRING, class CHAR>
		friend class console_screen_text;

	public:

		console_screen_frame(int x, int y, int high, int wide,
			CH up = 0, CH down = 0, CH left = 0, CH right = 0,
			CH top_left = 0, CH bottom_left = 0, CH top_right = 0, CH bottom_right = 0)
			:_the_char(x, y, high, wide, up, down, left, right
				, top_left, bottom_left, top_right, bottom_right)
		{
			;
		}

		void setPos(int x, int y)
		{
			_the_char.changePos(x, y);
		}

		void setFrameSize(int high, int wide)
		{
			_the_char.changeFrameSize(high, wide);
		}

		void setSide(CH up = 0, CH down = 0, CH left = 0, CH right = 0)
		{
			_the_char.changeSide(up, down, left, right);
		}

		void setCorner(CH top_left = 0, CH bottom_left = 0,
			CH top_right = 0, CH bottom_right = 0)
		{
			_the_char.changeCorner(top_left, bottom_left, top_right, bottom_right);
		}

		void setUp(CH up)
		{
			_the_char.changeUp(up);
		}

		void setDown(CH down)
		{
			_the_char.changeDown(down);
		}

		void setLeft(CH left)
		{
			_the_char.changeLeft(left);
		}

		void setRight(CH right)
		{
			_the_char.changeRight(right);
		}

		void setTopLeft(CH top_left)
		{
			_the_char.changeTopLeft(top_left);
		}

		void setTopRight(CH top_right)
		{
			_the_char.changeTopRight(top_right);
		}

		void setBottomLeft(CH bottom_left)
		{
			_the_char.changeBottomLeft(bottom_left);
		}

		void setBottomRight(CH bottom_right)
		{
			_the_char.changeBottomRight(bottom_right);
		}

		void frameShow()
		{
			_the_char.show();

			if (sizeof(CH) == sizeof(signed char))
			{
				wordShow((void(*)(STRING))&getCout, (void(*)(CH))&getCoutC);
			}
			else
			{
				wordShow((void(*)(STRING))&getWcout, (void(*)(CH))&getWcoutC);
			}
		}

		void frameClean()
		{
			_the_char.clean();
		}

		void numWord(int number)
		{
			_word.resize(number);
			_word_space.resize(number);
		}

		void setWord(int pos, STRING str1, signed char direction, short distance)
		{
			assert(pos >= 0 && pos < _word.size());

			_word[pos] = str1;
			_word_space[pos] = { direction, distance };
		}

		void recallWord(int pos)
		{
			assert(pos >= 0 && pos < _word.size());

			_word.erase(_word.begin() + pos);
			_word_space.erase(_word_space.begin() + pos);
		}

	protected:

		void wordShow(void(*outfuncString)(STRING), void(*outfuncChar)(CH))
		{
			for (int i = 0; i < _word.size(); ++i)
			{
				if (_the_char._up != 0 && _word_space[i].first == Up)
				{
					SetPos(_the_char._x + _word_space[i].second, _the_char._y);

					if (_word[i] == nullptr)
					{
						continue;
					}

					outfuncString(_word[i]);
				}
				else if (_the_char._down != 0 && _word_space[i].first == Down)
				{
					SetPos(_the_char._x + _word_space[i].second, _the_char._y + _the_char._high - 1);

					if (_word[i] == nullptr)
					{
						continue;
					}

					outfuncString(_word[i]);
				}
				else if (_the_char._left != 0 && _word_space[i].first == Left)
				{
					int len = clen(_word[i]);
					for (int j = 0; j < len; ++j)
					{
						SetPos(_the_char._x, _the_char._y + _word_space[i].second + j);

						if (_word[i] == nullptr)
						{
							continue;
						}

						outfuncChar(_word[i][j]);
					}
				}
				else if (_the_char._right != 0 && _word_space[i].first == Right)
				{
					int len = clen(_word[i]);
					for (int j = 0; j < len; ++j)
					{
						SetPos(_the_char._x + _the_char._wide - sizeof(CH), _the_char._y + _word_space[i].second + j);

						if (_word[i] == nullptr)
						{
							continue;
						}

						outfuncChar(_word[i][j]);
					}
				}
			}
		}

		static void getWcout(STRING str1)
		{
			std::wcout << str1;
		}

		static void getCout(STRING str1)
		{
			std::cout << str1;
		}

		static void getWcoutC(CH ch)
		{
			std::wcout << ch;
		}

		static void getCoutC(CH ch)
		{
			std::cout << ch;
		}

	protected:

		std::vector<STRING> _word;								// 嵌入词
		std::vector<std::pair<signed char, short>> _word_space;	// 嵌入词位置

		T _the_char;

		typedef size_t(*p_T_char)(STRING);

		p_T_char clen = sizeof(CH) == sizeof(signed char) ? (p_T_char)&strlen : (p_T_char)&wcslen;
	};

	typedef console_screen_frame<console_screen_frame_char, signed char, const char*> frame;

	typedef console_screen_frame<console_screen_frame_wchar_t, wchar_t, const wchar_t*> wframe;

}



menu

console_screen_menu_base.h

#pragma once

#include "console_screen_set.h"
#include <iostream>
#include <string>
#include <vector>
#include <cassert>
#include <Windows.h>
#include <utility>

namespace my
{
	template<class T>
	static T Max(T a, T b)
	{
		return a > b ? a : b;
	}

	typedef enum CONSOLE_SCREEN_COLOR
	{
		CBlack = 0,
		CBlue,
		CGreen,
		CLight_blue,
		CRed,
		CPurple,
		CYellow,
		CWhite,
		BBlack = 0,
		BBlue = 0x10,
		BGreen = 0x20,
		BLight_blue = 0x30,
		BRed = 0x40,
		BPurple = 0x50,
		BYellow = 0x60,
		BWhite = 0x70
	} the_color;

	class console_screen_menu_base
	{
	public:

		console_screen_menu_base(int x, int y, int rowNum = 1, int colNum = 1, int high = 1, int wide = 1)
			:_x(x), _y(y), _high(high), _wide(wide), _rowNum(rowNum), _colNum(colNum)
			, _option(rowNum, std::vector<std::string>(colNum, std::string("nullptr")))
			, _char_space(rowNum, std::vector<std::pair<short, short>>(colNum, { 1, 1 }))
			, _char_color(rowNum, std::vector<std::pair<short, bool>>(colNum, { CWhite, 0 }))
			, _background_space(rowNum, std::vector<std::pair<short, short>>(colNum, { 0, 0 }))
			, _background_color(rowNum, std::vector<std::pair<short, bool>>(colNum, { BBlack, 0 }))
		{
			assert(rowNum >= 1 && colNum >= 1);
			assert(x >= 0 && y >= 0);
			assert(high >= 0 && wide >= 0);
		}

		const std::string& getOption(int rowPos, int colPos)
		{
			assert(rowPos >= 1 && colPos >= 1);

			return _option[rowPos - 1][colPos - 1];
		}

		void setOption(int rowPos, int colPos, const std::string& str1,
			short front = 1, short back = 1)
		{
			assert(rowPos >= 1 && colPos >= 1);
			assert(front >= 0 && back >= 0);
			assert(rowPos <= _rowNum && colPos <= _colNum);

			_option[rowPos - 1][colPos - 1] = str1;
			_char_space[rowPos - 1][colPos - 1] = { front, back };
		}

		void setColor(int rowPos, int colPos, int charColor, bool charStrength, int backgroundColor = 0, bool backgroundStrength = false)
		{
			char_color(rowPos, colPos, charColor, charStrength);
			background_color(rowPos, colPos, backgroundColor, backgroundStrength);
		}

		void setCharColor(int rowPos, int colPos, int colorNum, bool strength = false)
		{
			char_color(rowPos, colPos, colorNum, strength);
		}

		void setBackgroundColor(int rowPos, int colPos, int colorNum, bool strength = false)
		{
			background_color(rowPos, colPos, colorNum, strength);
		}

		void setCharSpace(int rowPos, int colPos, int front, int back)
		{
			assert(rowPos >= 1 && colPos >= 1);

			_char_space[rowPos - 1][colPos - 1] = { front, back };
		}

		void setBackgroundSpace(int rowPos, int colPos, int front, int back)
		{
			assert(rowPos >= 1 && colPos >= 1);

			_background_space[rowPos - 1][colPos - 1] = { front, back };
		}

		void setRowSpace(int row)
		{
			assert(row >= 0);

			_row_space = row;
		}

		void setPos(int x, int y)
		{
			assert(x >= 0 && y >= 0);

			_x = x;
			_y = y;
		}

		void show()
		{
			show_or_clean_ready(true);
		}

		void clean()
		{
			show_or_clean_ready(false);
		}

	protected:

		void char_color(int rowPos, int colPos, int colorNum, bool strength)
		{
			assert(CBlack <= colorNum && colorNum <= CWhite);

			_char_color[rowPos - 1][colPos - 1] = { colorNum, strength };
		}

		void background_color(int rowPos, int colPos, int colorNum, bool strength)
		{
			assert(BBlack <= colorNum && colorNum <= BWhite);

			_background_color[rowPos - 1][colPos - 1] = { colorNum, strength };
		}

		void clean_ready(int i, int j, int x, int y)
		{
			int len1 = _option[i][j].size();
			
			if (_background_space[i][j].first > 0)
			{
				len1 += _background_space[i][j].first;
			}
			if (_background_space[i][j].second > 0)
			{
				len1 += _background_space[i][j].second;
			}

			// 补丁:正序打印会影响宽字体,逆向可解决
			for (int i = len1 - 1; i >= 0; --i)
			{
				SetPos(x + i, y);

				std::cout << ' ';
			}
		}

		void show_ready(int i, int j)
		{
			int charStrength = 0;
			int backgroundStrength = 0;
			if (_background_color[i][j].second == true)
			{
				backgroundStrength = BACKGROUND_INTENSITY;
			}
			if (_char_color[i][j].second == true)
			{
				charStrength = FOREGROUND_INTENSITY;
			}

			if (_background_space[i][j].first > 0)
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _background_color[i][j].first | backgroundStrength);
				std::cout << std::string(_background_space[i][j].first, ' ');
			}

			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _char_color[i][j].first | charStrength | _background_color[i][j].first | backgroundStrength);
			std::cout << _option[i][j];

			if (_background_space[i][j].second > 0)
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _background_color[i][j].first | backgroundStrength);
				std::cout << std::string(_background_space[i][j].second, ' ');
			}

			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), CWhite | BBlack);
		}

		void show_or_clean_ready(bool option)
		{
			int countPosY = 0;
			for (int i = 0; i < _rowNum; ++i)
			{
				if (i != 0)
				{
					countPosY += _row_space;
				}

				int countPosX = 0;
				for (int j = 0; j < _colNum; ++j)
				{
					int front = _char_space[i][j].first;

					if (j != 0)
					{
						countPosX += _option[i][j - 1].size();
						countPosX += _char_space[i][j - 1].first + _background_space[i][j - 1].first;
						countPosX += _background_space[i][j - 1].second + _char_space[i][j - 1].second;
					}

					SetPos(_x + front + countPosX, _y + i + countPosY);

					if (option == true)
					{
						show_ready(i, j);
					}
					else
					{
						clean_ready(i, j, _x + front + countPosX, _y + i + countPosY);
					}
				}
			}
		}

	protected:

		std::vector<std::vector<std::string>> _option;							// 选项
		//std::vector<std::vector<const char*>> _option;

		std::vector<std::vector<std::pair<short, short>>> _char_space;			// 字符间距
		std::vector<std::vector<std::pair<short, bool>>> _char_color;			// 字符 颜色 与 颜色加强

		std::vector<std::vector<std::pair<short, short>>> _background_space;	// 背景间距
		std::vector<std::vector<std::pair<short, bool>>> _background_color;		// 背景 颜色 与 颜色加强

		short _x;
		short _y;

		short _high;
		short _wide;

		//short _rowNum = 1;
		//short _colNum = 1;
		int _rowNum = 1;
		int _colNum = 1;

		signed char _row_space = 0;			// 行距

	};
}

console_screen_menu_operate.h

#pragma once

#include "console_screen_set.h"
#include <iostream>
#include <string>
#include <vector>
#include <cassert>
#include <Windows.h>
#include <utility>

namespace my
{
	template<class T>
	static T Max(T a, T b)
	{
		return a > b ? a : b;
	}

	typedef enum CONSOLE_SCREEN_COLOR
	{
		CBlack = 0,
		CBlue,
		CGreen,
		CLight_blue,
		CRed,
		CPurple,
		CYellow,
		CWhite,
		BBlack = 0,
		BBlue = 0x10,
		BGreen = 0x20,
		BLight_blue = 0x30,
		BRed = 0x40,
		BPurple = 0x50,
		BYellow = 0x60,
		BWhite = 0x70
	} the_color;

	class console_screen_menu_base
	{
	public:

		console_screen_menu_base(int x, int y, int rowNum = 1, int colNum = 1, int high = 1, int wide = 1)
			:_x(x), _y(y), _high(high), _wide(wide), _rowNum(rowNum), _colNum(colNum)
			, _option(rowNum, std::vector<std::string>(colNum, std::string("nullptr")))
			, _char_space(rowNum, std::vector<std::pair<short, short>>(colNum, { 1, 1 }))
			, _char_color(rowNum, std::vector<std::pair<short, bool>>(colNum, { CWhite, 0 }))
			, _background_space(rowNum, std::vector<std::pair<short, short>>(colNum, { 0, 0 }))
			, _background_color(rowNum, std::vector<std::pair<short, bool>>(colNum, { BBlack, 0 }))
		{
			assert(rowNum >= 1 && colNum >= 1);
			assert(x >= 0 && y >= 0);
			assert(high >= 0 && wide >= 0);
		}

		const std::string& getOption(int rowPos, int colPos)
		{
			assert(rowPos >= 1 && colPos >= 1);

			return _option[rowPos - 1][colPos - 1];
		}

		void setOption(int rowPos, int colPos, const std::string& str1,
			short front = 1, short back = 1)
		{
			assert(rowPos >= 1 && colPos >= 1);
			assert(front >= 0 && back >= 0);
			assert(rowPos <= _rowNum && colPos <= _colNum);

			_option[rowPos - 1][colPos - 1] = str1;
			_char_space[rowPos - 1][colPos - 1] = { front, back };
		}

		void setColor(int rowPos, int colPos, int charColor, bool charStrength, int backgroundColor = 0, bool backgroundStrength = false)
		{
			char_color(rowPos, colPos, charColor, charStrength);
			background_color(rowPos, colPos, backgroundColor, backgroundStrength);
		}

		void setCharColor(int rowPos, int colPos, int colorNum, bool strength = false)
		{
			char_color(rowPos, colPos, colorNum, strength);
		}

		void setBackgroundColor(int rowPos, int colPos, int colorNum, bool strength = false)
		{
			background_color(rowPos, colPos, colorNum, strength);
		}

		void setCharSpace(int rowPos, int colPos, int front, int back)
		{
			assert(rowPos >= 1 && colPos >= 1);

			_char_space[rowPos - 1][colPos - 1] = { front, back };
		}

		void setBackgroundSpace(int rowPos, int colPos, int front, int back)
		{
			assert(rowPos >= 1 && colPos >= 1);

			_background_space[rowPos - 1][colPos - 1] = { front, back };
		}

		void setRowSpace(int row)
		{
			assert(row >= 0);

			_row_space = row;
		}

		void setPos(int x, int y)
		{
			assert(x >= 0 && y >= 0);

			_x = x;
			_y = y;
		}

		void show()
		{
			show_or_clean_ready(true);
		}

		void clean()
		{
			show_or_clean_ready(false);
		}

	protected:

		void char_color(int rowPos, int colPos, int colorNum, bool strength)
		{
			assert(CBlack <= colorNum && colorNum <= CWhite);

			_char_color[rowPos - 1][colPos - 1] = { colorNum, strength };
		}

		void background_color(int rowPos, int colPos, int colorNum, bool strength)
		{
			assert(BBlack <= colorNum && colorNum <= BWhite);

			_background_color[rowPos - 1][colPos - 1] = { colorNum, strength };
		}

		void clean_ready(int i, int j, int x, int y)
		{
			int len1 = _option[i][j].size();
			
			if (_background_space[i][j].first > 0)
			{
				len1 += _background_space[i][j].first;
			}
			if (_background_space[i][j].second > 0)
			{
				len1 += _background_space[i][j].second;
			}

			// 补丁:正序打印会影响宽字体,逆向可解决
			for (int i = len1 - 1; i >= 0; --i)
			{
				SetPos(x + i, y);

				std::cout << ' ';
			}
		}

		void show_ready(int i, int j)
		{
			int charStrength = 0;
			int backgroundStrength = 0;
			if (_background_color[i][j].second == true)
			{
				backgroundStrength = BACKGROUND_INTENSITY;
			}
			if (_char_color[i][j].second == true)
			{
				charStrength = FOREGROUND_INTENSITY;
			}

			if (_background_space[i][j].first > 0)
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _background_color[i][j].first | backgroundStrength);
				std::cout << std::string(_background_space[i][j].first, ' ');
			}

			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _char_color[i][j].first | charStrength | _background_color[i][j].first | backgroundStrength);
			std::cout << _option[i][j];

			if (_background_space[i][j].second > 0)
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _background_color[i][j].first | backgroundStrength);
				std::cout << std::string(_background_space[i][j].second, ' ');
			}

			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), CWhite | BBlack);
		}

		void show_or_clean_ready(bool option)
		{
			int countPosY = 0;
			for (int i = 0; i < _rowNum; ++i)
			{
				if (i != 0)
				{
					countPosY += _row_space;
				}

				int countPosX = 0;
				for (int j = 0; j < _colNum; ++j)
				{
					int front = _char_space[i][j].first;

					if (j != 0)
					{
						countPosX += _option[i][j - 1].size();
						countPosX += _char_space[i][j - 1].first + _background_space[i][j - 1].first;
						countPosX += _background_space[i][j - 1].second + _char_space[i][j - 1].second;
					}

					SetPos(_x + front + countPosX, _y + i + countPosY);

					if (option == true)
					{
						show_ready(i, j);
					}
					else
					{
						clean_ready(i, j, _x + front + countPosX, _y + i + countPosY);
					}
				}
			}
		}

	protected:

		std::vector<std::vector<std::string>> _option;							// 选项
		//std::vector<std::vector<const char*>> _option;

		std::vector<std::vector<std::pair<short, short>>> _char_space;			// 字符间距
		std::vector<std::vector<std::pair<short, bool>>> _char_color;			// 字符 颜色 与 颜色加强

		std::vector<std::vector<std::pair<short, short>>> _background_space;	// 背景间距
		std::vector<std::vector<std::pair<short, bool>>> _background_color;		// 背景 颜色 与 颜色加强

		short _x;
		short _y;

		short _high;
		short _wide;

		//short _rowNum = 1;
		//short _colNum = 1;
		int _rowNum = 1;
		int _colNum = 1;

		signed char _row_space = 0;			// 行距

	};
}

console_screen_menu.h

#pragma once

#include "console_screen_frame.h"
#include "console_screen_menu_operate.h"

namespace my
{
	typedef enum console_screen_menu_operate_way
	{
		keyboard = 1,
		mouse,
	} way;

	template<class PFUNC = int(*)()
	,class MENU = console_screen_menu_operate<PFUNC>
	, class FRAME = frame
	, class CHAR = signed char
	, class STRING = const char*>
	class console_screen_menu
	{
	public:

		console_screen_menu(int x = 0, int y = 0, int high = 10, int wide = 20, int rowNum = 1, int colNum = 1, bool operate_switch = false)
			:_frame(x, y, high, wide)
			,_menu(x, y, operate_switch, rowNum, colNum, high, wide)
		{
			;
		}

	public:	// 自定义操作准备

		template<class T1, class T2, class T3, class T4>
		int operateCustom(int (*customize)(T1&, T2&, T3&, T4&), T2& fun1, T3& fun2, T4& fun3)
		{
			return customize(*this, fun1, fun2, fun3);
		}

		template<class T1, class T2, class T3>
		int operateCustom(int (*customize)(T1&, T2&, T3&), T2& fun1, T3& fun2)
		{
			return customize(*this, fun1, fun2);
		}

		template<class T1, class T2>
		int operateCustom(int (*customize)(T1&, T2&), T2& fun1)
		{
			return customize(*this, fun1);
		}

		template<class T>
		int operateCustom(int (*customize)(T&))
		{
			return customize(*this);
		}

		void customSetMenuCharColor(int rowPos, int colPos, int colorNum, bool strength = false)
		{
			_menu.setCharColor(rowPos, colPos, colorNum, strength);
		}

		const std::string& customGetMenuOption(int rowPos, int colPos)
		{
			return _menu.getOption(rowPos, colPos);
		}

		void customSetMenuOption(int rowPos, int colPos, const std::string& str1, short front = 0, short back = 0)
		{
			setMenuOption(rowPos, colPos, str1, front, back);
		}

		void customMouseAndOptionAc(int posX, int posY)
		{
			_menu.mouseAndOptionAc(posX, posY);
		}

		THE_POS customGetMouseCheckAlgorithm(int mouseX, int mouseY)
		{
			return _menu.mouseAndOptionDockingAlgorithm(mouseX, mouseY);
		}

		void customGetMouseOperate()
		{
			_menu.getMouseOperate();
		}

		void customOperateClean()
		{
			_menu.operateClean();
		}

		int customGetSleepTime()
		{
			return _menu._sleep_time;
		}

		PFUNC customGetOptionButton(int cursorX, int cursorY)
		{
			assert(cursorX >= 0 && cursorX < _menu._colNum);
			assert(cursorY >= 0 && cursorY < _menu._rowNum);

			return _menu._the_way[cursorY][cursorX];
		}

		int customGetCursorColNum()
		{
			return _menu._colNum;
		}

		int customGetCursorX()
		{
			return _menu._cursorPosX;
		}

		void customSetCursorX(int cursorX)
		{
			_menu.cursorXReset(cursorX);
		}

		int customGetCursorRowNum()
		{
			return _menu._rowNum;
		}

		int customGetCursorY()
		{
			return _menu._cursorPosY;
		}

		//short customGetOptionRowNum()
		//{
		//	return _menu._rowNum;
		//}

		//short customGetOptionY()
		//{
		//	return _menu._cursorPosY;
		//}

		void customSetCursorY(int cursorY)
		{
			_menu.cursorYReset(cursorY);
		}

		void customSetCursorPos(int cursorX, int cursorY)
		{
			_menu.cursorReset(cursorX, cursorY);
		}

		void customOperateShow()
		{
			_menu.operateShow();
		}

		bool customMenuCheckOperate()
		{
			return _menu._open_operate;
		}

	public:	// 静态准备

		void staticInit(bool yes = true)
		{
			_staticInit = yes;
		}

		bool alreadyStaticInit()
		{
			return _staticInit;
		}

	public:	// 有关菜单与框架

		void setPosCompare(short x, short y)
		{
			assert(x >= 0);
			assert(y >= 0);

			_compare_x = x;
			_compare_y = y;

			_menu.setPos(_menu._x + x, _menu._y + y);
		}

		void setAndCheckPos(int x, int y)
		{
			_frame.setPos(x, y);

			_menu.setPos(x, y);

			checkPosFrameWithMenu();
		}

		void show()
		{
			_menu.show();
			_frame.frameShow();
		}

		void clean()
		{
			_menu.clean();
			_frame.frameClean();
		}

	public:	// 只关于菜单的

		void setMaxSpaceOper()
		{
			_menu.setMaxSpaceOper();
		}

		void setSameSpaceOperWithBack()
		{
			_menu.setSameSpaceOperWithBack();
		}

		void setMenuButton(int rowPos, int colPos, PFUNC customize)
		{
			_menu.setWay(rowPos, colPos, customize);
		}

		void setOperateSpace(int rowPos, int colPos, int front, int back)
		{
			_menu.setOperateSapce(rowPos, colPos, front, back);
		}

		void setOperateColor(int rowPos, int colPos, int colorNum, bool strength = false)
		{
			_menu.setOperateColor(rowPos, colPos, colorNum, strength);
		}

		void operateMode(bool Yes = false)
		{
			_menu.operateMode(Yes);
		}

		int operateWay(int way, int optionX = 1, int optionY = 1)
		{
			int info = 0;
			if (way == keyboard)
			{
				info = _menu.operateKeyboardStart(optionX, optionY);
			}
			else if (way == mouse)
			{
				info = _menu.operateMouseStart();
			}
			return info;
		}

		//void operateMouseStart()
		//{
		//	_menu.operateMouseStart();
		//}

		//void operateKeyboardStart(int posX = 0, int posY = 0)
		//{
		//	_menu.operateKeyboardStart(posX, posY);
		//}

		void setMenuRowSpace(int row)
		{
			_menu.setRowSpace(row);
		}

		void setMenuBackgroundSpace(int rowPos, int colPos, int front, int back)
		{
			_menu.setBackgroundSpace(rowPos, colPos, front, back);
		}

		void setMenuCharSpace(int rowPos, int colPos, int front, int back)
		{
			_menu.setCharSpace(rowPos, colPos, front, back);
		}

		void setMenuBackgroundColor(int rowPos, int colPos, int colorNum, int strength = false)
		{
			_menu.setBackgroundColor(rowPos, colPos, colorNum, strength);
		}

		void setMenuCharColor(int rowPos, int colPos, int colorNum, int strength = false)
		{
			_menu.setCharColor(rowPos, colPos, colorNum, strength);
		}

		void setMenuColor(int rowPos, int colPos, int charColor, bool charStrength, int backgroundColor = 0, bool backgroundStrength = false)
		{
			_menu.setColor(rowPos, colPos, charColor, charStrength, backgroundColor, backgroundStrength);
		}

		void setMenuOption(int rowPos, int colPos, const std::string& str1, short front = 1, short back = 1)
		{
			_menu.setOption(rowPos, colPos, str1, front, back);
		}

	public:	// 只关于框架的

		void setFrameSide(CHAR up, CHAR down, CHAR left , CHAR right)
		{
			_frame.setSide(up, down, left, right);

			checkPosFrameWithMenu();
		}

		void setFrameCorner(CHAR top_left, CHAR bottom_left, CHAR top_right, CHAR bottom_right)
		{
			_frame.setCorner(top_left, bottom_left, top_right, bottom_right);

			checkPosFrameWithMenu();
		}

		void setFrameNumWord(int number)
		{
			_frame.numWord(number);
		}

		void setFrameWord(int pos, STRING str1, signed char direction, short distance)
		{
			_frame.setWord(pos, str1, direction, distance);
		}

		void setFrameRecallWord(int pos)
		{
			_frame.recallWord(pos);
		}

	protected:

		void checkPosFrameWithMenu()
		{
			if (_frame._the_char._x != _menu._x && _frame._the_char._y != _menu._y)
			{
				return;
			}

			short up = 0;
			short down = 0;
			short left = 0;
			short right = 0;

			if (_frame._the_char._up != 0)
			{
				up = 1;
			}
			if (_frame._the_char._left != 0)
			{
				left = sizeof(CHAR);
			}
			if (_frame._the_char._down != 0)
			{
				down = 1;
			}
			if (_frame._the_char._right != 0)
			{
				right = 1;
			}

			_menu.setPos(_frame._the_char._x + left + _compare_x, _frame._the_char._y + up + _compare_y);
		}

	protected:

		FRAME _frame;
		MENU _menu;

		short _compare_x = 0;
		short _compare_y = 0;

		bool _staticInit = false;

	};

	typedef console_screen_menu<int(*)(), console_screen_menu_operate<int(*)()>, frame, signed char, const char*> menu;

	typedef console_screen_menu<int(*)(), console_screen_menu_operate<int(*)()>, wframe, wchar_t, const wchar_t*> wmenu;
}

text

console_screen_text_base.h

#pragma once

#include <vector>
#include <utility>
#include <cassert>
#include <iostream>

namespace my
{
	template<class STRING, class CH>
	class console_screen_text_base
	{
		template<class TEXTCHAR, class FRAME, class STRING, class CHAR>
		friend class console_screen_text;

	public:

		console_screen_text_base(short x, short y, short high = 10, short wide = 10, int textNum = 1)
			:_text_num(textNum, std::pair<STRING, short>(nullptr, 0))
			,_x(x)
			,_y(y)
			,_high(high)
			,_wide(wide)
		{
			assert(textNum > 0);
			assert(high > 0 && wide > 0);
			assert(x >= 0 && y >= 0);
		}

		void setText(int theTextRank, STRING theText, short frontDistance)
		{
			assert(theTextRank > 0);
			assert(theText != nullptr && frontDistance >= 0);

			_text_num[theTextRank - 1] = { theText, frontDistance };
		}

		void setRowSpace(int row)
		{
			assert(row >= 0);

			_row_space = row;
		}

		void setHideAndWide(int high, int wide)
		{
			assert(high > 0 && wide > 0);

			_high = high;
			_wide = wide;
		}

		void showNoCheck()
		{
			if (sizeof(CH) == sizeof(signed char))
			{
				textShowClean((void(*)(STRING))&getCout, true);
			}
			else
			{
				textShowClean((void(*)(STRING)) & getWcout, true);
			}
		}

		void cleanNoCheck()
		{
			if (sizeof(CH) == sizeof(signed char))
			{
				textShowClean((void(*)(STRING)) & getCout, false);
			}
			else
			{
				textShowClean((void(*)(STRING)) & getWcout, false);
			}
		}

		void cleanAndCheck()
		{
			if (sizeof(CH) == sizeof(signed char))
			{
				textShowCleanAndCheck((void(*)(CH)) & getCoutC, false);
			}
			else
			{
				textShowCleanAndCheck((void(*)(CH)) & getWcoutC, false);
			}
		}

		void showAndCheck()
		{
			if (sizeof(CH) == sizeof(signed char))
			{
				textShowCleanAndCheck((void(*)(CH)) & getCoutC, true);
			}
			else
			{
				textShowCleanAndCheck((void(*)(CH)) & getWcoutC, true);
			}
		}

		void setPos(short x, short y)
		{
			assert(x >= 0 && y >= 0);

			_x = x;
			_y = y;
		}

	protected:

		//文本长度受宽度限制,过长会换行
		void textShowCleanAndCheck(void(*outfuncString)(CH), bool isShow)
		{
			int countPosY = 0;
			int wideLine = _wide;

			if (sizeof(CH) == 2)
			{
				wideLine /= 2;
			}

			for (int i = 0; i < _text_num.size(); ++i)
			{
				if (i != 0)
				{
					countPosY += _row_space;
				}

				if (_text_num[i].first == nullptr)
				{
					return;
				}

				int len = theStrlen(_text_num[i].first);

				int j = 0;

				int printIndex = 0;
				if (sizeof(CH) == 1)
				{
					printIndex = _text_num[i].second;
				}
				else
				{
					printIndex = _text_num[i].second % 2;
					printIndex = _text_num[i].second / 2;
				}

				SetPos(_x + _text_num[i].second, _y + i + countPosY);
				while (j < wideLine - printIndex)
				{
					if (isShow == true)
					{
						outfuncString(_text_num[i].first[j]);
					}
					else
					{
						CH blank = 0;
						if (sizeof(CH) == 2)
						{
							blank = L' ';
							outfuncString(blank);
							outfuncString(blank);
						}
						else
						{
							blank = ' ';
							outfuncString(blank);
						}
					}
					++j;
				}

				++countPosY;
				while (printIndex < len)
				{
					SetPos(_x, _y + i + countPosY);
					printIndex = j;

					int maxSize = wideLine + printIndex;
					if (maxSize > len)
					{
						maxSize = len;
					}

					while (j < maxSize)
					{
						if (isShow == true)
						{
							outfuncString(_text_num[i].first[j]);
						}
						else
						{
							CH blank = 0;
							if (sizeof(CH) == 2)
							{
								blank = L' ';
								outfuncString(blank);
								outfuncString(blank);
							}
							else
							{
								blank = ' ';
								outfuncString(blank);
							}
						}
						++j;
					}
					if (j < len)
					{
						++countPosY;
					}
				}
			}
		}

		void textShowClean(void(*outfuncString)(STRING), bool isShow)
		{
			int countPosY = 0;
			for (int i = 0; i < _text_num.size(); ++i)
			{
				if (i != 0)
				{
					countPosY += _row_space;
				}

				SetPos(_x + _text_num[i].second, _y + i + countPosY);

				if (_text_num[i].first == nullptr)
				{
					return;
				}
				if (isShow == true)
				{
					outfuncString(_text_num[i].first);
				}
				else
				{
					int len = theStrlen(_text_num[i].first);

					if (sizeof(CH) == 1)
					{
						std::cout << std::string(len, ' ');
					}
					else
					{
						std::wcout << std::wstring(len * 2, L' ');
					}
				}
			}
		}

		static void getWcout(STRING str1)
		{
			std::wcout << str1;
		}

		static void getCout(STRING str1)
		{
			std::cout << str1;
		}

		static void getWcoutC(CH ch)
		{
			std::wcout << ch;
		}

		static void getCoutC(CH ch)
		{
			std::cout << ch;
		}

	protected:

		std::vector<std::pair<STRING, short>> _text_num;	// 文本存储

		short _row_space = 0;								// 行距

		short _x;
		short _y;

		short _high;
		short _wide;	

		typedef size_t(*p_T_char)(STRING);

		p_T_char theStrlen = sizeof(CH) == sizeof(signed char) ? (p_T_char)&strlen : (p_T_char)&wcslen;
	};

	typedef console_screen_text_base<const char*, signed char> text_base;

	typedef console_screen_text_base<const wchar_t*, wchar_t> wtext_base;

}

console_screen_text.h

#pragma once

#include "console_screen_frame.h"
#include "console_screen_text_base.h"

namespace my
{
	template<class TEXTCHAR, class FRAME, class STRING, class CHAR>
	class console_screen_text
	{
	public:

		console_screen_text(short x, short y, short high = 10, short wide = 20, int textNum = 1)
			:_text(x, y, high, wide, textNum)
			, _frame(x, y, high, wide)
		{
			;
		}

	public:	// 静态准备

		void staticInit(bool yes = true)
		{
			_staticInit = yes;
		}

		bool alreadyStaticInit()
		{
			return _staticInit;
		}

	public:	// 有关文本与框架

		void setPosCompare(short x, short y)
		{
			assert(x >= 0);
			assert(y >= 0);

			_compare_x = x;
			_compare_y = y;

			setTextPos(_text._x + x, _text._y + y);
		}

		void checkPosFrameWithText()
		{
			if (_frame._the_char._x != _text._x && _frame._the_char._y != _text._y)
			{
				return;
			}

			short up = 0;
			short down = 0;
			short left = 0;
			short right = 0;

			if (_frame._the_char._up != 0)
			{
				up = 1;
			}
			if (_frame._the_char._left != 0)
			{
				left = sizeof(CHAR);
			}
			if (_frame._the_char._down != 0)
			{
				down = 1;
			}
			if (_frame._the_char._right != 0)
			{
				right = 1;
			}

			setTextPos(_frame._the_char._x + left + _compare_x, _frame._the_char._y + up + _compare_y);

			_text._high = _frame._the_char._high - up * 2;
			_text._wide = _frame._the_char._wide - left * 2;
		}

		void setAndCheckPos(int x, int y)
		{
			_frame.setPos(x, y);

			_text.setPos(x, y);

			checkPosFrameWithText();
		}

		void show()
		{
			_frame.frameShow();
			_text.showNoCheck();
		}

		void showAndCheck()
		{
			_frame.frameShow();
			_text.showAndCheck();
		}

		void clean()
		{
			_frame.frameClean();
			_text.cleanNoCheck();
		}

		void cleanAndCheck()
		{
			_frame.frameClean();
			_text.cleanAndCheck();
		}

	public:	// 只关于文本的

		void setTextPos(short x, short y)
		{
			_text.setPos(x, y);
		}

		//void showAndCheck()
		//{
		//	_text.showAndCheck();
		//}

		//void showButNoCheck()
		//{
		//	_text.showButNoCheck();
		//}

		void setHideAndWide(int high, int wide)
		{
			_text.setRowSpace(high, wide);
		}

		void setRowSpace(int row)
		{
			_text.setRowSpace(row);
		}

		void setText(int theTextRank, STRING text, short frontDistance)
		{
			_text.setText(theTextRank, text, frontDistance);
		}

	public:	// 只关于框架的

		void setFrameSide(CHAR up, CHAR down, CHAR left, CHAR right)
		{
			_frame.setSide(up, down, left, right);

			checkPosFrameWithText();
		}

		void setFrameCorner(CHAR top_left, CHAR bottom_left, CHAR top_right, CHAR bottom_right)
		{
			_frame.setCorner(top_left, bottom_left, top_right, bottom_right);

			checkPosFrameWithText();
		}

		void setFrameNumWord(int number)
		{
			_frame.numWord(number);
		}

		void setFrameWord(int pos, STRING str1, signed char direction, short distance)
		{
			_frame.setWord(pos, str1, direction, distance);
		}

		void setFrameRecallWord(int pos)
		{
			_frame.recallWord(pos);
		}

	protected:

		TEXTCHAR _text;
		FRAME _frame;

		short _compare_x = 0;
		short _compare_y = 0;

		bool _staticInit = false;

	};

	typedef console_screen_text<text_base, frame, const char*, signed char> text;

	typedef console_screen_text<wtext_base, wframe, const wchar_t*, wchar_t> wtext;

}

四、代码参考

后续可能会出一份使用菜单库的博客,这里只给一个菜单供大家参考。

#include "console_screen_menu.h"
#include <iostream>

int isQuit()
{
	return 1;
}

int main()
{
	std::wcout.imbue(std::locale("zh_CN"));
	my::HideCursor();

	static my::wmenu isATest(2, 1, 5, 10, 2, 1, true);

	if (isATest.alreadyStaticInit() == false)
	{
		isATest.setMenuOption(1, 1, "开始", 0, 0);
		isATest.setMenuOption(2, 1, "结束", 0, 0);

		isATest.setFrameSide(L'□', L'■', L'○', L'●');
		isATest.setFrameCorner(L'△', L'▲', L'▽', L'▼');

		isATest.setMenuBackgroundSpace(1, 1, 0, 2);
		isATest.setMenuBackgroundSpace(2, 1, 0, 2);
		isATest.setOperateSpace(1, 1, 2, 0);
		isATest.setOperateSpace(2, 1, 2, 0);

		isATest.setMenuButton(2, 1, isQuit);

		isATest.staticInit(true);
	}

	int operWay = 1;

	isATest.show();
	if (operWay == 1)
	{
		isATest.operateWay(my::keyboard);
	}
	else
	{
		isATest.operateWay(my::mouse);
	}

	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2055899.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

html+css 实现hover 凹陷按钮

前言:哈喽,大家好,今天给大家分享html+css 绚丽效果!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、原理解析💡1.这是一个,hover时凹陷的效果。每个按钮是一个button…

【Android 远程数据库操作】

按正常情况下&#xff0c;前端不应该直接进行远程数据库操作&#xff0c;这不是一个明智的方式&#xff0c;应该是后端提供对应接口来处理&#xff0c;奈何公司各方面原因需要前端这样做。 对此&#xff0c;我对远程数据库操作做了总结&#xff0c;便于自己复盘&#xff0c;同…

机器学习第十四章-概率图模型

目录 14.1 隐马尔可夫模型 14.2马尔科夫随机场 14.3条件随机场 14.4学习与推断 14.4.1变量消去 14.4.2信念传播 14.5近似推断 14.5.1 MCMC采样 14.5.2 变分推断 14.6 话题模型 14.1 隐马尔可夫模型 概率围棋型是一类用图来表达变量相关关系的概率模型.它以图为表示工具…

Transformer(课程笔记)

一&#xff1a;Motivation RNN需要顺序的执行&#xff0c;不利于并行计算。 RNN的变体例如GRU、LSTM等需要依靠注意力机制解决信息瓶颈等问题。 抛弃RNN结构&#xff0c;提出了Transformer结构。 Transformer整体架构 二&#xff1a; 输入层&#xff08;BPE&#xff0c;PE&…

《黑神话:悟空》玩家必看!AMD显卡驱动24.8.1版全力支持!

系统之家于8月20日发出最新报道&#xff0c;AMD发布了最新的24.8.1版本驱动&#xff0c;本次更新增加了《黑神话&#xff1a;悟空》《星球大战&#xff1a;亡命之徒》等游戏的支持&#xff0c;且HYPR Tune支持允许HYPR-RX启用游戏内技术。下面跟随小编一起来看看AMD显卡驱动24.…

Centos7 message日志因dockerd、kubelet、warpdrive、containerd等应用迅速增长

问题&#xff1a;公司服务器在部署一套业务后&#xff0c;message日志记录大量的dockerd、kubelet、warpdrive、containerd应用日志&#xff0c;每天增加2G大小的日志 解决方案&#xff1a; 前期吐槽下&#xff1a;发现某个帖子&#xff0c;需要会员或者花钱才能看&#xff0c…

探索网络安全的深度与广度:挑战、策略与未来展望

一、引言 在当今数字化的时代&#xff0c;网络已经成为社会运转的核心基础设施之一。从个人的日常通信、娱乐到企业的业务运营、国家的关键服务&#xff0c;几乎所有领域都依赖于网络。然而&#xff0c;随着网络的普及和应用的深化&#xff0c;网络安全问题也日益凸显&#xf…

松下弧焊机器人维修 控制柜故障 连接线修复

一、Panasonic焊接机器人控制柜与机器人的接线 机器人的控制箱&#xff0c;一定要配对使用。松下焊接机器人控制柜已经记忆了机器人的绝对原点(机器人位置控制原点)。 二、编码器电缆 (圆形连接器) 1. 接口的插头插座要注意&#xff0c;插头要插到插座中。 2. 用一手握住电缆&a…

网络原理TCP/UDP详解

目录 传输属的几种格式 1.xml&#xff1a;通过成对的标签表示键值对信息。 2.json&#xff1a;当前更主流一点的&#xff0c;网络通信的数据格式 3.yml&#xff08;yaml&#xff09;强制要求数据的组织格式 4.google protobuffer 传输层 1.端口号&#xff1a; UDP协议 …

Vue3 组件管理 12 种神仙写法,灵活使用才能提高效率

SFC 单文件组件 顾名思义&#xff0c;就是一个.vue文件只写一个组件 模板写法 如果这个组件想要在别的组件里使用&#xff0c;就需要在另一个.vue中引入和使用、复用 h函数写法 使用 defineComponent h 去进行组件编写 JSX/TSX写法 使用 defineComponent JSX/TSX 去进行…

【html+css 绚丽Loading】 - 000008 三才虚空灵瞳

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽Loading&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495…

应用方案 | 降压型DC-DC电源管理电路 D2576介绍

概述 D2576是一款高效降压型DC-DC转换器&#xff0c;固定52KHz开关频率&#xff0c;可以提供最高3A输出电流能力&#xff0c;具有低纹波&#xff0c;出色的线性调整率与负载调整率特点。 D2576内置固定频率振荡器与频率补偿电路&#xff0c;简化了电路设计。PWM控制环路可以调节…

Rivian暂停亚马逊送货车生产,特斯拉Roadster再引关注

Rivian遭遇供应链挑战&#xff0c;暂停亚马逊送货车生产 电动汽车制造商Rivian近期宣布&#xff0c;由于零部件短缺&#xff0c;已暂停为零售巨头亚马逊生产商业送货车。这一决定标志着Rivian在应对供应链挑战方面遭遇了最新挫折。作为Rivian的最大投资者&#xff0c;亚马逊持有…

画板444

p31 画H1和H2的封装 立创里面这次有尺寸了没单位好像 给的1.02 他设的1.1焊盘可以大点 排针穿过去的&#xff08;别的焊盘也这样&#xff1f;&#xff09; 引脚编号 直接改成2.54 他焊盘直间的 距离了 刚才改成通用的直径了&#x1f605;&#x1f605;&#x1f605; 这能测尺寸…

金九银十,软件测试面试八股文【含答案+文档】

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 测试技术面试题 1、什么是兼容性测试&#xff1f;兼容性测试侧重哪些方面&#xff1f; 参考答案&#xff1a; 兼容测试主要是检查软件在不同的硬件平台、软件…

google seo基础宝典,新手必学

Google SEO 是什么&#xff1f; Google SEO是指针对谷歌搜索引擎优化网站排名的一种营销方式&#xff0c;旨在提升外贸网站在谷歌的品牌和产品曝光度&#xff0c;从而吸引外贸订单。具体做法是根据谷歌的搜索引擎排名规则&#xff0c;对网站的内容、结构、链接等方面进行优化&a…

C++竞赛初阶L1-13-第五单元-循环嵌套(29~30课)536: T456455 画矩形

题目内容 根据输入的四个参数&#xff1a;a,b,c,f 参数&#xff0c;画出对应的矩形。 前两个参数 a,b 为整数&#xff0c;依次代表矩形的高和宽&#xff1b; 第三个参数 c 是一个字符&#xff0c;表示用来填充的矩形符号&#xff1b; 第四个参数 f 为整数&#xff0c;0 代表…

测试资料2222

一 解决穷举场景&#xff1a;使用等价类划分法 适用场景 正向用例&#xff1a;一条尽可能覆盖多条 逆向用例&#xff1a;每一条数据&#xff0c;都是一条单独用例 完整的用例应该是等价类和边界值一块写 二 能对限定边界规则设计测试点 2.1选取正好等于、刚好大于、刚好小于…

搜维尔科技:【产品推荐】Manus Quantum Mocap Metagloves VR手套数据手套机械手训练专用手套

全新量子追踪技术 Quantum Mocap Metagloves通过使用毫米级精确的指尖跟踪传感器来提供高保真手指跟踪。传感器没有漂移&#xff0c;可提供高度准确且可靠的手指捕获数据。 手指追踪的新黄金标准 Quantum Mocap Metagloves使用精确的量子跟踪技术捕捉手部每一个细节动作。让您…

Unity与UE,哪种游戏引擎适合你?

PlayStation vs Xbox&#xff0c;Mario vs Sonic&#xff0c;Unreal vs Unity&#xff1f;无论是游戏主机、角色还是游戏引擎&#xff0c;人们总是热衷于捍卫他们在游戏行业中的偏爱。 专注于游戏引擎&#xff0c;Unity和Unreal Engine&#xff08;简称UE4&#xff09;是目前市…