EGE基础:输入篇

EGE专栏:EGE专栏

EGE基础:输入篇

  EGE中的输入是基于 <ege/sys_edit.h> 头文件中是 sys_edit 类的。这个类提供一个输入框,可以用来输入。

  缺点是sys_edit 类中检测是否获得焦点的 isfocus() 失效,那创建多个输入框时,就不可以通过回车来获取输入内容,因为不知道焦点在哪个输入框。
  如果能检测焦点,那输入后回车就可以判断焦点在哪个输入框,然后获取该输入框的内容。现在不能检测,那就只能 通过添加按钮 的方式,当点击某个按钮时,就获取对应的输入框的内容。

一、sys_edit 类

  使用前需要先包含 sys_edit.h头文件。sys_edit.h头文件是放在ege文件夹下,所以使用#include <ege/sys_edit.h>
  sys_edit.h 头文件需要在graphics.hege.h之后包含,不能放在它们的前面。

  包含 sys_edit.h 头文件如下所示:

#include <graphics.h>
#include <ege/sys_edit.h>

1. 头文件检查

  sys_edit 类 定义在EGE的 sys_edit.h 头文件中,可能有些人按照的是别人的教程安装的EGE,所以头文件路径不正确,显示 No such File or Directory 。现在统一按照EGE安装包中的文件放置。

  可以看到,EGE安装包中,在include 目录下有两个头文件和一个ege文件夹,ege文件夹中有五个头文件,这些都是EGE自带的控件。所以复制头文件时,直接把include文件夹中的文件全选,复制到安装目录的inlcude目录即可
在这里插入图片描述
在这里插入图片描述

  • 然后到安装目录的include目录检查你的头文件(这个是VS2017,根据自己使用的IDE来查看)
    在这里插入图片描述
    在这里插入图片描述

二、 sys_edit类的使用

  需要包含 <ege/sys_edit.h> 头文件,需要注意的是, sys_edit.h 头文件需要在graphics.hege.h之后包含,不能放在它们的前面。

#include <graphics.h>
#include <ege/sys_edit.h>

  输入框使用前需要创建并进行一些设置,设置示例如下所示。

sys_edit editBox;
editBox.create(false);						//创建,false表示单行,true表示多行
editBox.move(100, 100);						//设置位置
editBox.size(fontHeight * 10, fontHeight);	//设置尺寸
editBox.setmaxlen(10);						//设置允许输入的字符数
editBox.visible(true);						//设置可见性
editBox.setfocus();							//设置获取焦点

  下面是具体的使用步骤。

1. 使用步骤

1.1 输入框的创建

  先创建 sys_edit 对象

sys_edit editBox;

  然后调用成员函数 create() 来创建输入框。

函数声明

int sys_edit::create(bool multline);

  函数参数为 bool 型,控制输入框是多行输入框还是单行输入框。

参数: bool型

  • true 表示多行输入框,这样输入超过输入框宽度时会自动换行,并且可以输入回车换行。
  • false 表示单行输入框,即使超过输入框长度,依然不会换行,都在同一行内,无法输入回车进行换行。

创建输入框

editBox.create(false);

1.2 设置输入框参数

1.2.1 必要设置
1.2.1.1 输入框位置

  设置输入框左上角在窗口上的位置坐标,单位为像素。

editBox.move(x, y);		//设置输入框位置
1.2.1.2 输入框大小

  设置输入框的宽高,单位为像素。

editBox.size(width, height);	//设置输入框大小

  这个宽度大小是包含输入框边框的,所以如果你正好设置为文字的高度,那么部分文字会被遮挡,输入框高度可以多加 8。

editBox.setfont(fontHeight, 0, "");		//设置输入框字体高度
editBox.size(editBoxWidth, fontHeight + 8);	//设置输入框大小
1.2.2 非必要设置

  这里是一些其它设置,可以根据需要进行设置

1.2.2.1 允许输入的最大字符数

  设置后,输入的字符数量不会超过这个值。当输入框中字符数量达到最大长度后,其它字符无法输入到输入框中。(中文字符和英文字符都算做一个字符)

editBox.setmaxlen(20);
1.2.2.2 输入框背景颜色
editBox.setbgcolor(输入框背景颜色);
1.2.2.3 输入框文字的颜色
editBox.setcolor(输入框文字颜色);
1.2.2.4 输入框文字的字体

  设置相应输入框的文字字体,和全局字体无关。
  参数是(height, width, “字体”)。(width为0时,表示文字在设置的高度下按照原比例所对应的宽度; width不为0时则强制字体变形为对应宽度。)

editBox.setfont(20, 0, "宋体");		
1.2.2.5 只读模式

  可以控制输入框是否允许用户输入。设置为只读模式后,输入框不允许用户输入。(输入框默认为允许输入)

editBox.setreadonly(true);		//设置为只读模式,不允许输入
editBox.setreadonly(false);		//设置输入框允许输入

1.3 设置输入框可见

  创建好后, 需要调用成员函数visible() 设置输入框可见,否则是看不到输入框的,因为输入框创建后默认是隐藏的(设置完成后再进行显示)。
  (如果你用的是19.01版本的EGE, 那应该是 visable() 函数,别问visable是什么单词,问就是visible)

editBox.visible(true);

参数:(bool)

  • true : 输入框可见。
  • false : 输入框隐藏 (默认)

1.4 设置输入框获取焦点 (非必要设置)

可设置输入框获取焦点。输入框获取焦点后,输入框将会有光标闪烁,此时用户可以进行输入。

  • 输入框获取焦点后,用户按下按键便可直接向输入框字符。
  • 不设置获取焦点时,用户需要先用鼠标点击一下输入框,让输入框获取焦点,才能进行输入。
editBox.setfocus();

2. 输入框内容的获取

  输入框内容的获取需要调用成员函数 gettext()

gettext(int maxLen, char* 字符缓冲区首地址); 			//char型
gettext(int maxLen, wchar_t* 字符缓冲区首地址); 		//宽字符型

  其中,参数maxLen 表示字符缓冲区所占内存的大小 (单位为字节)。字符缓冲区可以是char型,也可以是宽字符类型。

  要获取输入框内容,首先需要创建一个字符数组宽字符数组作为缓冲区,用于存储字符串。
  请根据输入的字符数预留好足够的空间大小,如果最大输入N个字符,缓冲区请至少预留2 * (N +1 )个字节的空间大小(汉字占两个字节,加上末尾’\0’字符)

const int buffSize = 100;
char strBuffer[100];

使用示例:

//创建一个字符数组来保存输入框中的内容
const int buffSize = 100;
char strBuffer[100];

//获取输入框的内容,保存到字符数组strBuffer[]中
editBox.gettext(buffSize,  strBuffer);

//可以对得到字符串做其它处理
xyprintf(0, 0, strBuffer);	//输出内容

int a;
sscanf(strBuffer, "%d", &a);	//如果输入框输入的是数字,读取到a中

  这样就获取到了输入框的内容。输入的内容保存在char数组strBuffer[ ]中

2.1 注意事项

  输入框是可以输入汉字的,但汉字在GB2312编码下正常会占两个字节,如果使用用char数组,将占用两个char。使用 printf() 也是可以正常输出的。
  按一次回车键会输入回车符换行符两个字符

2.2 宽字符

  如果你想要不管什么内容,一个字符都占用一个字符变量的大小,那可以使用宽字符类型 wchar_t(宽字符类型占用两个字节)

头文件包含

#include <wchar.h>

宽字符数组

const int buffSize = 100;
wchar_t strBuffer[100] = L"";

宽字符串要使用 L" " 来表示, 而不是 " "

获取输入框内容到宽字符数组缓存中:

editBox.gettext(buffSize, strBuffer);

buffSize是缓存区大小,这个要设置正确,设置的值可以小于缓存区大小,这样缓冲区有剩余部分不使用,但是不能超出缓冲区大小,否则输入框内容多时会出现写入内容越界,容易造成程序崩溃。

  获取宽字符数组长度可以使用 wcslen() 函数, 这个函数在头文件wchar.h 中声明。(即 wide char string length 的缩写)

int len = wcslen(strBuffer);

  使用xyprintf() 输出宽字符串时, 格式字符串也要用 L" " 表示,否则可能会输出不完整。

xyprintf(100, 60, L"输入内容:%s", strBuffer);

3. sys_edit类的其它操作

3.1 设置输入框的内容

使用 settext() 来设置输入框的内容

editBox.settext("输入框内容");

3.2 清空输入框内容

调用 settext(“”) 即可把输入框内容清空(即把内容设为空字符串)

editBox.settext("");

3.3 获取输入框位置和大小

获取输入框位置

editBox.getx();		//获取左上角x坐标
editBox.gety();		//获取左上角y坐标

获取输入框大小

editBox.width();	//获取输入框宽度
editBox.getw();		//获取输入框宽度

editBox.height();	//获取输入框高度
editBox.geth();		//获取输入框高度

3.4 隐藏输入框

  调用 editBox.visible(false) 就能将设置为不可见。

editBox.visible(false);

  如果焦点在输入框上时输入框隐藏,此时焦点仍在输入框上,除非用户点击了窗口,否则用户还是能通过按键继续输入。
  如果想隐藏输入框的同时不允许用户继续输入,可以同时将输入框设置为只读

editBox.visible(false);			//隐藏输入框
editBox.setreadonly(true);		//设置输入框为只读

  当输入框恢复可见时,不要忘记设置允许输入。

editBox.visible(true);			//输入框可见
editBox.setreadonly(false);		//输入框允许输入

3.5 销毁输入框

  如果已经不需要输入框了,可以调用 destroy() 将输入框销毁。这样输入框就没了。

editBox.destroy();

  销毁后,如果想再次输入,需要按照以上流程重新创建。

  需要注意的是,EGE 19.01及之前版本函数名是 destory如果编译错误,说找不到destroy,请改成 editBox.destory()

  sys_edit对象会在超出所在块后自动销毁。 所以一般情况下不需要调用。

4. 输入框说明

4.1 输入框相关的一些事项

  • 输入框作为子窗口位于EGE图形窗口之上,不会被绘图覆盖。
  • 点击输入框,光标闪烁,对应输入框会获取焦点。如果开始没有调用 setfocus(), 那么需要自己点击,输入框才会获取焦点。
  • 在输入框输入的时候依然会EGE图形窗口中产生按键消息,退出帧循环时,可以用flushkey() 清空一下消息队列,以免影响到其它如getch() ,getkey()之类的函数。

4.2 变量的生命周期问题

  对于一个变量,生命周期从程序执行到变量初始化处开始,程序执行到超出变量作用域后结束。
  如果变量是创建在块内,那么运行超出这个块后,这个变量将被销毁。这个在循环中很常见。一个循环需要多次执行语句块,所以会多次进入块、退出块的操作。因此定义在块中局部变量,会被多次创建和销毁。
  按如下代码所示,输入框会被多次创建和销毁,而输入框创建后默认是隐藏的,如果在输入框生命周期中将输入框设置为可见,那么输入框会在不断地创建、使用和销毁过程中闪烁,并且无法输入内容。

for ( ; is_run(); delay_fps(60)) {
	sys_edit editBox;	//放在循环内,每次循环都会重新创建一个新的sys_edit
	
	editBox.create(false);
	...	//输入框初始化,参数配置等等操作
	
	//继续运行将超过editBox所在块,editBox自动销毁
}

  所以在输入框的使用过程中,应该保证不超出输入框的生命周期范围之外。输入框应该定义在帧循环之外。按如下所示,循环过程中

sys_edit editBox;	//定义在循环之外,循环执行过程不会重复创建
editBox.create(false);

...	//输入框初始化,参数配置等等操作
	
for ( ; is_run(); delay_fps(60)) {


}

  那如果同一个输入框在不同的函数里使用怎么办?此时就不能定义成函数的局部变量,应该使用动态分配或者定义成全局变量,保证使用过程一直在输入框的生命周期内。

三、输入框使用例程

下面来做个输入框示例(宽字符型wchar_t 和 字符型 char 分别做个示例)

1. 文本输入实例

  这里简单做个输入框输入的示例,按下回车便会在窗口上显示内容。对于char型和wchar_t型,使用上没有多大的区别,仅仅只是字符串存储上的不同。

1.1 字符char型

#include <graphics.h>
#include <ege/sys_edit.h>

int main()
{
	initgraph(480, 320, INIT_RENDERMANUAL);

	setbkcolor(WHITE);
	setcolor(BLACK);

	int fontHeight = 20;
	setfont(fontHeight, 0, "楷体");
	setbkmode(TRANSPARENT);

	sys_edit editBox;
	editBox.create(true);						//创建,false表示单行
	editBox.move(100, 200);						//设置位置
	int editTextHeight = 16;
	editBox.size(editTextHeight * 10, 4 * editTextHeight + 10);	//设置尺寸,高度一般要比字的高多一点,因为输入框的边框也占一定大小。
	editBox.setbgcolor(YELLOW);					//设置背景颜色
	editBox.setcolor(BLACK);					//设置文字颜色
	editBox.setfont(editTextHeight, 0, "楷体");	//设置字体

	int maxLen = 60;

	editBox.setmaxlen(maxLen);					//设置输入最大长度
	//editBox.setreadonly(false);				//默认允许输入
	editBox.visible(true);						//使可见
	//获取焦点
	editBox.setfocus();

	//创建输入缓存区
	const int buffSize = 100;
	char strBuffer[100] = "";
	int buffLen = 0;

	for (; is_run(); delay_fps(60)) {
		bool isOutput = false;

		//检测到回车键弹起就标记输出
		while (kbmsg()) {
			key_msg msg = getkey();
			if ((msg.key == key_enter) && (msg.msg == key_msg_up)) {
				isOutput = true;
			}
		}
		
		//需要输出
		if (isOutput) {
			//获取输入框内容字符串
			editBox.gettext(buffSize, strBuffer);
			//计算字符串长度
			buffLen = strlen(strBuffer);

			//如果你想获取后清空输入框,设置内容为空字符串
			//editBox.settext("");
		}

		cleardevice();
		xyprintf(100, 0, "缓存区大小:%d", buffSize);
		xyprintf(100, 20, "限制最大输入长度:%d", maxLen);

		//如果缓存区有内容就输出
		if (strBuffer[0] != '\0') {
			xyprintf(100, 40, "输入文本长度:%d", buffLen);
			//区域输出,因为内容较多,xyprintf不会自动换行,所以用下面这个
			outtextxy(100, 60, "输入内容:");
			rectprintf(100, 80, 380, 200, "%s", strBuffer);
		}
	}

	//如果退出循环,直接getch()是无法阻塞的,因为输入的时候也在产生按键消息
	//需要先清空按键消息
	flushkey();
	getch();

	closegraph();
	return 0;
}

在这里插入图片描述

1.2 宽字符wchar_t 型

  这里需要注意的是,在 C++ 标准中,wprintf() 中的 wchar_t 型字符串的占位符是 %ls,而在 MSVC 则是 %s

#include <graphics.h>
#include <wchar.h>
#include <ege/sys_edit.h>
#include <locale.h>

//wprintf 宽字符串占位符,MSVC 使用 %s, 其它使用 %ls
#ifdef _MSC_VER
#define WPRINTF_WSTR_FORMAT  "%s"
#else
#define WPRINTF_WSTR_FORMAT  "%ls"
#endif

int main()
{
	initgraph(480, 320);
	setrendermode(RENDER_MANUAL);
	setlocale(LC_ALL, "");						//设置地域
	setbkcolor(WHITE);

	setcolor(BLACK);
	int fontHeight = 20;
	setfont(fontHeight, 0, "楷体");
	setbkmode(TRANSPARENT);

	sys_edit editBox;
	editBox.create(true);						//创建,false表示单行
	editBox.move(100, 200);
	int editTextHeight = 16;
	editBox.size(editTextHeight * 10, 4 * editTextHeight + 8);	//设置尺寸
	editBox.setbgcolor(YELLOW);					//设置背景颜色
	editBox.setcolor(BLACK);					//设置文字颜色
	editBox.setfont(editTextHeight, 0, "楷体");	//设置字体

	int maxLen = 60;

	editBox.setmaxlen(maxLen);					//设置输入最大长度
	//editBox.setreadonly(false);				//默认允许输入
	editBox.visible(true);						//使可见
	editBox.setfocus();							//获取焦点

	const int buffSize = 100;
	//初始值给一个空字符串,方便判断是否有内容,否则未初始化,不好处理
	//宽字符串用 L""表示
	wchar_t strBuffer[100] = L"";
	int buffLen = 0;

	bool press = false;		//用来标记是否按下

	for (; is_run(); delay_fps(60)) {
		bool isOutput = false;

		//检测到回车键抬起就标记输出
		while (kbmsg()) {
			key_msg msg = getkey();
			if ((msg.key == key_enter) && (msg.msg == key_msg_up)) {
				isOutput = true;
			}
		}

		//需要进行输出
		if (isOutput) {
			//获取输入框内容字符串
			editBox.gettext(buffSize, strBuffer);
			//计算字符串长度
			buffLen = wcslen(strBuffer);
		}

		cleardevice();
		xyprintf(100, 0, "缓存区大小:%d", buffSize);
		xyprintf(100, 20, "限制最大输入长度:%d", maxLen);

		//如果缓存区有内容就输出
		if (strBuffer[0] != '\0') {
			xyprintf(100, 40, "输入文本长度:%d", buffLen);
			outtextxy(100, 60, "输入内容:");
			//wsprintf()

			//注意这里要用 L"", 至于占位符,MSVC 使用 %s, GCC 编译器使用 %ls
			rectprintf(100, 80, 380, 200, L"" WPRINTF_WSTR_FORMAT, strBuffer);
		}
	}

	//如果退出循环,直接getch()是无法阻塞的,因为输入的时候也在产生按键消息
	//需要先清空按键消息
	flushkey();
	getch();

	closegraph();
	return 0;
}

在这里插入图片描述

2. 多个输入框

2.1 多个输入框的使用

多个输入框就创建多个sys_edit对象,分别对其初始化即可。

#include <graphics.h>
#include <stdio.h>
#include <ege/sys_edit.h>

int main()
{
	initgraph(640, 480, INIT_RENDERMANUAL);
	setbkcolor(WHITE);

	sys_edit editBox;
	editBox.create(false);
	editBox.size(200, 24 + 8);
	editBox.setbgcolor(YELLOW);
	editBox.setfont(24, 0, "黑体");
	editBox.move(40, 40);
	editBox.visible(true);
	editBox.setfocus();

	sys_edit editBox1;
	editBox1.create(false);
	editBox1.size(200, 24+8);
	editBox1.setbgcolor(YELLOW);
	editBox1.setfont(24, 0, "黑体");
	editBox1.move(400, 40);
	editBox1.visible(true);
	editBox1.setfocus();

	//帧循环,处理交互,不可少,否则直接退出
	for (;is_run(); delay_fps(60)) {

	}

	closegraph();

	return 0;
}

2.2 相同样式输入框统一初始化

  较多情况下,输入框的样式基本都是一样的,只是大小,位置不同,这时可以将配置输入框的函数封装,只留下位置和大小参数。
  如果觉得输入框需要各种不同的样式,可以自己定义一个包含各种设置参数的结构体,当做参数传入即可。(EGE的输入框也没提供什么样式,小搞一下就行)

#include <graphics.h>
#include <stdio.h>
#include <ege/sys_edit.h>

void initEditBox(sys_edit* editBox, int x, int y, int width, int height)
{
	editBox->create(false);
	editBox->size(width, height + 8);
	editBox->setbgcolor(YELLOW);
	editBox->setfont(24, 0, "黑体");
	editBox->move(x, y);
	editBox->visible(true);
	editBox->setfocus();
}

int main()
{
	initgraph(640, 480, INIT_RENDERMANUAL);
	setbkcolor(WHITE);

	sys_edit editBox[8];
	int width = 280, height = 24;
	char text[64];
	for (int i = 0; i < 8; i++) {
		int x = (i % 2) * 300 + 20, y = (i / 2) * 60 + 20;

		initEditBox(&editBox[i], x, y, width, height);

		sprintf(text, "editbox %d", i + 1);
		editBox[i].settext(text);
	}

	//帧循环,处理交互,不可少,否则直接退出
	for (;is_run(); delay_fps(60)) {

	}

	closegraph();

	return 0;
}

在这里插入图片描述

3. getch()无法阻塞、窗口闪退的情况

  因为你在输入框输入的时候会产生按键消息,所以当你退出循环后,因为存有按键消息,getch()会直接从按键消息队列里面获取,而不会阻塞,所以如果后面就是closegraph(),看到窗口闪一下就关闭了。
  对于有输入框的程序,可以考虑是否需要使用 flushkey() 清空消息队列。

下面先看一下出问题时情况:
  这个程序在帧循环里仅仅只是检测回车键有没有按下,按下就退出循环,并且没有读取按键消息。那么这时消息队列里就会堆积一定数量的消息。退出循环后,程序就会读取队列里剩余的按键消息并计数。这样可以看到在退出循环后,会剩余多少个按键消息,这就是getch()不阻塞的原因。

#include <graphics.h>
#include <ege/sys_edit.h>

int main()
{
	initgraph(640, 480, INIT_RENDERMANUAL);
	setbkcolor(WHITE);
	sys_edit editBox;
	editBox.create(false);
	editBox.size(24 * 20, 24+8);
	editBox.setfont(24, 0, "黑体");
	editBox.move(100, 100);
	editBox.visible(true);
	editBox.setfocus();
	setcolor(BLACK);
	setfont(26, 0, "楷体");
	xyprintf(100, 140, "输入后按回车, 看看有多少个按键消息");
	xyprintf(100, 180, "和你输入时按下的按键数和速度有关");

	for (; is_run(); delay_fps(60)) {
		if (keystate(key_enter))
			break;
	}

	int count = 0;

	//这里用来计数并清空剩余按键消息
	while (kbmsg()) {
		getkey();
		count++;
	}

	setcolor(RED);
	xyprintf(100, 250, "剩余字符数:%d", count);
	xyprintf(100, 280, "按任意键退出");

	getch();

	closegraph();

	return 0;
}

在这里插入图片描述

  所以在输入框中输入完成后,可以考虑用 flushkey() 清空按键消息,或者在帧循环中处理按键消息。==

如下所示

#include <graphics.h>
#include <ege/sys_edit.h>

int main()
{
	initgraph(640, 480, INIT_RENDERMANUAL);
	setbkcolor(WHITE);

	sys_edit editBox;
	editBox.create(false);
	editBox.size(24 * 20, 24 + 8);
	editBox.setfont(24, 0, "黑体");
	editBox.move(100, 100);
	editBox.visible(true);
	editBox.setfocus();
	setcolor(BLACK);
	setfont(26, 0, "楷体");
	xyprintf(100, 140, "输入后按回车, 看看有多少个按键消息");
	xyprintf(100, 180, "和你输入时按下的按键数和速度有关");
	
	for (;is_run(); delay_fps(60)) {
		bool exit = false;
		while (kbmsg()) {
			key_msg msg = getkey();

			//检测到按键按下就退出
			if ((msg.key == key_enter) && (msg.msg == key_msg_up)) {
				exit = true;
				break;
			}
		}

		if (exit) {
			break;
		}	
	}

	//注意这里,清空按键消息队列里的消息
	flushkey();

	setcolor(RED);
	xyprintf(100, 280, "按任意键退出");

	getch();

	closegraph();

	return 0;
}

4. 获取数字等输入

  可能有人只会在控制台程序中使用 scanf() 获取数字输入,而对于从输入框获取到的字符串不知如何得到参数,因为它只给我们提供了获取字符串内容的gettext()

  在控制台中获取输入,我们可能会这样:

int a, b;
scanf("%d %d", &a, &b);

  然后从控制台输入两个数据,就完成了变量的赋值。但其实呢,我们输入进控制台的,就是字符串, 只不过是 scanf() 函数 对这个字符串进行了解析,从里面提取出了我们想要的值

  你可能见过这样的编程题:

函数填空
  calculateN 函数的功能是计算出由字符串表示的数值。
  函数参数为一个只包含十进制数字字符(‘0’~‘9’)的字符串,字符串长度最小为1,最大为5。字符串所对应的十进制数字为 N ( 0 ⩽ N ⩽ 9999 ) N(0 \leqslant N \leqslant 9999) N(0N9999),要求计算出 N N N的值并返回。

int calculateN(const char* str)
{

}

我们可以写下这样的答案:

int calculateN(const char* str)
{
	int sum = 0;
	const char* p = str;

	for (p = str; *p != '\0'; p++) {
		sum = 10 * sum + (*p - '0');
	}

	return sum;
}

这样就能将字符串转成数字了。

  那标准库中有没有这样的函数能实现同样的效果呢?当然有,<stdlib.h> 头文件中的 atoi() 就能将十进制数字字符串转成相应的值。
  所以函数可以改成如下所示:

int calculateN(const char* str)
{
 	return atoi(str);
}

  那对于更复杂的输入,想像 scanf() 一样从字符串读取各种数据呢?那就是同在 <stdio.h> 头文件中的 sscanf()
  sscanf() 可以和 scanf() 一样读取出各种不同的数据,区别仅仅是 scanf() 控制台的输入中读取,而 sscanf() 从字符串中读取。类似的,还有从文件中读取的 fscanf()

函数声明:

int scanf(char const* const _Format, ...);

int sscanf(char const* const _Buffer, char const* const _Format, ...);

  可以看到 sscanf() 前面多了一个字符串类型的 _Buffer 参数,对于从 输入框得到的字符串 ,我们可以将其传入 sscanf() 来获取我们需要的值。

#include <stdio.h>	//sscanf()所需头文件 <stdio.h>


int a, b;

const int buffSize = 100;
char strBuffer[100];

editBox.gettext(buffSize,  strBuffer);

sscanf(strBuffer, "%d %d", &a, &b);

  其中,strBuffer是字符数组首地址
  可以看到,除了前面多了个 strBuffer参数 , 其它参数和 scanf() 是一样的。这和我们在控制台是一样的, 只不过scanf() 处理的是我们在控制台窗口输入的字符,而sscanf() 处理的是字符串中的内容。

  对于宽字符类型的字符串, 则可以使用 swscanf()


#include <stdio.h>	//swscanf()所需头文件 <stdio.h>


int a, b;

const int buffSize = 100;
wchar_t strBuffer[100];

editBox.gettext(buffSize,  strBuffer);

swscanf(strBuffer, L"%d %d", &a, &b);

  上面我们已经能通过 sys_edit::gettext(),获取输入框内容了,假设是存入strBuff 中,那么就可以用下面的方法获取输入的数字:

这是之前定义的缓存区
const int buffSize = 100;
char strBuffer[100] = "";
...

这是变量
int a = 0;

if (在输入框输入完成后) {
	editBox.gettext(buffSize, strBuff);
	sscanf(strBuffer, "%d", &a);
	
	这样就已经完成了数字的输入
}

  可以看到, sscanf() 相比于 scanf() 除了字符串的来源不同,其它都是一样的,你可以输入小数,用 "%f ", 输入整数,用 “%d”, 输入两个数字,用 “%d %d”

4.1 从输入框获取参数示例

  实现从输入框中获取输入的数字,然后计算平方值。
在这里插入图片描述

  要注意的是,因为输入框可以随便输入,输入的格式不一定正确,所以要好好利用 scanf 的返回值,返回值是读入的数值个数,如果和我们要读入的变量数不等,那就不操作,或者提示输入有误,直到输入正确。

  下面有很多判断的代码是 为了检测输入框内容是否要求,如果能确保格式符合要求,gettext() 后直接 ssanf() 就完成了。

#include <graphics.h>
#include <stdio.h>
#include <ege/sys_edit.h>

int main()
{
	initgraph(300, 120, INIT_RENDERMANUAL);

	setbkcolor(WHITE);
	setcolor(BLACK);

	int fontHeight = 20;
	setfont(fontHeight, 0, "楷体");
	setbkmode(TRANSPARENT);

	sys_edit editBox;
	editBox.create(false);						//单行
	editBox.move(100, 20);						//设置位置

	int editTextHeight = 16;

	//设置尺寸,高度一般要比字的高多一点,因为输入框的边框也占一定大小。
	editBox.size(editTextHeight * 10, editTextHeight + 8);	

	editBox.setbgcolor(WHITE);					//设置背景颜色
	editBox.setcolor(BLACK);					//设置文字颜色
	editBox.setfont(editTextHeight, 0, "楷体");	//设置输入框字体
	editBox.setmaxlen(8);						//设置输入最大长度
	editBox.visible(true);						//使可见
	editBox.setfocus();							//获取焦点

	//创建输入缓存区
	const int buffSize = 100;
	char strBuffer[100] = "";

	bool flag_press = false;		//用来标记是否按下
	bool hasInput = false;			//标记是否有数字输入
	bool error = false;				//标记是否输入错误
	double a;
	double result = 0.0;

	for (; is_run(); delay_fps(60)) {
		bool calculate = false;

		//检测到回车键抬起就标记输出
		while (kbmsg()) {
			key_msg msg = getkey();
			if ((msg.key == key_enter) && (msg.msg == key_msg_up)) {
				calculate = true;
			}
		}

		//需要进行计算
		if (calculate) {
			//获取输入框内容字符串
			editBox.gettext(buffSize, strBuffer);

			//判断输入是否为空
			if (strBuffer[0] == '\0') {
				hasInput = error = false;
			}
			//判断是否成功读取到数字
			else if (sscanf(strBuff, "%lf", &a) == 1) {
				result = a * a;
				error = false;
				hasInput = true;
			}
			//输入错误
			else {
				hasInput = error = true;
			}
		}

		/* --------绘图部分-------*/
		cleardevice();		//清屏
		setcolor(BLACK);
		outtextxy(10, 20, "输入数字:");
		outtextxy(10, 60, "平方结果:");

		if (hasInput) {		//有输入
			if (error) {	//有输入但是输入错误
				//输出错误提示
				setcolor(RED);
				outtextxy(100, 60, "输入错误,请重新输入");
			}
			else {		//有输入并且输入正确
				xyprintf(100, 60, "%f", result);
			}
		}
	}

	closegraph();
	return 0;
}

5. EGE自带的输入对话框

inputbox_getline()

  对话框样式是这个函数自己画的,不是很好看,可以自己画个背景其实。并且在ege20.08版本中出了点问题,导致对话框全黑。 (个人不建议使用)

功能:
  使用对话框让用户输入一个字符串。
  不过这个对话框不能自己设置样式。对话框其实都是自己画的,想要样式可以使用sys_edit 类,然后自己贴个对话框背景图

函数声明:

int inputbox_getline(LPCSTR  title, LPCSTR  text, LPSTR  buf, int len);
int inputbox_getline(LPCWSTR title, LPCWSTR text, LPWSTR buf, int len);

参数:

  • title: 对话框标题
  • text: 对话框内显示的提示文字,可以使用’\n’或者’\t’进行格式控制。
  • buf: 用于接收输入的字符串指针,指向一个缓冲区
  • len: 指定buf指向的缓冲区的大小,同时也会限制在对话框里输入的最大长度

返回值:
  返回 true 表示输入有效,buf中的内容为用户所输入的数据,返回 false 表示输入无效,同时buf清空。

示例程序:

#include "graphics.h"

int main()
{
    initgraph(640, 480);
    setbkcolor(WHITE);
    
    char str[100];
    inputbox_getline("这是一个对话框", "请随便\n输入一串字符,输入完请回车",
                    str, sizeof(str)/sizeof(*str));
    outtextxy(0, 0, str);
    getch();
    return 0;
}

在这里插入图片描述


EGE专栏:EGE专栏

  • 81
    点赞
  • 246
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 48
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

依稀_yixy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值