组件库篇 | EUI | 快速上手

news2024/11/27 14:36:01

组件库篇 | EUI | 快速上手


导入组件库

仅需三个步骤便可以导入组件库:

  1. 进入main.cpp所在目录,将EUI文件夹复制到该目录下

  2. 双击sln文件使用vs打开项目,右键项目名-添加-新建筛选器,命名为EUI

  3. 将第1步导入的EUI文件夹拖入到第2步创建的筛选器中

算了,文字描述总归不够细致,你们肯定希望我手把手教你们,那好吧,我可太懂读者的心声了,谁让我要打造最适合初学者最通俗易懂的教程呢,来吧。

我们从创建空项目开始,先新建一个空项目,再添加main.cpp文件

请添加图片描述
然后就是上述的三步:

步1:进入main.cpp所在目录,将EUI文件夹复制到该目录下
请添加图片描述
步2:双击sln文件使用vs打开项目,右键项目名-添加-新建筛选器,命名为EUI

请添加图片描述

步3:将第1步导入的EUI文件夹拖入到第2步创建的筛选器中

请添加图片描述
跟着我的步骤走应该不会有任何问题了吧,嘿嘿。

在使用EUI图形库之前,需要添加头文件

#include "EUI/EUI.h" // 引入EUI组件库

然后就随心所欲的使用这些组件来构建你的软件系统吧!

下面我们来循序渐进地使用每个控件(给出的都是完整的可运行代码,在引入组件库后,直接复制代码到项目中就可以成功运行啦)


按钮

我们来使用EUI组件库创建一个按钮吧。

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT);	// 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255)); // 白色
	cleardevice();

	Button btn(820, 320, 120, 40); // 创建一个宽120,高40的按钮,坐标为(820,320)
	btn.setText(L"点击"); // 设置文本
	btn.show(); // 显示按钮

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述

这样就创建好了一个按钮,但是它还不能点击,因为我们还没有对鼠标进行监测,让我们来继续完善这个按钮,让它可以响应鼠标操作吧。

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT); // 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	Button btn(820, 320, 120, 40); // 创建一个宽120,高40的按钮,坐标为(820,320)
	btn.setText(L"点击"); // 设置文本
	btn.show(); // 显示按钮

	// 整个界面的事件循环监听
	ExMessage msg; // 鼠标消息
	while (1)
	{
		msg = getmessage(EX_MOUSE);	// 获取消息输入		

		// 如果鼠标位于按钮区域
		if (btn.isOn(msg.x, msg.y))
		{
			btn.eventLoop(); // 进入按钮的事件循环
		}
	}

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述
这次我们定义了一个鼠标消息,加了一段循环,然后它就能响应鼠标操作了,拥有了悬浮和点击效果。其实就是利用一个循环来实时监测鼠标消息,当鼠标位于按钮所在区域时进入按钮的事件循环,事件循环的内容就是按钮对鼠标的操作进行响应,你可以不必了解事件循环的具体内容,只需要知道只有进入控件的事件循环中,控件才能对鼠标和键盘的操作进行响应,明白这一点就够了。

好了,现在我们拥有了一个外观效果非常完善的按钮,但是别忘了,按钮存在的目的是为了让用户点击后实现某个效果,我们目前的按钮还只是一个空按钮,还没有对它绑定点击事件,下面我们继续进行功能上的完善,实现点击后展示一段文本的功能(当然,在实际的业务场景下,可能是点击按钮进行搜索,或是点击进行界面切换,功能由我们自己定制,我们这里为了方便只演示点击按钮展示文本的功能)。

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

// 显示文本
void showText()
{
	settextcolor(BLACK); // 设置文本颜色为黑色
	outtextxy(810, 460, L"用户点击了按钮"); // 在坐标(810,460)下显示文本
}

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT); // 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	Button btn(820, 320, 120, 40); // 创建一个宽120,高40的按钮,坐标为(820,320)
	btn.setText(L"点击");
	btn.bindOnClick(showText); // 为按钮绑定showText函数作为点击事件
	btn.show(); // 显示按钮

	// 整个界面的事件循环监听
	ExMessage msg; // 鼠标消息
	while (1)
	{
		msg = getmessage(EX_MOUSE); // 获取消息输入	

		// 如果鼠标位于按钮区域
		if (btn.isOn(msg.x, msg.y))
		{
			btn.eventLoop();
		}
	}
	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述
我们定义了一个showText函数,它的功能很简单,就是显示文本(注意,如果不设置文本颜色的话,默认是白色,与背景融为一体,则看不出任何效果,这是一个常见的坑),然后为按钮绑定showText函数作为点击事件。

到现在为止,我们就实现出了一个非常完善且具有现代化风格的按钮,你可以按照项目的需求为按钮绑定相应的点击事件。

注意区分界面的事件循环监听和控件的事件循环监听,界面的事件循环监听是一个大while循环,负责监听整个界面中鼠标和键盘对所有控件的操作,界面中所有的控件判断是否进入事件循环的语句都要放在这个大while循环中。


输入框

创建一个文本输入框。

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT);	// 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	Input input(800, 320, 170, 30); // 创建一个宽170,高30的按钮,坐标为(800,320)
	input.show();

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述

这样就创建好了一个输入框,但它还什么都做不了,别着急,让我们为它注入灵魂。

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT);	// 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	Input input(800, 320, 170, 30); // 创建一个宽170,高30的按钮,坐标为(800,320)
	input.show();

	// 整个界面的事件循环监听
	ExMessage msg; // 鼠标消息
	while (1)
	{
		msg = getmessage(EX_MOUSE);			// 获取消息输入

		// 如果鼠标位于输入框所在区域
		if (input.isOn(msg.x, msg.y))
		{
			if (msg.message == WM_LBUTTONDOWN) // 鼠标点击
			{
				input.eventLoop(); // 进入输入框的事件循环
			}
		}
	}

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述

与按钮相同,我们用循环实时监听鼠标消息,当鼠标位于输入框所在区域且鼠标进行了点击操作后进入输入框的事件循环,然后就可以响应鼠标和键盘操作了,即用户就可以正常输入了。

那用户输入后怎样获取输入的文本内容呢?我们要是拿不到用户输入的内容,那输入框就没有存在的意义了,所以我们的下一步操作是获取用户的输入内容,请看:

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT); // 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	Input input(800, 320, 170, 30); // 创建一个宽170,高30的按钮,坐标为(800,320)
	input.show();

	// 整个界面的事件循环监听
	ExMessage msg; // 鼠标消息
	while (1)
	{
		msg = getmessage(EX_MOUSE); // 获取消息输入

		// 如果鼠标位于输入框所在区域
		if (input.isOn(msg.x, msg.y))
		{
			if (msg.message == WM_LBUTTONDOWN)
			{
				input.eventLoop(); // 进入输入框的事件循环

				// 获取输入框文本,并进行显示
				settextcolor(BLACK);
				wchar_t* text = input.text();
				outtextxy(800, 380, text);
			}
		}
	}

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述

我们使用Input的text函数获取到用户输入的文本,该函数的返回值是一个wchar_t类型的指针,如果你认为wchar_t是一个新数据类型那就大错特错了,不过是char在Unicode编码下的新形式而已,我们用一个wchar_t类型的指针接收返回值,然后进行文本展示。为什么要将获取文本的操作放在进入输入框的事件循环结束后呢,因为事件循环结束意味着用户的本轮输入结束,所以在这个时候获取文本再合适不过了,那为什么放在循环中呢,因为用户可能进行多轮输入,要确保每一轮输入都能够获取到,并覆盖之前的旧输入。

现在的输入框是一个普通输入框,用户输入的文本会明文显示,那你可能会说了,我想做一个登录界面,需要用到密码输入框,让用户在输入密码时不明文显示,而是用星号隐藏,这又该怎么做呢?放心,我已经替你们考虑到了,只需要加一行代码就可以搞定了,请看:

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT);	// 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	Input input(800, 320, 170, 30); // 创建一个宽170,高30的按钮,坐标为(800,320)
	input.setPassword(1); // 设置为密码输入框
	input.show();

	ExMessage msg; // 鼠标消息
	while (1)
	{
		msg = getmessage(EX_MOUSE);			// 获取消息输入

		// 如果鼠标位于输入框所在区域
		if (input.isOn(msg.x, msg.y))
		{
			if (msg.message == WM_LBUTTONDOWN)
			{
				input.eventLoop(); // 进入输入框的事件循环

				// 获取输入框文本,并进行显示
				settextcolor(BLACK);
				wchar_t* text = input.text();
				outtextxy(800, 380, text);
			}
		}
	}

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述
现在你可能又有话要说了,我不仅需要密码输入框用来做登录界面,我还想在输入框中设置提示文本。好的没问题,只需 一行代码即可设置占位文本,请看:

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT);	// 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	Input input(800, 320, 170, 30); // 创建一个宽170,高30的按钮,坐标为(800,320)
	input.setHolderText(L"占位文本"); // 设置占位文本
	input.show();

	// 整个界面的事件循环监听
	ExMessage msg; // 鼠标消息
	while (1)
	{
		msg = getmessage(EX_MOUSE);			// 获取消息输入

		// 如果鼠标位于输入框所在区域
		if (input.isOn(msg.x, msg.y))
		{
			if (msg.message == WM_LBUTTONDOWN)
			{
				input.eventLoop(); // 进入输入框的事件循环

				// 获取输入框文本,并进行显示
				settextcolor(BLACK);
				wchar_t* text = input.text();
				outtextxy(598, 380, text);
			}
		}
	}

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述
好了,现在我们既实现了普通输入框,又实现了密码输入框,既可以给输入框设置占位文本,又可以获取到用户输入,可以说是功能非常完善了,快用到自己的项目中吧。


弹框

说起弹框也许你大致有个概念,但并不是完全清楚它到底是什么东西,下面我来展示一下,你一看便知。
请添加图片描述
这是第一种类型的弹框,我们可以称它为确认消息弹框,确认消息弹框的功能为当用户做出重要操作时,给出一段提示消息,让用户二次确认或取消,例如删除某条数据,为了防止用户误操作,一个合格的软件系统应该给出一个确认消息弹框。再来看看下面这个。

请添加图片描述

这是第二种类型的弹框,我们可以称它为提交内容弹框,提交内容弹框的功能为让用户在弹框中输入并提交信息,例如添加一条数据,就需要给出一个提交内容弹框。

下面我们来分别演示如何使用上述两种类型的弹框。

第一种:确认消息弹框

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

Message message(WIN_WIDTH, WIN_HEIGHT, 520, 145); // 创建宽520,高145的弹框,并传入窗口的宽和高
Button messageBtn(800, 320, 120, 40); // 创建宽120,高40的按钮,坐标为(800,320)

// 打开弹框
void openMessage()
{
	message.open(INFO); // 打开弹框,传入INFO参数表明这是一个确认消息弹框
}

// 关闭弹框
void closeMessage()
{
	message.close(); // 关闭弹框
}

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT);	// 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	message.setTitle(L"提示"); // 设置弹框标题
	message.setText(L"你打开了确认消息弹框"); // 设置弹框文本
	message.enterBtn()->bindOnClick(closeMessage); // 获取到弹框的确认按钮并绑定hideMessage函数为点击事件
	message.cancelBtn()->bindOnClick(closeMessage); // 获取到弹框的取消按钮并绑定hideMessage函数为点击事件

	messageBtn.bindOnClick(openMessage); // 为按钮绑定showMessage函数为点击事件
	messageBtn.show(); // 显示按钮

	int messageShow = message.isShow(); // 弹框是否处于显示状态

	ExMessage msg; // 鼠标消息
	while (1)
	{
		msg = getmessage(EX_MOUSE);			// 获取消息输入

		// 先判断有没有弹框,如果有则优先进入弹框的事件循环
		if (messageShow)
		{
			// 如果鼠标位于弹框所在区域
			if (message.isOn(msg.x, msg.y))
			{
				message.eventLoop(); // 进入弹框的事件循环
				messageShow = message.isShow(); // 获取弹框的状态(显示/隐藏)
			}
		}
		else
		{
			// 如果鼠标位于按钮所在区域
			if (messageBtn.isOn(msg.x, msg.y))
			{
				messageBtn.eventLoop(); // 进入按钮的事件循环
				messageShow = message.isShow(); // 获取弹框的状态(显示/隐藏)
			}
		}
	}

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述

弹框应当是动态显示的,即在用户按下某个按钮后显示。因此除了创建弹框外,还需要创建一个按钮,并且定义两个函数,这两个函数的功能分别为显示、隐藏弹框。由于函数中需要用到message,因此将message作为全局变量,这里我把messageBtn同样也作为全局变量。

为messageBtn绑定显示弹框的点击事件,值得注意的是,弹框右下角有两个按钮,也需要绑定点击事件,我这里绑定的隐藏弹框的点击事件(在实际业务场景中根据需求自行设计)。

我们还需要一个int变量来标识弹框的状态。使用Message的isShow函数可以获取到弹框的状态,1为显示,0为隐藏。在弹框的事件循环结束后和按钮的事件循环结束后分别获取弹框的状态,因为弹框状态的改变取决于弹框事件循环中右下角两个按钮的点击操作和按钮事件循环中的点击操作。在整个界面的事件循环监听中,需要优先判断弹框的状态,如果弹框为显示状态,则根据鼠标的状态判断进入弹框的事件循环中,只有当弹框隐藏时才判断是否进入其他控件的事件循环。

确认消息弹框的核心内容:

  • show函数传入参数为INFO
  • 使用setText函数设置文本

弹框是所有控件中最复杂的控件,如果有些细节不太理解也没有关系,以项目为驱动,会使用即可。

第二种:提交内容弹框

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

Message message(WIN_WIDTH, WIN_HEIGHT, 520, 345); // 创建宽520,高145的弹框,并传入窗口的宽和高
Button messageBtn(800, 120, 120, 40); // 创建宽120,高40的按钮,坐标为(800,120)

// 弹框内输入框
Input input1(0, 0, 150, 35);
Input* input1Ptr = &input1;
Input input2(0, 0, 150, 35);
Input* input2Ptr = &input2;
Input input3(0, 0, 150, 35);
Input* input3Ptr = &input3;

// 打开弹框
void openMessage()
{
	message.open(CONTENT); // 打开弹框,传入CONTENT参数表明这是一个提交内容弹框
}

// 关闭弹框
void closeMessage()
{
	message.close(); // 关闭弹框
}

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT); // 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	message.setTitle(L"提示"); // 设置弹框标题
	// 弹框内添加文本
	message.addLabel(L"书名");
	message.addLabel(L"作者");
	message.addLabel(L"出版时间");
	// 弹框内添加输入框
	message.addInput(input1Ptr);
	message.addInput(input2Ptr);
	message.addInput(input3Ptr);
	message.enterBtn()->bindOnClick(closeMessage); // 获取到弹框的确认按钮并绑定hideMessage函数为点击事件
	message.cancelBtn()->bindOnClick(closeMessage); // 获取到弹框的取消按钮并绑定hideMessage函数为点击事件

	messageBtn.bindOnClick(openMessage); // 为按钮绑定showMessage函数为点击事件
	messageBtn.show(); // 显示按钮

	int messageShow = message.isShow(); // 弹框是否处于显示状态

	ExMessage msg; // 鼠标消息
	while (1)
	{
		msg = getmessage(EX_MOUSE); // 获取消息输入

		// 先判断有没有弹框,如果有则优先进入弹框的事件循环
		if (messageShow)
		{
			if (message.isOn(msg.x, msg.y))
			{
				message.eventLoop(); // 进入弹框的事件循环
				messageShow = message.isShow(); // 获取弹框的状态(打开/关闭)

				// 获取CONTENT弹框中输入框1的文本,并显示
				settextcolor(BLACK);
				wchar_t* input1Text = input1Ptr->text();
				wchar_t* input2Text = input2Ptr->text();
				wchar_t* input3Text = input3Ptr->text();
				outtextxy(500, 50, input1Text);
				outtextxy(500, 100, input2Text);
				outtextxy(500, 150, input3Text);
			}
		}
		else
		{
			// 如果鼠标位于按钮所在区域
			if (messageBtn.isOn(msg.x, msg.y))
			{
				messageBtn.eventLoop(); // 进入按钮的事件循环
				messageShow = message.isShow(); // 获取弹框的状态(打开/关闭)
			}
		}
	}

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述
提交内容弹框与确认消息弹框大都类似。

这里为什么要先创建输入框,再创建输入框指针指向输入框呢,因为addInput函数的参数为Input*,即传参必须传递输入框指针。

提交内容弹框的核心内容:

  • open函数参数为CONTENT
  • 需要使用addLabel函数添加文本
  • 需要使用addInput函数添加输入框
  • 在弹框的事件循环结束后获取输入框中的文本

这里给的示例为获取文本后显示,在实际的业务场景中大多需要将获取的文本保存起来,或存入文件或存入数据库中。


侧边导航栏

侧边导航栏也是一个常用的组件,它是由侧边导航栏和侧边导航栏按钮组成的,换句话说,侧边导航栏按钮存在的意义就是为侧边导航栏服务。我们下面来说明如何使用导航栏组件,其中会用到导航栏按钮组件。

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT);	// 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	// 导航栏
	Navbar nav(0, 0, 200, WIN_HEIGHT); // 创建导航栏,宽200,高与窗口高度一致,坐标为(0,0)

	// 导航栏按钮
	// 创建3个宽200,高50的导航栏按钮
	NavButton navBtn1(200, 50);
	NavButton* navBtn1_ptr = &navBtn1;
	NavButton navBtn2(200, 50);
	NavButton* navBtn2_ptr = &navBtn2;
	NavButton navBtn3(200, 50);
	NavButton* navBtn3_ptr = &navBtn3;

	// 导航栏
	nav.setTitleText(L"侧边导航栏"); // 设置导航栏头部文本
	// 设置导航栏按钮文本
	navBtn1_ptr->setText(L"首页");
	navBtn2_ptr->setText(L"账户管理");
	navBtn3_ptr->setText(L"图书管理");
	// 导航栏内添加按钮
	nav.addNavButton(navBtn1_ptr);
	nav.addNavButton(navBtn2_ptr);
	nav.addNavButton(navBtn3_ptr);
	nav.show(); // 显示导航栏

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述
这样就创建了一个有三个按钮的侧边导航栏,有三个要点:

  • 创建导航栏是高度要与窗口高度一致,坐标定为(0,0)
  • 各个导航栏按钮大小一致
  • 按钮在导航栏中排列的次序只与添加按钮的先后次序有关

由于还没有加界面的事件循环监听,因此现在导航栏的按钮还不能对鼠标做出响应,我们继续。

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT);	// 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	// 导航栏
	Navbar nav(0, 0, 200, WIN_HEIGHT); // 创建导航栏,宽200,高与窗口高度一致,坐标为(0,0)

	// 导航栏按钮
	// 创建3个宽200,高50的导航栏按钮
	NavButton navBtn1(200, 50);
	NavButton* navBtn1_ptr = &navBtn1;
	NavButton navBtn2(200, 50);
	NavButton* navBtn2_ptr = &navBtn2;
	NavButton navBtn3(200, 50);
	NavButton* navBtn3_ptr = &navBtn3;

	// 导航栏
	nav.setTitleText(L"侧边导航栏"); // 设置导航栏头部文本
	// 设置导航栏按钮文本
	navBtn1_ptr->setText(L"首页");
	navBtn2_ptr->setText(L"账户管理");
	navBtn3_ptr->setText(L"图书管理");
	// 导航栏内添加按钮
	nav.addNavButton(navBtn1_ptr);
	nav.addNavButton(navBtn2_ptr);
	nav.addNavButton(navBtn3_ptr);
	nav.show(); // 显示导航栏

	// 界面的事件循环监听
	ExMessage msg; // 鼠标消息
	while (1)
	{
		msg = getmessage(EX_MOUSE); // 获取消息输入

		// 鼠标位于导航栏所在区域
		if (nav.isOn(msg.x, msg.y))
		{
			nav.eventLoop(); // 进入导航栏的事件循环监听
		}
	}

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述
值得注意的是,只需要对导航栏判断是否进入事件循环监听即可,并不需要一一对按钮做判断,因为导航栏按钮是包含在导航栏中的。

这里创建导航栏按钮指针是因为 addNavButton 函数需要接收NavButton*类型的参数。

除此之外,我们需要对每个导航栏按钮绑定点击事件,这与普通按钮的绑定操作完全一致,因此不再演示,如果你不太清楚这部分内容可以去看按钮的部分,在实际业务场景中一般绑定的点击事件为切换界面,自行实现即可。


列表

如果你开发一个软件系统,尤其是管理系统,那列表是绝对无法避免的组件,很多初学者都会卡在这一块,后来可能干脆表格不打了,直接一行一行输出文本,其实这还真不是犯懒,因为这对初学者而言确实是个难题。不过,用了EUI组件库,这种问题就不叫问题了,下面请看示例:

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

// 表格数据结构体
typedef struct {
	wchar_t id[MAX_TEXT_LEN];
	wchar_t bookName[MAX_TEXT_LEN];
	wchar_t author[MAX_TEXT_LEN];
	wchar_t time[MAX_TEXT_LEN];
}list;

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT); // 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	Table tb(230, 230, 1430, 6, 4); // 创建表格,宽1430,6行4列,坐标为(230,230)
	headerList hl[MAX_COL]; // 表头

	int width[] = { 10,20,20,50 }; // 设定表格宽度比例,单位为%,和为100
	tb.setGridWidth(width);

	// 设定表头,4列
	wcscpy_s(hl[0].header, L"序号");
	wcscpy_s(hl[1].header, L"书名");
	wcscpy_s(hl[2].header, L"作者");
	wcscpy_s(hl[3].header, L"时间");

	list data[4]; // 表格数据
	int listCnt = 2; // 表格数据条数
	// 设定表格数据
	wcscpy_s(data[0].id, L"01");
	wcscpy_s(data[0].bookName, L"C程序设计语言");
	wcscpy_s(data[0].author, L"布莱恩");
	wcscpy_s(data[0].time, L"2023-01-23");
	wcscpy_s(data[1].id, L"02");
	wcscpy_s(data[1].bookName, L"深入理解计算机系统");
	wcscpy_s(data[1].author, L"兰德尔");
	wcscpy_s(data[1].time, L"2023-06-02");

	tableList* tl = tb.tableListCont(); // 获取tableList指针
	// 将表格数据一对一映射到tableList中
	for (int i = 0; i < listCnt; i++)
	{
		wcscpy_s(tl->col[0], data[i].id);
		wcscpy_s(tl->col[1], data[i].bookName);
		wcscpy_s(tl->col[2], data[i].author);
		wcscpy_s(tl->col[3], data[i].time);
		tl++;
	}
	tb.show(hl);

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述

在C语言开发的软件系统中,要在表格中展示的数据通常都存放在结构体数组中,这里我定义了一个结构体数组,并使用wcscpy_s函数为其赋初值,如果你是第一次见到这个函数心里可能还有一点畏惧,看起来好难的样子,其实不用担心,我想你一定用过strcpy这个函数,就是字符数组的拷贝函数,即把一个字符数组的内容拷贝到另一个字符数组中,这个函数也是一样的,它可以把字符串常量拷贝到wchar_t数组中,或是wchar_t数组之间的拷贝。

你需要定义一个元素个数和表格列数相同的int型数组,设定表格宽度比例,单位为%,和为100,将该数组作为参数传入setGridWidth函数中,这样就得到了自定义列宽的表格,下面就要为其填入数据了。

使用tableListCont函数获取到tableList类型的指针,再将表格数据一对一映射到tableList中,这段代码是一套固定的写法,大家可以直接照搬,再根据你项目中表格数据的不同微微做调整。由于这块的原理稍微有些复杂,所以并不要求大家掌握,只要会使用即可。

注意,表格是一个用于展示的组件,并不需要与鼠标交互,因此没有事件循环监听。


弱提示框

也许你是第一次听到这个词语:弱提示框,不免心生疑惑,什么是弱提示框。弱提示框顾名思义就是不含任何选择性、强制性的提示框,只是给你一个弱弱的提示,告诉你发生了什么事,这是一个交互优秀的软件系统所必需的,下面来看一个示例:

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

Toast toast(WIN_WIDTH, 30, 350, 50); // 创建一个宽350,高50的弱提示框,y坐标为30,传入窗口宽度
Button toastBtn(820, 180, 120, 40); // 创建一个宽120,高40的按钮,坐标为(820,180)

void showToast()
{
	toast.show(SUCCESS); // 显示弱提示框,类型为SUCCESS
}

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT);	// 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	toast.setText(L"这是一段成功消息"); // 设置文本

	// 弱提示框按钮
	toastBtn.setText(L"按钮");
	toastBtn.bindOnClick(showToast); // 绑定点击事件
	toastBtn.show();

	// 界面的事件循环监听
	ExMessage msg; // 鼠标消息
	while (1)
	{
		msg = getmessage(EX_MOUSE); // 获取消息输入

		// 鼠标位于按钮所在区域
		if (toastBtn.isOn(msg.x, msg.y))
		{
			toastBtn.eventLoop(); // 进入导航栏的事件循环监听
		}
	}

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述
弱提示框与弹框类似,也是一个动态显示的组件,因此需要一个按钮来触发,定义一个显示弱提示框的函数与按钮进行绑定,由于函数中要使用toast,因此我将弱提示框作为全局变量,同样把按钮也放在了全局,然后,我们需要进行界面的事件循环监听,判断是否进入按钮的事件循环中。

弱提示框有两种类型,成功类型SUCCESS和警告类型WARNING,分别用来展示成功消息和警告消息,类型需要在show函数中体现,即给show函数传参SUCCESS或WARNNING。当然,你还需要为弱提示框设置文本作为你的消息内容。

上面的示例是SUCCESS类型的成功提示框,下面来演示WARNING类型的警告提示框,它们在使用上仅仅只有传参的区别,当然,警告框的文本肯定与成功框有所不同,请看:

#include "EUI/EUI.h" // 引入EUI组件库

#define WIN_WIDTH 1800 // 窗口宽度
#define WIN_HEIGHT 900 // 窗口高度

Toast toast(WIN_WIDTH, 30, 350, 50); // 创建一个宽350,高50的弱提示框,y坐标为30,传入窗口宽度
Button toastBtn(820, 180, 120, 40); // 创建一个宽120,高40的按钮,坐标为(820,180)

void showToast()
{
	toast.show(WARNING); // 显示弱提示框,类型为WARNNING
}

int main()
{
	initgraph(WIN_WIDTH, WIN_HEIGHT);	// 创建绘图窗口

	// 设置背景色
	setbkcolor(RGB(255, 255, 255));
	cleardevice();

	toast.setText(L"这是一段警告消息"); // 设置文本

	// 弱提示框按钮
	toastBtn.setText(L"按钮");
	toastBtn.bindOnClick(showToast); // 绑定点击事件
	toastBtn.show();

	// 界面的事件循环监听
	ExMessage msg; // 鼠标消息
	while (1)
	{
		msg = getmessage(EX_MOUSE); // 获取消息输入

		// 鼠标位于按钮所在区域
		if (toastBtn.isOn(msg.x, msg.y))
		{
			toastBtn.eventLoop(); // 进入导航栏的事件循环监听
		}
	}

	_getch();				// 按任意键继续
	closegraph();			// 关闭绘图窗口
	return 0;
}

请添加图片描述
注意,弱提示框是一个用于展示的组件,并不需要与鼠标进行交互,因此没有事件循环监听,这里的事件循环监听是按钮的,一定要区分清楚。


小结

好了,这就是快速上手部分的全部内容了,我带着大家挨个组件循序渐进地进行了使用方法的演示和讲解,虽然我认为自己讲的已经足够详细且通俗易懂了,但可能对于初学者来说难免会有些不太理解的地方,现阶段不必过于纠结,核心是会用、会用、会用,重要的事情说三遍。图形库、组件库只是工具,对于工具我们大多数时候只要会使用就足够了,并不需要深入它的原理和底层,切勿本末倒置。当然,如果你想做一个新的工具,那你就需要研究各种各样工具的设计思想、底层原理,这个时候对现有工具的要求可就不是会用这么简单了。所以说呢,学习这件事是一件非常灵活的事,如何学习、学到什么程度完全取决于你学习的目的,要把有限的精力花在刀刃上。希望EUI组件库带给你的不仅仅是帮助你开发软件系统这一件事,希望你能从中体会到合理高效的学习方法和面对新工具、新事物的处理办法,在你日后的软件开发生涯中帮助你最大程度的提高效率。

当然,如果你并不满足于会使用EUI组件库,而非常好奇我是如何实现出各种各样美观的组件的,那么在你基本掌握了C++后,完全可以学习EUI的设计思想和实现方法,这是一个非常轻量级的库,总计代码不超过2000行,非常适合C++初学者学习,这样你不仅会使用它,也可以改造它,并且可以融入自己的思想和理念,在这期间你的能力一定会得到相当大的提升,而这也正是软件开发的魅力所在。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1207675.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

做C语言的编程题总是想骂人怎么办?

做C语言的编程题总是想骂人怎么办&#xff1f; 可能C语言的编程题难住了您吧&#xff0c;导致情绪激烈不平静&#xff0c;那么做C语言的编程题可以顺利-些吗? 当然有一些方法可是现实此目标的:最近很多小伙伴找我&#xff0c;说想要一些C语言的资料&#xff0c;然后我根据自己…

K8S的基础知识

K8S的意义与入门 专有名词 容器:包含了运行一个应用程序所需要的所有东西,包括:代码、运行时、各种依赖和配置。pod:K8s调度的最小单元,包含一个或多个容器。一个容器组中的容器具有紧密耦合性,共享资源,存储空间和IP。即同一个容器组中的容器可以通过localhost:xxx访问…

【C++初阶(八)】C/C++内存管理详解

本专栏内容为&#xff1a;C学习专栏&#xff0c;分为初阶和进阶两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握C。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;C &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&…

C 语言指针怎么理解?

今日话题&#xff0c;C 语言指针怎么理解&#xff1f;让我用更简洁的方式来表达这个内容&#xff1a;就像桌面上的快捷方式一样&#xff0c;指针也可以有多层引用。我们可以将指针比作快捷方式的图标&#xff0c;快捷方式可以指向游戏&#xff08;普通指针&#xff09;&#xf…

人工智能基础_机器学习030_ElasticNet弹性网络_弹性回归的使用---人工智能工作笔记0070

然后我们再来看elastic-net弹性网络,之所以叫弹性是因为,他融合了L1和L2正则,可以看到 他的公式 公式中有L1正则和L2正则两个都在这个公式中 可以看到弹性网络,在很多特征互相联系的时候,非常有用,比如, 相关性,如果数学好,那么物理也好,如果语文好,那么英语也好 这种联系 正…

制作这种在线宣传画册,可轻松收获客户!

制作企业宣传画册&#xff0c;首先要了解企业制作宣传画册的需求以及展示方向&#xff0c;如今互联网时代&#xff0c;宣传画册的制作也应该要创新&#xff0c;而制作一本在线电子宣传画册用于线上宣传是非常有必要的。如何制作呢&#xff1f; 我们 可以使用FLBOOK平台在线制作…

bfc 简单理解及应用

1、概念 bfc 是 Block formatting context 的缩写&#xff0c;也就是块级格式化上下文&#xff0c;就是让元素形成独立的渲染区域&#xff0c;bfc容器内部的渲染对外部不会有影响。 2、形成bfc的常见条件 浮动 设置元素具有float: left/right绝对/固定定位&#xff1a;posit…

keepalived 的安装部署及使用详细完整版

架构 1.安装 yum install keepalived -ysystemctl enable keepalivedsystemctl restart keepalivedsystemctl status keepalived2.部署配置样例 vim /etc/keepalived/keepalived.conf global_defs {router_id PROXYSQL_HAscript_user rootenable_script_security } vrrp_scri…

js案例:跟随鼠标移动的大虫子

目录 效果预览图 整体思路 完整代码 效果预览图 整体思路 rang 函数用于生成指定范围内的随机整数。 通过循环&#xff0c;创建了50个div元素&#xff0c;每个div都有一个不同的数字和随机的背景颜色。 给每个div元素添加了名为 "ball" 的类名。 通过 documen…

为什么说葡萄酒越复杂,越有可能陈年?

大家都觉得老酒更好&#xff0c;对吧&#xff1f;一瓶酒在黑暗的洞穴里放得越久&#xff0c;瓶子慢慢积灰&#xff0c;我们喝的时候就越好喝&#xff0c;对吗&#xff1f;其实是不对的&#xff01;葡萄酒陈酿的根本原因是为了让它的味道更好&#xff0c;或者更确切地说让风味发…

一文懂得电源模块过温保护测试方法 ate测试软件助力测试

过温保护测试是电源模块保护功能测试项目之一&#xff0c;也是电源模块测试的重要测试指标&#xff0c;以保证电源模块过温保护功能正常&#xff0c;确保电源模块不受损坏。用ate测试软件测试电源模块过温保护&#xff0c;不仅可以保证测试结果的准确性&#xff0c;还可以多维度…

SAP 70策略测试简介

在前面的文章中我们已经测试了10、11、20、40、50、52、60、62策略的测试,接下来我们需要对70策略进行测试,很多的项目中也都会用到70策略。 70策略是一种比较常见的、基于按库存且主要用于半成品或者原材料的计划策略。 我们还是按照之前的惯例,先看下70策略的后台配置 我…

书单 | 11月程序员新书播报

11月最新上架计算机书籍 1、人工智能&#xff08;第3版&#xff09; 美国经典人工智能教材第3版&#xff0c;人工智能的百科全书&#xff0c;新增深度学习及人工智能编程等内容&#xff0c;理论阐释结合动手实践&#xff0c;附赠PPT课件、配套视频及代码文件。 1.人工智能经典…

Linux线程池

文章目录&#xff1a; 线程池了解线程池模拟实现 线程池了解 线程池是一种常见的线程使用模式。线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。而线程池维护着多个线程&#xff0c;等待着监督管理者分配可并发执行的任务&#xff0c;以避免在处理短时间任…

Python爬虫过程中DNS解析错误解决策略

在Python爬虫开发中&#xff0c;经常会遇到DNS解析错误&#xff0c;这是一个常见且也令人头疼的问题。DNS解析错误可能会导致爬虫失败&#xff0c;但幸运的是&#xff0c;我们可以采取一些策略来处理这些错误&#xff0c;确保爬虫能够正常运行。本文将介绍什么是DNS解析错误&am…

JLMR Micro Super Resolution Algorithm国产微超分算法DEMO

一、简介 目前&#xff0c;做超分算法基本还是以AI训练为主&#xff0c;但是AI基本上都是基于既定场景的训练。而传统的算法基本上都是利用上下文的纹理预测、插值等方案&#xff0c;在图像放大过程中会出现模糊&#xff0c;或马赛克等现象。 我们基于加权概率模型&#xff0c…

后端接口性能优化分析-1

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码&#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44d;三连支持&…

SQLite3 数据库学习(一):数据库和 SQLite 基础

参考引用 SQL 必知必会SQLite 权威指南&#xff08;第二版&#xff09;关系型数据库概述 1. 数据库基础 1.1 什么是数据库 数据库&#xff08;database&#xff09;&#xff1a;保存有组织的数据的容器&#xff08;通常是一个文件或一组文件&#xff09; 可以将其想象为一个文…

谷歌提出AGI的6大原则,和5大能力等级

随着ChatGPT等大模型的出现,AGI概念正在从哲学层面快速转向实际应用落地&#xff0c;并且ChatGPT已经展示出了初级AGI的功能&#xff08;如AutoGPT&#xff09;,有不少专家认为&#xff0c;AGI时代可能在10年内到来。 因此&#xff0c;需要一个明确的技术框架来讨论和衡量不同…

图片转excel的三种方案(电脑、手机)

图片怎么转换成excel文件呢?用金鸣表格文字识别是最便捷、最佳的解决方案。也许有些同学会问,那我用手工也可以解决呀,干吗要用软件?这么想就不对了,手工做不但要做表格线,还要手工打字,非常麻烦,而且容易出错,特别是对于数字多的图片,更是要命,现在有金鸣识别就不用那么麻烦…