[C++] Easyx ベースの UI ライブラリ (2022-8-14 V2)

シリーズ記事ディレクトリ

[C++] Easyx ベースの UI ライブラリ (2022-8-14 V1)


序章

実装言語:C++

プロジェクト名: UI.h

プロジェクトの種類: コンソール アプリ

プロジェクト バージョン: 2022-8-14 V2

開発環境: Visual Studio 2022 Community 17.3.1 & Easyx 2022-6-10


プロジェクト紹介

前回の記事では、誰かがいくつかの提案を行いました。今日、私は彼の提案に基づいてコードを修正しました。

彼が言った問題は、LPCTSTR 型がポインタであるため、直接コピー (浅いコピー) できず、ディープ コピーが使用されることです。

このために、LPCTSTR 型の元のメンバーを LPTSTR 型に変更し、浅いコピーを深いコピーに変更しました (lstrcpy 関数を使用)。少しだけ変更されているように見えますが、実際には長い間手探りでした.LPCTSTRタイプの詳細なチュートリアルはインターネット上にないため.


更新履歴

  • 2022-8-18 既存のコントロールを最適化する
  • 2022-8-14 既存のコントロールを最適化、init()の初期化関数をコンストラクタに変更、チェックボックス(Checked List Box)を追加
  • 2022-8-13 チェックボックス、最適化ボタン、テキストを追加
  • 2022-8-7 完成ボタン(Button)とテキスト(Label)
  • 2022-8-5 UI.h の作成

コード

UI.h

/***************************************************************
 *                                                             *
 * UI.h                                                        *
 * UI Library for C++ Base on Easyx.                           *
 * 基于 Easyx 的 C++ UI 库                                     *
 * Version : 2022-8-14 V2                                      *
 * 版本:2022-8-14 V2                                          *
 * https://easyx.cn                                            *
 * https://blog.csdn.net/qq_43546083?spm=1000.2115.3001.5343   *
 *                                                             *
 ***************************************************************/

#pragma once

#if __has_include(<graphics.h>)

#include <graphics.h>

namespace UI {
	/**** 按钮 ****/
	class Button {
	public:
		/**** 控件左上角的x坐标 ****/
		int x = 0,

		/**** 控件左上角的y坐标 ****/
		y = 0;

		/**** 控件的宽度 ****/
		int width = 0,

		/**** 控件的高度 ****/
		height = 0;

		/**** 控件所显示的文本 ****/
		LPTSTR text = new wchar_t[1024];

		/**** 控件显示的文本高度 ****/
		int size = 16;

		/**** 控件是否可见,可见为true,否则为false ****/
		bool visible = false;

		/**** 构造函数,初始化控件左上角的坐标、宽度、高度、显示的文本与文本的高度(默认为16) ****/
		Button(int x, int y, int width, int height, LPCTSTR text, int size = 16) {
			this->x = x;
			this->y = y;
			this->width = width;
			this->height = height;
			lstrcpy(this->text, text);
			this->size = size;
			return;
		}

		/**** 显示控件,成功返回true,出现异常返回false ****/
		bool show() {
			if (visible) {
				//当前控件可见
				return false;
			}
			int temp = getbkmode();
			setbkmode(TRANSPARENT);
			LOGFONT* temp1 = new LOGFONT();
			LOGFONT* temp2 = new LOGFONT();
			gettextstyle(temp1);
			gettextstyle(temp2);
			temp2->lfHeight = size;
			settextstyle(temp2);
			if (width - textwidth(text) <= 0 || height - textheight(text) <= 0) {
				//文字过大
				settextstyle(temp1);
				return false;
			}
			fillrectangle(x, y, x + width - 1, y + height - 1);
			outtextxy(x + (width - textwidth(text)) / 2, y + (height - textheight(text)) / 2, text);
			settextstyle(temp1);
			setbkmode(temp);
			delete temp1;
			delete temp2;
			visible = true;
			return true;
		}

		/**** 隐藏控件 ****/
		void hide() {
			COLORREF temp = getfillcolor();
			setfillcolor(getbkcolor());
			solidrectangle(x, y, x + width - 1, y + height - 1);
			setfillcolor(temp);
			visible = false;
			return;
		}

		/**** 判断按钮是否被按下,被按下返回true,没有按下或出现异常返回false ****/
		bool click(ExMessage m) {
			if ((x == 0 || y == 0 || width == 0 || height == 0) || !visible) {
				//未初始化控件或当前控件不可见
				return false;
			}
			return m.message == WM_LBUTTONUP && (m.x >= x && m.x <= x + width - 1) && (m.y >= y && m.y <= y + height - 1);
		}

		/**** 刷新插件(显示状态下) ****/
		void reload() {
			visible = false;
			show();
		}

		~Button()
		{
			text = nullptr;
			delete[] text;
		}
	};

	/**** 文本(该控件为自动调整大小) ****/
	class Label {
	private:
		int width, height;
	public:
		/**** 控件左上角的x坐标 ****/
		int x = 0,

		/**** 控件左上角的y坐标 ****/
			y = 0;

		/**** 控件所显示的文本 ****/
		LPTSTR text = new wchar_t[1024];

		/**** 控件显示的文本高度 ****/
		int size = 16;

		/**** 控件是否可见,可见为true,否则为false ****/
		bool visible = false;

		/**** 构造函数,初始化控件左上角的坐标、显示的文本与文本的高度(默认为16) ****/
		Label(int x, int y, LPCTSTR text, int size = 16) {
			this->x = x;
			this->y = y;
			lstrcpy(this->text, text);
			this->size = size;
			width = 0;
			height = 0;
			return;
		}

		/**** 显示控件,成功返回true,出现异常返回false ****/
		bool show() {
			if (visible) {
				//当前控件可见
				return false;
			}
			int temp = getbkmode();
			setbkmode(TRANSPARENT);
			LOGFONT* temp1 = new LOGFONT();
			LOGFONT* temp2 = new LOGFONT();
			gettextstyle(temp1);
			gettextstyle(temp2);
			temp2->lfHeight = size;
			settextstyle(temp2);
			outtextxy(x, y, text);
			width = textwidth(text);
			height = textheight(text);
			settextstyle(temp1);
			delete temp1;
			delete temp2;
			setbkmode(temp);
			visible = true;
			return true;
		}

		/**** 隐藏控件 ****/
		void hide() {
			COLORREF temp = getfillcolor();
			setfillcolor(getbkcolor());
			solidrectangle(x, y, x + width - 1, y + height - 1);
			setfillcolor(temp);
			visible = false;
			return;
		}

		/**** 刷新插件(显示状态下) ****/
		void reload() {
			visible = false;
			show();
		}

		~Label()
		{
			text = nullptr;
			delete[] text;
		}
	};

	/**** 勾选框(该控件为自动大小) ****/
	class CheckBox {
	private:
		//勾选框=按钮+文本
		Button* button;
		Label* label;

	public:
		/**** 控件左上角的x坐标 ****/
		int x = 0,

		/**** 控件左上角的y坐标 ****/
			y = 0;

		/**** 控件所显示的文本 ****/
		LPTSTR text = new wchar_t[1024];

		/**** 是否已被勾选 ****/
		bool state = false;

		/**** 构造函数,初始化控件左上角的坐标与显示的文本 ****/
		CheckBox(int x, int y, LPCTSTR text) {
			this->x = x;
			this->y = y;
			lstrcpy(this->text, text);
			button = new Button(x, y, 18, 18, L"");
			label = new Label(x + 20, y, text, 18);
			return;
		}

		/**** 显示控件,成功返回true,出现异常返回false ****/
		bool show() {
			if (!button->show() || !label->show()) {
				hide();
				return false;
			}
			return true;
		}

		/**** 隐藏控件 ****/
		void hide() {
			button->hide();
			label->hide();
			return;
		}

		/**** 控件是否被勾选,按下则切换效果,出现异常返回false ****/
		bool check(ExMessage m) {
			if ((button->x == 0 || button->y == 0 || button->width == 0 || button->height == 0) || (label->x == 0 || label->y == 0) || !(button->visible && label->visible)) {
				//未初始化控件或当前控件不可见
				return false;
			}
			if (button->click(m)) {
				state = !state;
				state ? lstrcpy(button->text, L"√") : lstrcpy(button->text, L"");
				reload();
			}
			return true;
		}

		/**** 刷新插件(显示状态下) ****/
		void reload() {
			button->reload();
			label->reload();
		}

		~CheckBox()
		{
			text = nullptr;
			button = nullptr;
			label = nullptr;
			delete[] text;
			delete button;
			delete label;
		}
	};

	/**** 复选框(最多15项,该控件为自动大小) ****/
	class CheckedListBox {
	public:
		//复选框=多个勾选框
		CheckBox* checkbox[15] = { nullptr };

		/**** 控件左上角的x坐标 ****/
		int x = 0,

		/**** 控件左上角的y坐标 ****/
			y = 0;

		/**** 项数 ****/
		int num = 0;

		/**** 构造函数,初始化控件左上角的坐标与显示的文本 ****/
		CheckedListBox(int x, int y, int num, LPCTSTR text[]) {
			this->x = x;
			this->y = y;
			if (num > 15) {
				MessageBox(0, L"项数过多!", L"UI.h", MB_OK | MB_ICONSTOP);
				return;
			}
			this->num = num;
			for (int i = 0; i < num; i++) {
				checkbox[i] = new CheckBox(x + 5, y + 5 + i * 20, text[i]);
			}
		}
		CheckedListBox(int num, CheckBox checkbox[]) {
			this->x = checkbox[0].x - 5;
			this->y = checkbox[0].y - 5;
			if (num > 15) {
				MessageBox(0, L"项数过多!", L"UI.h", MB_OK | MB_ICONSTOP);
				return;
			}
			this->num = num;
			for (int i = 0; i < num; i++) {
				this->checkbox[i] = &checkbox[i];
			}
		}

		/**** 显示控件,成功返回true,出现异常返回false ****/
		bool show() {
			int maxlen = 0;
			for (int i = 0; i < num; i++) {
				maxlen = max(maxlen, textwidth(checkbox[i]->text));
				if (!checkbox[i]->show()) {
					for (int j = 0; j < i; j++) {
						checkbox[j]->hide();
						return false;
					}
				}
			}
			rectangle(x, y, x + maxlen + 30, y + num * 20 + 8);
			return true;
		}

		/**** 隐藏控件 ****/
		void hide() {
			for (int i = 0; i < num; i++) checkbox[i]->hide();
		}

		/**** 控件是否被勾选,按下则切换效果,出现异常返回false ****/
		bool check(ExMessage m) {
			for (int i = 0; i < num; i++) {
				if (!checkbox[i]->check(m))return false;
			}
			return true;
		}

		/**** 刷新插件(显示状态下) ****/
		void relad() {
			for (int i = 0; i < num; i++)checkbox[i]->reload();
			return;
		}

		~CheckedListBox()
		{
			for (int i = 0; i < num; i++) {
				checkbox[i] = nullptr;
				delete checkbox[i];
			}
		}
	};
}
#else
	#error 请先安装Easyx库,下载地址:https://easyx.cn
#endif

今日は効果とサンプル コードを表示しません。前回の記事を参照してください。さようなら!

おすすめ

転載: blog.csdn.net/qq_43546083/article/details/126410713