【C++】基于Easyx的UI库(2022-8-21 V1)

4 篇文章 1 订阅

系列文章目录

【C++】基于Easyx的UI库(2022-8-14 V1)

【C++】基于Easyx的UI库(2022-8-14 V2)


简介

实现语言:C++

项目名称:UI.h

项目类型:控制台应用

项目版本:2022-8-21 V1

开发环境:Visual Studio 2022 Community 17.3.1  &  Easyx 2022-6-10


这里就不再写项目介绍了(因为根本就没啥好写的)。


更新历史

  • 2022-8-21 增加文本框(Text Box)
  • 2022-8-18 优化已有的控件
  • 2022-8-14 优化已有的控件,将init()初始化函数改为构造函数;增加复选框(Checked List Box)
  • 2022-8-13 增加单选框(Check Box),优化按钮(Button)和文本(Label)
  • 2022-8-7 完成按钮(Button)和文本(Label)
  • 2022-8-5 创建UI.h

代码

UI.h

/***************************************************************
 *                                                             *
 * UI.h                                                        *
 * UI Library for C++ Base on Easyx.                           *
 * Version : 2022-8-21 V1                                      *
 * 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 {
	private:
		int width = 0, height = 0;

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

		/**** 控件左上角的y坐标 ****/
		y = 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() {
			clearrectangle(x, y, x + width - 1, y + height - 1);
			visible = false;
			return;
		}

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

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

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

	/**** 文本(该控件为自动调整大小) ****/
	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() {
			clearrectangle(x, y, x + width - 1, y + height - 1);
			visible = false;
			return;
		}

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

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

	/**** 勾选框(该控件为自动大小) ****/
	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->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();
			return;
		}

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

	/**** 复选框(最多15项,该控件为自动大小) ****/
	class CheckedListBox {
	private:
		int num = 0;

	public:
		//复选框=多个勾选框
		CheckBox* checkbox[15] = { nullptr };

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

		/**** 控件左上角的y坐标 ****/
			y = 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();
			return;
		}

		/**** 控件是否被勾选,按下则切换效果,出现异常返回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];
			}
			return;
		}
	};

	/**** 文本框 ****/
	class TextBox {
	private:
		int width, height = 22;
		Button* button;
		Label* label;

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

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

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

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

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

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

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

		/**** 输入文本 ****/
		void in() {
			ExMessage m;
			int count = -1;
			size_t len = 0;
			bool state = false;
			while (true) {
				m.message = 0;
				peekmessage(&m, EM_MOUSE | EM_CHAR);
				if (m.message == WM_LBUTTONDOWN) {
					if (!button->click(m)) {
						state = false;
						goto End;
					}
					state = true;
				}
				else if (m.message == WM_CHAR && state) {
					len = wcslen(label->text);
					switch (m.ch) {
					case '\b':
						if (len > 0) {
							label->text[len - 1] = 0;
							clearrectangle(x + 1 + textwidth(label->text), y + 3, x + width - 2, y + height - 4);
							lstrcpy(text, label->text);
							label->reload();
						}
						break;
					case '\n':
					case '\r':
						state = false;
						goto End;
						break;
					default:
						label->text[len++] = m.ch;
						label->text[len] = 0;
						if (textwidth(label->text) < width - 10) {
							label->text[--len] = 0;
							clearrectangle(x + 5 + textwidth(label->text), y + 3, x + 5 + textwidth(label->text), y + height - 4);
							label->text[len++] = m.ch;
							lstrcpy(text, label->text);
							label->reload();
						}
						else {
							label->text[--len] = 0;
						}
						break;
					}
				}
				count = (count + 1) % 64;
				if (count < 32 && state) line(x + 5 + textwidth(label->text), y + 3, x + 5 + textwidth(label->text), y + height - 4);
				else if (state) clearrectangle(x + 5 + textwidth(label->text), y + 3, x + 5 + textwidth(label->text), y + height - 4);
				Sleep(10);
			}
		End:
			clearrectangle(x + 5 + textwidth(label->text), y + 3, x + 5 + textwidth(label->text), y + height - 4);
			return;
		}

		~TextBox()
		{
			delete button;
			delete label;
			return;
		}
	};
}
#else
	#error 请先安装Easyx库,下载地址:https://easyx.cn
#endif

今天上一个例子:

text.cpp

#include "UI.h"
int main() {
	initgraph(640, 480);
	settextcolor(BLACK);
	setlinecolor(BLACK);
	setbkcolor(RGB(240, 240, 240));
	cleardevice();
	UI::TextBox textbox(5, 5, 200);
	textbox.show();
	int width = 0;
	while (true) {
		width = textwidth(textbox.text);
		textbox.in();
		clearrectangle(10, 40, 20 + width, 56);
		outtextxy(10, 40, textbox.text);
	}
}

运行效果:

UI.h 2022-8-21 V1版本 效果


溜了,拜拜!

  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

H.Y_C ⁹⁹⁹⁹⁹⁹⁺

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

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

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

打赏作者

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

抵扣说明:

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

余额充值