EGE专栏:EGE专栏
图形窗口中的文字并不像控制台那样只能固定输出在某一行中,可以在绘图区的任意位置进行输出。
窗口绘图区坐标系如下图所示: x x x 轴向右为正, y y y 轴向下为正。从左到右,从上到下,这和我们平时阅读文字的顺序是一致的。
屏幕显像区域是由固定数量的像素点组成,左上角像素的坐标为 ( x , y ) (x, y) (x,y), 如果窗口的宽度 为 s c r e e n W i d t h \mathrm{screenWidth} screenWidth 个像素, 高度为 s c r e e n H e i g h t \mathrm{screenHeight} screenHeight 个像素,那么右上角像素点坐标为 ( s c r e e n W i d t h − 1 , 0 ) (\mathrm{screenWidth}-1, 0) (screenWidth−1,0) 。
在图形窗口中输出文字需要给出文字的位置信息,这个位置信息一般是指文字输出区域的左上角坐标。至于文字的大小,一般会有函数进行统一设置,不需要在输出文字时指定每个字的大小,因为一行文字基本上是使用统一的样式,而不是样式各不相同。
文字输出前需要设置好文字样式,否则默认的字体、大小和颜色可能不符合需求。
EGE中的 setfont()
函数可以设置字体、宽度和高度,还可以将文字样式设置为斜体,粗体,旋转角度等。
通常以如下方式使用,设置文字的高度和字体,宽度为0即让系统自动按照文字对应的宽度输出,如果设置固定宽度可能会让文字变形。常用字体有:"宋体"
, "黑体"
, "楷体"
等。
setfont(height, 0, "字体名");
setfont()
还有很多重载,可以设置更复杂的文字样式。
详细可以参考 EGE库函数文档:setfont()。
文字的颜色则是通过setcolor()
进行设置,颜色可以带透明度,但只有ege_drawtext()
支持输出带透明度的文字,其它的文字输出函数会忽略透明度。
setcolor(EGEARGB(0x80, 0x30, 0x30, 0x30));
当然还有个文字背景色,由 setfontbkcolor() 指定,不过一般我们都不会让文字有自己的背景色,背景色都是透明的,文字后面原来是什么图就显示什么。
所以我们一般都会加上一个设置,让文字的背景色为透明,即下面这句:
setbkmode(TRANSPARENT); //设置文字背景色为透明
文字对齐方式可以使用 settextjustify()
进行设置,两个参数分别是水平对齐方式和垂直对齐方式。下面示例为水平居中,垂直居中对齐。
settextjustify(CENTER_TEXT, CENTER_TEXT);
设置好合适的文字样式后,就可以使用相关函数输出文字了。EGE最常用的文字输出函数为 xyprintf()
,它具有和C标准库的printf()
类似的使用方式,可以将变量转为字符串进行输出,仅仅是需要多添加两个位置相关参数,用于指定文字输出位置的左上角坐标。
xyprintf(x, y, "格式化字符串", 参数1, 参数2, ...); //图形窗口的输出
如果只是想输出固定的文字,不带参数即可。
xyprintf(x, y, "要输出的文字");
当然,输出固定文字有专用的 outtextxy() ,可以免去字符串解析。
outtextxy(x, y, "要输出的文字");
上面两个函数不可以让文字输出时自动换行,所以有了 rectprint()
,指定一个矩形区域,让文字即将超出区域时自动换行。
rectprintf(x, y, width, height, "格式字符串", 参数1, 参数2,...);
#include <graphics.h>
int main()
{
initgraph(640, 480,0); //初始化窗口
setbkcolor(WHITE); //设置窗口背景为白色
//文字的属性设置
setcolor(BLACK); //文字的颜色
setbkmode(TRANSPARENT); //设置文字背景色为透明
int height = 40; //文字高度
setfont(height, 0, "楷体"); //设置文字宽度和字体
settextjustify(LEFT_TEXT, TOP_TEXT); //水平左对齐,垂直顶部对齐
//输出文字
xyprintf(100, 100, "这里是输出的文字");
getch();
closegraph();
return 0;
}
除了最常用的xyprintf(), 还有一些其它的,下面都列出来。
需要注意的是,这些函数末尾其实还有个 PIMAGE参数,指定输出到图像上,省略则是输出到窗口。
单行输出 | 多行输出 | |
---|---|---|
固定文本 | outtextxy(), outtext() |
outtextrect() |
格式化文本 | xyprintf() |
rectprintf() |
单行输出有两个函数:xyprintf() 和 outtextxy()。
单行输出,即指定了坐标后,只会在一行输出, 即使超出窗口范围了也不会换行,并且无法输出 \t, \n
等特殊符号,如有需要,使用 多行输出函数。
在指定位置 ( x , y ) (x, y) (x,y)处输出文字,可以使用 outtext() ,不过这个只适合输出固定的文字,如果想将一些变量转换为字符串输出,那将应该使用 xyprintf()。
outtextxy(x, y, "你想要输出的文字");
xyprintf() 类似 printf() ,可以输出参数,也可以输出固定文字。
xyprintf(x, y, "格式字符串(%d, %f之类的", 参数1, 参数2, ...);
还有个outtext()
函数是在当前位置输出文字,``当前位置由 moveto(), moverel() 指定。
outtext("想要输出的文字");
多行输出有以下两个函数:outtextrect() 和 rectprintf()
指定一个输出区域,文字会在这个区域内输出,要超出边界时自动换行。并且可以使用 \n, \t 来控制文字的换行与缩进,可以很方便地用于像控制台的printf() 那样连续输出多行文字。如果仅仅用xyprintf() 输出多行文字的话,需要自己控制每一行的起始位置坐标。
在某个矩形区域内输出:
outtextrect(x, y, width, height, "想要输出的文字");
rectprintf(x, y, width, height, "格式字符串", 参数1, 参数2,...);
额外地,我们新增了一个 ege_drawtext 函数,可以使用ARGB颜色,绘制出带透明度的文字,函数声明如下:
void EGEAPI ege_drawtext(LPCSTR textstring, float x, float y, PIMAGE pimg = NULL);
void EGEAPI ege_drawtext(LPCWSTR textstring, float x, float y, PIMAGE pimg = NULL);
现在,设置颜色为ARGB颜色后,就可以直接使用了,如:
//设置透明度为0x80的蓝色
setcolor(EGEACOLOR(0x80, BLUE));
ege_drawtext("这里是要输出的文字", 20, 40);
这个函数和其它函数的参数位置有点区别,位置参数是放后面。
最后有个PIMAGE参数,是指定输出的目标图像,如果要输出到窗口,省略或者传入NULL即可。
如果有让文字占固定的宽度的需求,可使用格式化字符串的 %[flag][m.n]type 格式,如printf(“%10d, %10s\n”, 12, “string” ) 中的 %10d 和 %10s
注意事项:
printf 格式字符串相关参考: https://blog.csdn.net/qq_25544855/article/details/81146800
文字对齐示例
#include <graphics.h>
int main()
{
initgraph(700, 300, 0);
setcolor(BLACK);
setbkcolor(WHITE);
setfont(16, 0, "宋体");
xyprintf(0, 0, "|%-12s|%-12s|%-12s|%-12s|%-12s",
"文字", "对齐", "的一个示例", "对齐", "font align" );
xyprintf(0, 20,"|%-12s|%-12s|%-12s|%-12s|%-12s|%-12s|%-12s",
"EGE文字对齐", "文字对齐", "123", " !%#@!$23)*&", "12322","一二三四五", "0");
getch();
closegraph();
return 0;
}
EGE提供了两个可以格式化输出的文字输出函数:
xyprintf(x, y, "格式字符串(%d, %f之类的", 参数1, 参数2, ...);
rectprintf(x, y, width, height, "格式字符串", 参数1, 参数2,...);
但有时仍需要对生成的字符串一些操作,这时就可以使用格式化字符串输出函数 sprintf()。 平时我们常用 printf() 将内容输出到控制台窗口,而 sprintf() 是把内容输出到字符数组里。这样就可以得到格式化输出的字符串,用于其它操作。
方法:
先定义一个能容纳输出字符串的数组
char strBuffer[32];
再使用 sprintf() 生成格式化字符串并存入 strBuffer 中。
sprintf(strBuffer, "今天是%d月%d日", 9, 2);
这样,在 strBuffer 中我们就得到 "今天是9月2日"
的字符串,
对于文字输出,经常需要调整字体,大小,颜色,对齐方式等,下面就列出关于这些设置相关的内容。
设置只对之后的文字输出生效。 所以不能先输出文字再设置文字样式,设置之前已经绘制出的文字不会因为新的设置而改变。
文字颜色即前景色(默认是浅灰色)
, 由 setcolor(color) 指定。如,设置文字颜色为蓝色。
setcolor(BLUE);
文字的背景色, 由 setfontbkcolor(color) 指定(默认是白色)
, 如,设置文字背景颜色为白色。
setfontbkcolor(WHITE)
我们常常需要文字的背景颜色是 透明 的,窗口什么颜色,背景就是什么颜色,不然一个字后面有一个色块,把后面的图片挡住,很难看。
这就用到 setbkmode() 函数, 参数可以选择设置文字的背景颜色是透明还是使用当前文字背景色。
设置文字背景色为透明。
setbkmode(TRANSPARENT);
设置文字背景色为当前文字背景色。
setbkmode(OPAQUE);
下面的图中,可以看到两种文字背景颜色模式的区别,透明背景模式的更自然。
使用setfont() 设置文字字体和大小,这个函数有四个重载。最常用的是
void setfont(int nHeight, int nWidth, LPCSTR lpszFace, PIMAGE pimg = NULL);
比如,设置文字为高度为12 的宋体字,宽度自适应。( 这个高度是指 像素)
setfont(12, 0, "宋体");
宽度自适应是根据高度自动调整宽度,以保证字体宽高比例。
需要注意的是 ege_drawtext() 由于底层的实现是用GDI+,和其它函数不同,所以输出的宽度可能会不太一样。
支持系统已经安装的字体。
在自己电脑桌面右击选择 “个性化”–>“字体” 查看。
下面做个字体样式显示测试。(可以往fontStyle数组里添加自己想要显示的字体,查看字体显示效果)
#include <graphics.h>
int main()
{
initgraph(800, 640, INIT_RENDERMANUAL); //初始化窗口
setcaption("EGE字体样式"); //设置窗口标题
setbkcolor(WHITE); //设置窗口背景为白色
setcolor(BLACK); //设置前景色为黑色
setbkmode(TRANSPARENT); //设置文字背景色为透明
const char* fontStyle[] = {
"宋体", "楷体", "黑体", "微软雅黑", "仿宋",
"Consolas", "思源黑体", "Romantic", "华文中宋", "华文仿宋" ,
"华文宋体", "华文彩云", "华文新魏", "华文琥珀", "华文细黑",
"华文行楷", "幼圆", "新宋体", "隶书", "等线",
"方正姚体", "方正舒体", "Roboto", "Italic","Vineta BT",
"华文隶书", "Tahoma", "汉仪南宫体简",
};
//计算字体样式数
int len = sizeof(fontStyle) / sizeof(fontStyle[0]);
//每一行显示的样式数
int styleNumOfOneLine = 5;
//行之间的间隔
int lineSpacing = 8, horizontalSpacing = 160;
int fontHeight = 28;
for (int i = 0; i < len; i++) {
setfont(fontHeight, 0, fontStyle[i]);
int x = (i % styleNumOfOneLine) * horizontalSpacing;
int y = (i / styleNumOfOneLine) * (fontHeight + lineSpacing);
xyprintf(x, y, fontStyle[i]);
}
getch();
closegraph();
return 0;
}
setfont() 还有其他的重载函数,可以设置下划线,斜体,角度,删除线,剪辑精度,输出质量,笔画粗细,等。
具体请参考官网库函数文档文字输出部分,这里不再另作说明 EGE库函数文档:setfont()
字体样式的一个结构体 LOGFONT ,
struct LOGFONT {
LONG lfHeight; //高度
LONG lfWidth //宽度
LONG lfEscapement; //字符串书写角度
LONG lfOrientation; //字的书写角度
LONG lfWeight; //笔画粗细
BYTE lfItalic; //是否斜体
BYTE lfUnderline; //字体是否有下划线
BYTE lfStrikeOut; //字体是否有删除线
BYTE lfCharSet; //指定字符集
BYTE lfOutPrecision;
BYTE lfClipPrecision;
BYTE lfQuality;
BYTE lfPitchAndFamily;
TCHAR lfFaceName[LF_FACESIZE];
};
获取当前字体样式
LOGFONT font;
getfont(&font);
获取字体样式后,可以设置改变LOGFONT其中需要改变的属性,然后设置字体样式。
setfont(&font);
可以设置文字 水平对齐方式 和 垂直对齐方式。
对齐方式适合 单行输出,如果是多行输出的话,可能只能设置水平左对齐和水平右对齐。
在单行文字输出中,对齐就是文字坐标在文字的位置(文字坐标即输出文字时指定的坐标)
, 默认对齐方式是水平左对齐,垂直顶部对齐(也就是文字坐标在文字左上角),如果指定水平和垂直都中心对齐,那么文字坐标就会在文字中间。
下面是指定文字对齐用的函数 settextjustify() 的声明。
void settextjustify(
int horiz, //水平对齐方式
int vert, //垂直对齐方式
PIMAGE pimg = NULL
);
对齐参数可以选择下面几种枚举值
水平对齐方式有:左对齐,右对齐,中心对齐
垂直对齐方式有:顶部对齐,底部对齐,中心对齐
enum text_just {
//水平对齐方式
LEFT_TEXT = 0,
CENTER_TEXT = 1,
RIGHT_TEXT = 2,
//垂直对齐方式
BOTTOM_TEXT = 0,
/* CENTER_TEXT = 1, already defined above */
TOP_TEXT = 2
};
使用示例:
设置文字绘制到窗口时,水平和垂直方向都是中心对齐。PIMAGE参数为NULL时表示设置窗口,这也是默认参数,省略即可。
//设置文字对齐方式为水平中心对齐,垂直中心对齐
settextjustify(CENTER_TEXT, CENTER_TEXT);
这个获取要输出字符串的宽高,是做一些适应性调整,比如文字泡,文字周围有框框,可以根据字符串的实际大小调整好框的大小。
下面都是假设字符串输出为一行时的文本宽度。
这里给出一个读取文本文件内容并显示的例程,主要是C语言读取文件部分的知识。
需要注意文本文档的编码,如果编码不一致会导致 汉字输出乱码 ,中文系统一般默认使用 GBK编码或者GB2312编码,所以可以保存为这两种。
可以用记事本打开文本文档,选择另存为, 编码选择 ANSI(即当前系统使用的本地编码,中文系统则默认为GB2312)。
使用 fopen() 函数打开文件:
#include <stdio.h>
FILE* fp = fopen("文本文件名.txt", "r");
if (fp == NULL) {
打开文件失败
}
先创建个缓存区,足够容纳一行的内容。为了简便,文件的一行不是很长,长了的话需要自己处理一下绘制位置。
下面一行一行地读取文本内容:
char buffer[1024];
while (!feof(fp)) {
buffer[0] = '\0';
fgets(buff, 1024, fp); //读取一行
if (buffer[0] == '\0') {
//文件结束,没有读取到新内容,退出
break;
}
//一行内容已经读取进buff中了,这里做输出处理
puts(buffer);
}
完整示例程序:
#include <graphics.h>
#include <stdio.h>
int main()
{
initgraph(800, 640, INIT_RENDERMANUAL);
setbkcolor(WHITE);
//打开文件
FILE* fp = fopen("吹梦到西洲.txt", "r");
if (fp == NULL) {
xyprintf(0, 0, "打开文件失败");
getch();
return -1;
}
setcolor(BLACK);
int titleHeight = 40;
setfont(40, 0, "楷体");
xyprintf((800 - textwidth("吹梦到西洲")) / 2, 0, "吹梦到西洲");
int fontHeight = 20;
setfont(fontHeight, 0, "楷体");
int x = 40, y = titleHeight + 20;
char readBuffer[1024] = ""; // 输入缓冲区
while (!feof(fp)) {
readBuffer[0] = '\0'; // 输入缓冲区置为空字符串
fgets(readBuffer, 1024, fp);
if (readBuffer[0] == '\0') // 如果没有读取到内容(文件结束),退出
break;
xyprintf(x, y, readBuffer);
//计算下一行的位置
y += fontHeight;
//大于每页的长度,换页
if (y + fontHeight > 600) {
//转到另一页起始位置
x += 400;
y = titleHeight + 20;
//超过显示区域,不再输出
if (x > 800)
break;
}
}
fclose(fp);
getch();
closegraph();
return 0;
}
下图为原txt文件中的内容
运行结果
实际上很多时候一行文字很多,超出宽度,就会出现被覆盖的情况。这时就要用 rectprintf() 了,内容超出行宽后会自动换行输出,但是因为是一行一行地读取输出的,需要自己用 textwidth() 判断一行内容的长度,计算输出了多少行,如果真要弄起来也挺麻烦的,EGE本身给出的接口不足。
怎么计算呢?
指定用 rectprintf() 在区域内输出,因为超出宽度后会自动换行,但是我们需要知道它实际输出了多少行,才能知道下一次输出的位置。我们只要用 字符串总宽度除以行宽, 向上取整即可得到输出的行数(实际上也不是很可靠,因为末尾不够输出一个字的时候会换行,这时就会算错)
所以计算方式如下:( / 是整除)
输出行数 = (字符串总宽度 + 行宽 - 1) / 行宽
下面则是把多行并做一行,然后显示超出一行的宽度示例:
#include <graphics.h>
#include <stdio.h>
int main()
{
const int SCR_WIDTH = 800, SCR_HEIGHT = 700;
initgraph(SCR_WIDTH, SCR_HEIGHT, INIT_RENDERMANUAL);
setbkcolor(WHITE);
//打开文件
FILE* fp = fopen("吹梦到西洲.txt", "r");
if (fp == NULL) {
xyprintf(0, 0, "打开文件失败");
getch();
return -1;
}
setcolor(BLACK);
int titleHeight = 40;
setfont(40, 0, "楷体");
xyprintf((SCR_WIDTH - textwidth("吹梦到西洲")) / 2, 0, "吹梦到西洲");
int fontHeight = 20;
setfont(fontHeight, 0, "楷体");
int x = 40, yBase = titleHeight + 20, y = yBase;
char outputBuffer[1024 + 4] = " "; //输出缓冲区,一行前面4个空格(两个汉字宽)
char* readBuffer = &outputBuffer[4]; //输入缓冲区,首地址在输出缓冲区往后偏移4个字符位置
int c = feof(fp);
while (!feof(fp)) {
readBuffer[0] = '\0'; //读取前置为空字符串
fgets(readBuffer, 1024, fp); //读取一行文本
if (readBuffer[0] == '\0') //如果没有读到内容,退出循环
break;
//多行输出:将输出缓冲区outputBuffer的内容输出到窗口相应的位置
rectprintf(x, y, SCR_WIDTH - 2 * x, SCR_HEIGHT - y, outputBuffer);
//计算一下输出了多少行高度, 向上取整
int width = textwidth(outputBuffer);
int lineCount = (width + SCR_WIDTH - 2 * x - 1) / (SCR_WIDTH - 2 * x);
//输出区域往下移
y += lineCount * fontHeight;
//超出显示范围
if (y >= SCR_HEIGHT) {
break;
}
}
fclose(fp);
getch();
closegraph();
return 0;
}
TXT文件原内容
运行截图:
EGE专栏:EGE专栏
使用IDEA下载插件时,可能会出现MarketPlace一直加载不出来的问题,导致我们无法从MarketPlace中选择我们需要的插件进行下载,在确保网络正常的情况下,针对这个问题,只需要进行一个简单的设置即可。以IDEA 2020.1版本为例,找到File->Settings->Appearance&Behavior->System Settings->Updates,如下图所示,将画圈部分的打勾去掉并保存修改即可。...
上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大家.对于这次跳槽找工作, 我准备了挺长的时间, 其中也收集了很多比较好的笔试面试题, 大都是一些常用的基础, 很多都是由于时间原因没有来得及给出答案, 但是题目大都是比较经典实用的, 现在都放到这里, 希望对正处于找工作的博友有一定的帮助.第一部分: Java基础(此部分面试题题目来自:http://www.h
1. 可以安装 sttyopkg update opkg install coreutils-stty2. 设定串口波特率stty -F /dev/ttyS1 raw speed 9600注意,如果在使用串口时,一定要注意 ttyS0 ttyS1 这个S是大写的,再说一下,是大写的在不清楚是,要常用TAB进行补全,这样就不会出错。
人工智能 (AI) 目前是影响和改变许多部门、影响我们日常生活的支柱。 医疗保健、教育、金融、技术和零售等行业正在采用人工智能来高效工作、降低成本和自动化任务。 不仅在这些领域,而且在我们的家中,人工智能正在控制电视、手机、数字助理、家庭自动化和安全摄像头。由于 AI 不断竞争对我们的生活施加更多控制,因此必须安全可靠地创建和验证所有系统。 这就是用于软件测试的人工智能出现的地方。本文将讨论如何在软件测试中使用 AI。 随后,我们将了解 HeadSpin 平台及其独有的功能如何帮助实现卓越的软件..
【课程1.5】 Numpy随机数numpy.random包含多种概率分布的随机样本,是数据分析辅助的重点工具之一随机数生成samples = np.random.normal(size=(4,4))print(samples)# 生成一个标准正太分布的4*4样本值--------------------------------------------------------------...
重构是程序员的主力技能。工作日志能提升脑容量。先用profiler调查,才有脸谈优化。注释贵精不贵多。杜绝大姨妈般的“例注”。漫山遍野的碎碎念注释,实际就是背景噪音。普通程序员+google=超级程序员。(一个不错的vpn)单元测试总是合算的。不要先写框架再写实现。最好反过来,从原型中提炼框架。代码结构清晰,其它问题都不算事儿。好的项目作风硬派,一键测试,一键发布,一键部署; 烂的项
无意中发现了一个巨牛的人工智能教程,忍不住分享一下给大家。教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。点这里可以跳转到教程。Sina邮箱:pop.sina.com.cn(免费)/smtp.sina.com.cnpop3.vip.sina.com(收费)/smtp.vip.sina.comSohu邮箱:pop3.sohu.com/smtp.sohu.compop3.vip.sohu.com/smtp.vip.sohu.com21cn邮箱:pop.2.
POP3POP3是Post Office Protocol 3的简称,即邮局协议的第3个版本,它规定怎样将个人计算机连接到Internet的邮件服务器和下载电子邮件的电子协议。它是因特网电子邮件的第一个离线协议标准,POP3允许用户从服务器上把邮件存储到本地主机(即自己的计算机)上,同时删除保存在邮件服务器上的邮件,而POP3服务器则是遵循 POP3协议的接收邮件服务器,用来接收电子邮件的...
一开始的mail.setting本地windows下面发送没问题host = smtp.qq.com# 发件人(必须正确,否则发送失败)from = [email protected] = [email protected]# 密码(注意,某些邮箱需要为SMTP服务单独设置密码,QQ邮箱要单独的授权码)pass = xxxxxxx死活不对MessagingExcep...
MobaXterm远程连接工具连接不上Linux解决办法:
天下武功唯快不破!若要快速解决项目开发过程中遇到的各种刁钻Error,首先要快速识破它的本质!而不是一味的依赖第六感去猜测,更不该盲目凭借自身的幸运值去不断尝试解决!本文虽不会帮你去逐一识破各种Error,但会给你一大体方向,希望对你当前的工作会有所帮助!一、本文将会出现以下英语词汇assignment[əˈsaɪnmənt] 赋值;分配assignment [əˈsaɪnmənt] 分配;任务call [kɔːl] 调用caught [kɔːt] 捕获;接住;截住;拦住;constru.