📄 ch18.htm
字号:
<html>
<head>
<title>第十八章 表单库</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb
2312">
<meta name="keywords" content="ncurses,curses,表单库">
</head>
<body leftmargin=40 bgcolor="#DAFFFF" text="black" link="#0000ff"
alink="blue" vlink="#940084">
<br>
<div align="center"><a href="index.htm"><font size="5">
<strong>
回 目 录
</strong>
</font></a></div>
<div align="right">
<font size="5">
<a href="ch17.htm">
<strong>
上 一 章
</strong>
</a>
<a href="ch19.htm">
<strong>
下 一 章
</strong>
</a>
</font>
</div>
<br>
<br>
<br>
<h1 align="center">
第十八章 表单库
</h1>
<br>
<br>
<br>
<div align="left"><font size="4">
<p>
<dd>
当你看到网页上那些处理用户数据的表单后,你肯定很想在纯文本模式下创建一个那样的表单。用纯ncurses创建那样的表单十分困难。但是表单库(Form Library)为我们提供了一个基础的编写框架,使我们可以很容易地创建和维护表单。它包含了很多的函数,分别用来管理,动态扩展表单域等等。我们将通过后面的内容来掌握它。
</dd>
</p>
<p>
<dd>
表单就是表单域的集合,也许这些表单域是一个标签,也许是一项数据的输入框。表单库也提供把表单划分为页面的函数。
</dd>
</p>
<br>
<br>
<h3 align="left">
<a name="basis">
18.1. 基础知识
</a>
</h3>
<br>
<p>
<dd>
表单的创建步骤与菜单的创建大致相同:
</dd>
</p>
<p>
<dd>
首先,用new_field()创建与表单相关联的表单域。你可以设置表单域的修饰选项,这样的界面显示出来会更加美观。离开表单域以前, 这些对表单域的修饰属性都是有效的。
</dd>
</p>
<p>
<dd>
然后,表单域添加进表单,整个表单就会显示到屏幕上,准备读取输入信息。与menu_driver()相似,表单由form_driver()操纵。我们可以传递请求给form_driver()来移动显示焦点(校者注:即表示被选定,通常是高亮条等)到某个表单域,或将光标移动到表单域的结尾等等。用户在表单域内输入并确认后结束,表单就不再显示,并释放占用过的内存。
</dd>
</p>
<p>
<dd>
一个表单程序的流程大致如下:
</dd>
</p>
<pre>
初始化curses
通过new_field()创建表单域。你可以指定域的高度,宽度以及它在表单中的位置。
指定表单域所作用的表单,并用new_form()创建表单。
用form_post()来递送表单,并刷新屏幕。
用一个循环来处理用户请求,通过form_driver()对表单做相应的更新。
用form_unpost()取消表单的递送。
用free_form()释放已分配给表单的内存。
释放已分配给菜单项的内存。
结束curses
</pre>
<p>
<dd>
如你所见,表单库的用法与跟菜单库的用法很像。下面的几个例子将会让我们领略表单处理的其他方面。先让我们从一个简单的例子开始吧:
</dd>
</p>
<br>
<br>
<h3 align="left">
<a name="compile">
18.2 编译包含表单库的程序
</a>
</h3>
<br>
<p>
<dd>
要使用表单库中的函数,必须要把form.h头文件包含进源程序代码。在编译和连接时要同时添加 –lform 和 –lncurses两个选项。
</dd>
</p>
<pre>
#include <form.h>
.
.
.
编译和链接: gcc <程序文件> -lform –lncurses
</pre>
<p>
例25. 表单库基础知识
</p>
<font color="Maroon">
<pre>
#include <form.h>
int main()
{ FIELD *field[3];
FORM *my_form;
int ch;
/* 初始化curses */
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
/* 初始化表单域 */
field[0] = new_field(1, 10, 4, 18, 0, 0);
field[1] = new_field(1, 10, 6, 18, 0, 0);
field[2] = NULL;
/* 设置表单域 */
set_field_back(field[0], A_UNDERLINE); /* 为选项打印一条下滑线 */
field_opts_off(field[0], O_AUTOSKIP);
/* 在域(输入框)填满后光标不会自动跳到下一个表单域 */
set_field_back(field[1], A_UNDERLINE);
field_opts_off(field[1], O_AUTOSKIP);
/* 创建并递送表单 */
my_form = new_form(field);
post_form(my_form);
refresh();
mvprintw(4, 10, "Value 1:");
mvprintw(6, 10, "Value 2:");
refresh();
/* 用循环获取用户请求 */
while((ch = getch()) != KEY_F(1))
{ switch(ch)
{ case KEY_DOWN:
/* 跳至下一个表单域 */
form_driver(my_form, REQ_NEXT_FIELD);
/* 跳到当前缓冲的末尾 */
/* 精确地在输入最后一个后字符跳出这个表单域 */
form_driver(my_form, REQ_END_LINE);
break;
case KEY_UP:
/* 移动到前一个表单域 */
form_driver(my_form, REQ_PREV_FIELD);
form_driver(my_form, REQ_END_LINE);
break;
default:
/* 如果输入的是普通字符, 就把它打印出来 */
form_driver(my_form, ch);
break;
}
}
/* 取消表单并释放内存 */
unpost_form(my_form);
free_form(my_form);
free_field(field[0]);
free_field(field[1]);
endwin();
return 0;
}
</pre>
</font>
<p>
<dd>
上面的程序比较简单易懂。它首先调用new_field()函数创建了两个表单域。new_field()的六个参数分别确定了表单域的高、宽、起始位置的纵坐标、横坐标、不在显示的行数,以及附加的工作缓冲区。其中第五个参数(不显示的行数)决定了表单域哪些部分的是可见的。如果是0,则显示整个表单域。当用户访问的表单域超出了显示范围,那么表单将变成可滚动的。之后,表单库分别为每个表单分配了缓冲区,用来存储用户输入的数据。new_field()的最后一个参数用来分配额外的缓冲区。这些缓冲区可以用来做其它的事情。
</dd>
</p>
<p>
<dd>
当创建表单域后,用set_field_back()函数可以增添背景修饰效果。选项AUTOSKIP已用field_opts_off()关闭。如果这个选项是打开的,一旦当前的表单域被输入的数据填满,则光标自动跳转到下一个表单域。
</dd>
</p>
<p>
<dd>
给表单添加完表单域后,就把表单递送出去。接着,通过对form_driver()发送相应的操作请求, while循环里将处理用户输入的信息。有关form_driver()的细节将在后面的部分详细解释。
</dd>
</p>
<br>
<br>
<h3 align="left">
<a name="formfield">
18.3.玩转表单域
</a>
</h3>
<br>
<p>
<dd>
每个表单域关联了大量的属性。那样可意使你定制它们从而得到你想要的效果。是不是很有趣?那还等什么呢?
</dd>
</p>
<br>
<h4 align="left">
<strong>
18.3.1. 获取域的大小和位置
</strong>
</h4>
<p>
<dd>
我们可以用函数field_info()得到已创建表单域的参数。该函数返回表单域的高、宽、起始位置的纵坐标、横坐标、不显示的行数和附加的缓冲区。它的顺序跟new_field()的相反:
</dd>
</p>
<font color="maroon">
<pre>
int field_info( FIELD *field, /* 要获取信息的表单域*/
int *height, *int width, /* 域的高、宽 */
int *top, int *left, /* 起点的y坐标,起点的x坐标 */
int *offscreen, /* 不在显示范围内的行数 */
int *nbuf); /* 附加缓冲区的大小 */
</pre>
</font>
<br>
<h4 align="left">
<strong>
18.3.2.移动表单域
</strong>
</h4>
<p>
<dd>
通过函数move_field()可以移动表单域的位置。
</dd>
</p>
<font color="Maroon">
<pre>
int move_field( FIELD *field, /* 要移动的表单域 */
int top, int left); /* 新位置的起点坐标(先行后列)*/
</pre>
</font>
<p>
<dd>
同样的,改变后的位置也可以通过field_info()查询到。
</dd>
</p>
<br>
<h4 align="left">
<strong>
18.3.3.设置表单域的对齐方式
</strong>
</h4>
<p>
<dd>
输入表单域数据的对齐方式可以用函数set_field_just()设置。
</dd>
</p>
<font color="Maroon">
<pre>
int set_field_just(FIELD *field, /* 要更改的表单域 */
int justmode); /* 要设置的对齐方式 */
int field_just(FIELD *field); /* 查询表单域的对齐方式 */
</pre>
</font>
<p>
<dd>
这两个函数可以用来设置或者返回相应表单域对齐方式的值,分别为为NO_JUSTIFICATION(没有对齐方式),JUSTIFY_RIGHT(右对齐),JUSTIFY_LEFT(左对齐) 或者JUSTIFY_CENTER(居中对齐)。
</dd>
</p>
<br>
<h4 align="left">
<strong>
18.3.4.表单域的显示修饰
</strong>
</h4>
<p>
<dd>
正像前面提到的那样,在上面的例子中,表单域的修饰效果可以用set_field_fore()和set_field_back()两个函数来设置。这两个函数分别设置表单域的前景和背景修饰。你也可以指定用字符填充该表单域的空白处。通过调用函数set_field_pad()你就可以设置背景填充字符了。默认背景填充字符为空格。函数field_fore(),field_back(),field_pad()可以用来查询当前表单域的前景、背景修饰和背景填充字符。以下是这些函数的原形:
</dd>
</p>
<font color="maroon">
<pre>
int set_field_fore(FIELD *field, /* 要设置的表单域 */
chtype attr); /* 被设置表单域的前景修饰属性 */
chtype field_fore(FIELD *field); /* 要查询的表单域 */
/* 返回该表单域的前景修饰属性 */
int set_field_back(FIELD *field, /* 要设置的表单域 */
chtype attr); /* 被设置表单域的背景修饰属性 */
chtype field_back(FIELD *field); /* 要查询的表单域 */
/* 返回该表单域的背景修饰属性 */
int set_field_pad(FIELD *field, /* 要设置的表单域*/
int pad); /* 要设置表单域的背景填充字符 */
chtype field_pad(FIELD *field); /* 要查询的表单域*/
/* 返回该表单域的背景填充字符 */
</pre>
</font>
<p>
<dd>
尽管上面的函数看起来很简单,但用set_field_fore()来设置颜色对初学者来说可能很困难。我先解释一下表单域的前景和背景修饰。前景修饰与字符有关。即在表单域内以set_field_for()设置字符的修饰效果。背景修饰用来填充表单域的背景,不管表单域内是否有字符。由于颜色通常是成对定义,怎样才能正确显示包含颜色设置的表单域呢?下面的例子很清楚地解释了颜色定义。
</dd>
</p>
<p>
例26.一个有关表单域属性的例子
</p>
<font color="maroon">
<pre>
#include <form.h>
int main()
{
FIELD *field[3];
FORM *my_form;
int ch;
/* 初始化curses */
initscr();
start_color();
cbreak();
noecho();
keypad(stdscr, TRUE);
/* 初始化颜色 */
init_pair(1, COLOR_WHITE, COLOR_BLUE);
init_pair(2, COLOR_WHITE, COLOR_BLUE);
/* 初始化表单域 */
field[0] = new_field(1, 10, 4, 18, 0, 0);
field[1] = new_field(1, 10, 6, 18, 0, 0);
field[2] = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -