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

简介

实现语言:C++

项目名称:UI.h

项目类型:控制台应用

项目版本:2022-8-14 V1

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


项目介绍

前段时间我研究了C#,就想把C#窗体应用中的控件搬到C++上,于是就有了这篇文章。


更新历史

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

代码

这个代码只要是懂一点Easyx的应该都看得懂(因为Easyx本身并不难),并且我还在里面加了一些注释,应该大部分人阅读起来都是没问题的。

UI.h

/***************************************************************
 *                                                             *
 * UI.h                                                        *
 * UI Library for C++ Base on Easyx.                           *
 * Version : 2022-8-14 V1                                      *
 * https://easyx.cn                                            *
 * https://blog.csdn.net/qq_43546083?spm=1000.2115.3001.5343   *
 *                                                             *
 ***************************************************************/

#pragma once

#if __has_include()

#include 

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

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

		/**** 控件的宽度 ****/
		int width = -1,

		/**** 控件的高度 ****/
		height = -1;

		/**** 控件所显示的文本 ****/
		LPCTSTR text = L"";

		/**** 控件显示的文本高度 ****/
		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;
			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 == -1 || y == -1 || width == -1 || height == -1) || !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();
		}
	};

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

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

		/**** 控件所显示的文本 ****/
		LPCTSTR text = L"";

		/**** 控件显示的文本高度 ****/
		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;
			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();
		}
	};

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

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

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

		/**** 控件所显示的文本 ****/
		LPCTSTR text = L"";

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

		/**** 构造函数,初始化控件左上角的坐标与显示的文本 ****/
		CheckBox(int x, int y, LPCTSTR text) {
			this->x = x;
			this->y = y;
			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 == -1 || button->y == -1 || button->width == -1 || button->height == -1) || (label->x == -1 || label->y == -1) || !(button->visible && label->visible)) {
				//未初始化控件或当前控件不可见
				return false;
			}
			if (button->click(m)) {
				state = !state;
				button->text = state ? L"√" : L"";
				reload();
			}
			return true;
		}

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

		~CheckBox()
		{
			delete button;
			delete label;
		}
	};

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

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

		/**** 构造函数,初始化控件左上角的坐标与显示的文本 ****/
		CheckedListBox(int x, int y, int num, LPCTSTR text[]) {
			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 + i * 20, text[i]);
			}
		}
		CheckedListBox(int num, CheckBox checkbox[]) {
			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 = -1;
			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(checkbox[0]->x - 5, checkbox[0]->y - 5, checkbox[0]->x + maxlen + 25, checkbox[0]->y + num * 20 + 3);
			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()
		{
			delete[] &checkbox;
		}
	};
}
#else
	#error 请先安装Easyx库,下载地址:https://easyx.cn
#endif

在这里,为了让大家简单了解一下这些类使用的方法,给了一段参考代码:

text.cpp

#include "UI.h"
int main() {
	initgraph(640,480);
	settextcolor(BLACK);
	setbkcolor(RGB(240, 240, 240));
	setlinecolor(BLACK);
	setfillcolor(RGB(230, 230, 230));
	cleardevice();
	LPCTSTR text[3] = { L"这是",L"一个",L"Checked List Box" };
	UI::Button button(5, 5, 200, 60, L"这是一个Button");
	UI::CheckBox checkbox(5, 70, L"这是一个Check Box");
	UI::CheckedListBox checkedlistbox(5, 155, 3, text);
	UI::Label label1(5, 95, L"这是一个Label"), label2(5, 115, L"这是一个彩蛋", 32);
	button.show();
	checkbox.show();
	checkedlistbox.show();
	label1.show();
	ExMessage m;
	while (true) {
		m = getmessage(EM_MOUSE);
		checkbox.check(m);
		checkedlistbox.check(m);
		if (checkbox.state == true)label2.show();
		else label2.hide();
		if (button.click(m)){
			if (label1.visible)label1.hide();
			else label1.show();
		}
	}
	return 0;
}

 运行效果:

UI.h 2022-8-14版本 效果


好了,今天就到这里了。如果大家有对这篇文章有不懂或有建议可以告诉我。拜拜!

你可能感兴趣的:(C++,Easyx,c++,Easyx)