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;
}
相关推荐
Ajiang28247353041 小时前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
梓仁沐白3 小时前
ubuntu+windows双系统切换后蓝牙设备无法连接
windows·ubuntu
‘’林花谢了春红‘’5 小时前
C++ list (链表)容器
c++·链表·list
九鼎科技-Leo7 小时前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
机器视觉知识推荐、就业指导7 小时前
C++设计模式:建造者模式(Builder) 房屋建造案例
c++
朝九晚五ฺ7 小时前
【Linux探索学习】第十四弹——进程优先级:深入理解操作系统中的进程优先级
linux·运维·学习
猫爪笔记9 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
Yang.999 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
熬夜学编程的小王9 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表