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

Windows C++控制台菜单库

声明:

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

演示视频:

C++菜单库例子展示

一、前言

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

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

二、具体框架

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

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

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

cpp 复制代码
	std::wcout.imbue(std::locale("zh_CN"));		

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

三、源码展示

console_screen_set.h

cpp 复制代码
#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

cpp 复制代码
#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

cpp 复制代码
#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

cpp 复制代码
#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

cpp 复制代码
#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;

}

console_screen_menu_base.h

cpp 复制代码
#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

cpp 复制代码
#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

cpp 复制代码
#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

cpp 复制代码
#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

cpp 复制代码
#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;

}

四、代码参考

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

cpp 复制代码
#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;
}
相关推荐
爱隐身的官人24 分钟前
爬虫基础学习-爬取网页项目(二)
前端·爬虫·python·学习
Ysn07192 小时前
pytorch_grad_cam 库学习笔记—— Ablation-CAM 算法的基类 AblationCAM 和 AblationLayer
pytorch·笔记·学习
小清兔2 小时前
c#基础知识
开发语言·数据库·学习·unity·c#·游戏引擎·.net
霜绛2 小时前
Unity笔记(七)——四元数、延迟函数、协同程序
笔记·学习·unity·游戏引擎
2006yu3 小时前
从零开始学习单片机13
单片机·嵌入式硬件·学习
风和日丽 随波逐流3 小时前
java18学习笔记
笔记·学习·java18
幽络源小助理3 小时前
如何从零开始学习黑客技术?网络安全入门指南
网络·学习·web安全
2006yu5 小时前
从零开始学习单片机12
学习
Univin5 小时前
8.25作业
数据结构·windows
Incredibuild5 小时前
DevSecOps 集成 CI/CD Pipeline:实用指南
c++·ci/cd·devsecops