[color=blue:52cb699fa2]

■ 许昌市农业银行 赵钢




现在在Unix系统下用shell编写的菜单程式大都还是采用多级菜单的模式,这种模式的弊端在于菜单的层次多,界面本身不直观,而且在编程过程中,将菜单的显示格式和内容连同所调用的子程式包括在菜单主程式中,使得程式只能满足某个方面的需求,菜单程式本身不具备通用性。本程式设计采用了一种新的设计思路,将下拉菜单界面作为二维表格来处理,把下拉菜单的内容连同所调用的子程式名称分别存放在这两个二维表中,通过对表的读取,实现了控制光标移动、选择菜单内容连同调用子程式的目的。采用这种方式编写出来的程式易于维护,通用性强。在程式本身不做任何改变的情况下,能够在同一操作平台中进行任意移植,因而具备广泛的应用价值。这种思维模式并不局限在Unix系统下的shell编程,而且对于像C这样的过程化语言也具备一定的借鉴意义。

设计思路

在下拉菜单制作过程中,整个下拉菜单界面所包含的菜单名称连同所调用的子程式名之间的相互关系构成了二维表,其中子菜单名称和子程式名称作为表的元素,通过选择光标在表中上下左右移动,将表中元素读出来,再进行处理运算,从而达到控制菜单的选择连同子程式调用等目的。

表1 菜单项
菜单1 菜单2 菜单3 …… 菜单n
菜单11 菜单12 菜单13 …… 菜单1n
菜单21 菜单22 菜单23 菜单2n
菜单31 菜单32 菜单33 菜单3n
……
菜单m1 菜单m2 菜单m3 菜单mn


表2 对应各菜单项的子程式
子程式11 子程式12 子程式13 …… 子程式1n
子程式21 子程式22 子程式23 子程式2n
子程式31 子程式32 子程式33 子程式3n
……
子程式m1 子程式m2 子程式m3 子程式mn


从上面的两个表中不难看出除表1中的第一行为标题行(菜单栏),表1和表2有相同结构,两个表之间的元素存在着一一对应的关系,即每个菜单名称下对应着所调用的程式名(备注: 由于每个菜单标题栏下的子菜单的内容是不相同的,因而每个子菜单下的菜单数目也各不相同,表中一些元素能够是空值,他表示在此没有菜单选择项)。

文中介绍方法的技术难点在于选择光标位置和实际光标位置的关系。所谓选择光标位置是指在上下左右键的控制下,光标在菜单界面的位置,也就是光标在表中的行和列的位置。而实际光标位置是指光标在电脑屏幕上的实际位置。如何通过选择光标位置计算出实际光标位置是本程式的一个难点。本程式的处理办法是将选择光标的行列位置分别作为计算函数的参数,通过函数计算出实际光标的位置。

实现步骤

先将菜单的内容按照一定的格式显示在电脑屏幕上。显示格式要依据表的结构和内容而定,而不能固定不变。假如事先固定下来,会使显示格式和内容之间产生矛盾,难以达到相互之间的统一,程式就不具备通用性。

选择光标在菜单栏左右移动确定选择项目的同时将菜单栏下所包含的子菜单内容显示出来。菜单栏最右端的菜单选择项一般情况下表示“退出”,当选择光标处于这个位置时,回车后退出整个菜单的选择。

在菜单栏中回车或按↓键进入菜单栏下一级子菜单,按照所显示的子菜单内容,选择光标上下移动确定所选定的子菜单内容,回车执行所调用的子程式,←、→两个键退出子菜单的选择。

需要说明的是由于在Unix系统中,光标在上下左右移动时, Unix系统的read命令无法捕获←、↑、→、↓键的控制字符,无法对光标进行有效的控制,为了获取移动光标的控制字符,这里需要用C语言编写一个函数,其主要功能是在光标进行上下左右移动时,能够准确地返回←、↑、→、↓控制键的ASCII值,函数名为getchar。

程式分析

由于光标移动过程中涉及光标的行列位置等重复运算,运用函数可减少程式自身的长度,使程式变得短小、精悍。这里涉及以下一些函数:

1. 画框函数

前面提到显示格式依据表的结构而定,对菜单的边框长度的配置不能固定不变,他要依据菜单标题栏的长度连同标题栏的标题个数而定。这个函数的功能就是依据菜单界面宽度画边框,参数$1表示边框的横线和竖线。

menu_x()

{

_R=$1

col_x=1

while [ col_x -le ${S_LENGTH} ]

do

if [ $_R ]; then echo $_R“\c”

else echo “\c”

fi

col_x=‘expr $col_x 2’

done

}

2. 计算实际光标在屏幕上的行列位置函数

选择光标在标题栏左右移动的过程中,需要计算光标在屏幕上的实际位置,通过这个函数能够准确地计算出这个实际位置。其运算过程是将选择光标在表中的行列位置作为函数的参数,依据这两个参数计算出光标在屏幕上的准确位置,并将选择光标按照计算出的位置在屏幕上准确显示。其中变量SCREEN- CUR表示表1的元素内容,也就是菜单界面的菜单名称,变量SCREEN-R和SCREEN-C分别表示实际光标在屏幕上位置。执行的结果是将选择光标的内容按实际光标的位置显示在屏幕上。

menu_c()

{ _C=$1 # 选择光标在菜单界面的列位置

_R=$2 # 选择光标在菜单界面的行位置

SCREEN_CUR=‘awk -F“|” “NR==$_R { print }”menu|cut -d“|” -f$_C’

if [ $_C -gt 1 ]; then F_C=‘expr $_C - 1’

SCREEN_LENG=‘head -1 menu| cut -d“|” -f0-$F_C|sed -e ‘s/|//g’ \ | awk ‘{ print length($0)}’’

else

SCREEN_LENG=0

fi

SCREEN_R=‘expr $_R 2’

SCREEN_C=‘expr $C_COL $SCREEN_LENG 2’

SCREEN_CUR_X=“\033[${SCREEN_R};${SCREEN_C}H${SCREEN_CUR}”

}

3. 计算选择光标在移动过程中位置的函数

选择光标在上下左右的移动过程中,其在菜单界面的位置也随之发生变化,需要通过运算,以确定选择光标在菜单界面的准确位置。其中参数$1表示上下左右键所返回的ASCII值,当参数$1等于2或3时,表示选择光标在上移或左移; 等于1或4时表示选择光标在向下移动或向右移动。参数$2表示选择光标移动过程中在表1中的位置,参数$3表示选择光标移动过程中所限定的区间范围。

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!