龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > C/C++开发 >

Unix下用C编写类Windows菜单

时间:2009-12-22 15:42来源:未知 作者:admin 点击:
分享到:
在开发程序时,程序的界面、开放性是两个非常重要的方面,目前,在Unix系统下运行的程序的界面大都比较死板,而且,在进行功能扩充时也不是很方便。那么,能不能设计一个象 W

  在开发程序时,程序的界面、开放性是两个非常重要的方面,目前,在Unix系统下运行的程序的界面大都比较死板,而且,在进行功能扩充时也不是很方便。那么,能不能设计一个象 Windows那样能够按照用户要求随意调整界面,功能扩充方便的程序呢?答案是肯定的。笔者通过实践,设计了一个菜单程序,使用户在对菜单的显式样式不满足时,只需通过对菜单参数文件进行操作即可完成对菜单位置、宽度、长度、是否有边框等进行调整;在用户需要进行功能扩充时,也无须改动源程序,只须对参数文件进行操作就可将新增功能挂到菜单上。

  

一 参数文件说明

  

本程序需要借肋两个参数文件来实现:

  

(1)、对菜单中每一项参数进行说明的文件(menu.def),它格式如下所述:

  

!所属菜单代号!项顺序号!菜单项名称!外挂程序名称!下级菜单代号!

  

说明:

  

1、如菜单代号为"0",则表示此项属于主菜单;

  

2、如外挂程序名称为"0",则表示此菜单项对应的过程在菜单程序内部或对应于一个子菜单;

  

3、如下级菜单代号为"0",则表示此菜单项无下级子菜单;

  

4、项顺序号同时可作为菜单热键使用。

  

假如文件menu.def中有下面这一行:

  

!0!3!格式化磁盘!format /dev/rfd0135ds18!0!

  

它表示主菜单的第三项为格式化磁盘,它对应的执行过程为 format /dev/rfd0135ds18,本项无子菜单。

  

假如用户想把自己编的实现查询功能程序XXX挂到本程序主菜单第4项上,则可在menu.def中增加下面这一行:

  

!0!4!查询!XXX!0!

  

(2)、对各菜单参数进行说明文件(menu.conf),其格式如下所述:

  

!菜单代号!上一级菜单代号!边框标志!菜单宽度!菜单行数!菜单列数!起始横坐标!起始纵坐标!

  

说明:

  

1、边框标志为"0"表示无框,为"1"表示有边框;

  

2、上级菜单代号为"-1",表示无上级菜单;

  

3、如菜单代号为"0",表示主菜单。

  

当用户对菜单显示样式不满足时,可通过调整此文件设计个性化的界面。

  

  

二 编程实现

  

本程序文件为menu.c,部分代码如下:

  

  

#include

  

#define ESC 27

  

#define ENT 13

  

#define REFRESH 12

  

#define MAX_M 10 /* 菜单最大层数 */

  

  

void initial(),nomlastpos(),revcurpos(),disponepage(),dispprevline();

  

void dispnextline(),domenu(),getmenUConf(),keycont();

  

void getitem(), get_m_conf(), get_m_item(),clearwin(),execprog();

  

/* 标识每一菜单项的结构 */

  

struct menu {

  

short menu_code; /* 所属菜单代号 */

  

short item_order; /* 项顺序号 */

  

char item[20]; /* 菜单项名称 */

  

char prog[80]; /* 本项菜单执行程序 */

  

short submenu_code; /* 下一级菜单编号 */

  

struct menu *next; /* 指向上一项的指针 */

  

struct menu *prev; /* 指向下一项的指针 */

  

} m_item,*head,*this,*new,*last,*scrpos,*lastscrpos,*begin,*lastbegin,*lastscr[MAX_M];

  

/* 标识每一菜单内容的结构 */

  

struct menuconf {

  

short menu_code; /* 菜单代号 */

  

short last_code; /* 上一级菜单代号 */

  

short bord_flag; /* 边框标志 0--无边框 1--有边框 **/

  

short m_wight; /* 菜单显示宽度 */

  

short m_lengh; /* 每一行项数 */

  

short m_col; /* 菜单列数 */

  

short m_bx; /* 菜单起始横坐标 */

  

short m_by; /* 菜单起始纵坐标 */

  

} m_conf;

  

WINDOW *menuwin, *boxwin, *curw, *lastw[MAX_M], *workwin;

  

long curpos, lastcurpos, lastscrcurpos, lastmenucur[MAX_M];

  

short menu_no = 0, wno = 0;

  

  

/* 主函数 */

  

main()

  

{

  

initial();

  

getmenuconf(0); /* 取第0号菜单参数 */

  

  

/* 创建主窗口 */

  

menuwin=newwin(m_conf.m_lengh, m_conf.m_wight, m_conf.m_bx+1, m_conf.m_by+1);

  

curw=menuwin; lastw[wno]=menuwin;

  

  

  

getitem(); /* 取当前菜单各项内容 */

  

domenu(head, 0);

  

endwin();

  

}

  

  

/* 取菜单各项参数函数 */

  

void getitem()

  

{

  

FILE *fp;

  

char buff[0x100];

  

  

/* 建边框窗口 */

  

boxwin=newwin(m_conf.m_lengh+2,m_conf.m_wight+2,m_conf.m_bx,m_conf.m_by);

  

keypad(curw, TRUE);

  

if (m_conf.bord_flag==1) {

  

box(boxwin, 0,0 );

  

wrefresh(boxwin);

  

}

  

  

head=NULL;

  

if ((fp = fopen("./menu.def","r")) == NULL) {

  

fprintf(stderr, "

不能打开菜单定义文件

");

  

return;

  

}

  

while( fgets(buff, 0x100, fp)!=NULL) {

  

get_m_item(buff);

  

  

if (m_item.menu_code != menu_no)

  

continue;

  

  

new=(struct menu*)malloc(sizeof(struct menu));

  

if (head == NULL) {

  

last = head; head = new;

  

}

  

else {

  

this->next = new; last = this;

  

}

  

this = new;

  

this->menu_code=m_item.menu_code;

  

this->item_order=m_item.item_order;

  

strcpy(this->item,m_item.item);

  

strcpy(this->prog,m_item.prog);

  

this->submenu_code=m_item.submenu_code;

  

this->next=NULL;

  

this->prev = last;

  

}

  

fclose(fp);

  

}

  

/* 菜单处理函数 */

  

void domenu(curscrp, curp)

  

struct menu *curscrp;

  

int curp;

  

{

  

int i, x, y;

  

struct menu *mpos;

  

  

this = head;

  

disponepage(this);

  

curpos = curp; scrpos = curscrp;

  

lastcurpos = lastscrcurpos = 0;

  

revcurpos();

  

for(;;) {

  

switch (wgetch(curw)) {

  

case ENT:

  

/* 有下一级菜单 */

  

if ((!strcmp(scrpos->prog, "0")) && (scrpos->submenu_code != 0)) {

  

lastbegin = begin->next;

  

getmenuconf(scrpos->submenu_code);

  

menu_no = scrpos->submenu_code;

  

  

wno++;

  

lastmenucur[wno]=curpos;

  

lastscr[wno] = scrpos;

  

lastw[wno]=curw;

  

  

workwin=newwin(m_conf.m_lengh,m_conf.m_wight,m_conf.m_bx+1,m_conf.m_by+1);

  

curw=workwin;

  

getitem();

  

domenu(head, 0);

  

}

  

/* 是内部函数 */

  

/* 是外部可执行程序 */

  

else {

  

endwin();

  

execprog();

  

}

  

break;

  

case ESC:

  

case 'q':

  

case 'Q':

  

case '0':

  

/* 无上级菜单 */

  

if (m_conf.last_code == -1) {

  

clearwin(); endwin(); exit(0);

  

}

  

/* 有上级菜单 */

  

else {

  

menu_no = m_conf.last_code;

  

clearwin();

  

getmenuconf(menu_no);

  

getitem();

  

touchwin(lastw[wno]);

  

curw=lastw[wno];

  

curpos = lastmenucur[wno];

  

scrpos = lastscr[wno];

  

wno--;

  

wrefresh(curw);

  

}

  

  

break;

  

case 'r':

  

case 'R':

  

case REFRESH: /* 重显屏幕 */

  

wrefresh(curscr);

  

break;

  

case KEY_RIGHT: /* 右光标键 */

  

if ( scrpos->next != NULL ) {

  

lastcurpos = curpos; lastscrpos = scrpos;

  

scrpos=scrpos->next;

  

getyx(curw, x, y);

  

if((x==m_conf.m_lengh-1)&&(curpos%m_conf.m_col==m_conf.m_col-1)){

  

curpos-=(m_conf.m_col-1); lastcurpos = curpos - 1;

  

/* 实现向上卷屏 */

  

wmove(curw, 0, 0); wdeleteln(curw); dispnextline("R");

  

}

  

else

  

curpos++;

  

if ((curpos%m_conf.m_col == 0) && (m_conf.m_lengh == 1)) {

  

revcurpos(); break;

  

}

  

else {

  

nomlastpos(); revcurpos();

  

}

  

}

  

break;

  

case KEY_LEFT: /* 左光标键 */

  

if ( scrpos->prev != NULL ) {

  

lastcurpos = curpos; lastscrpos = scrpos;

  

scrpos=scrpos->prev;

  

getyx(curw, x, y);

  

if ((x==0) && (curpos%m_conf.m_col ==0)) {

  

curpos+=m_conf.m_col-1; lastcurpos = curpos + 1;

  

/* 实现向下卷屏 */

  

winsertln(curw); dispprevline("L");

  

}

  

else

  

curpos--;

  

if ((curpos%m_conf.m_col==m_conf.m_col-1)&&(m_conf.m_lengh==1)) {

  

revcurpos(); break;

  

}

  

else {

  

nomlastpos(); revcurpos();

  

}

  

}

  

break;

  

case KEY_UP: /* 上光标键 */

  

lastcurpos = curpos; lastscrpos = scrpos;

  

mpos = scrpos;

  

for(i=0; i/td>

  

if ( mpos->prev != NULL ) mpos=mpos->prev;

  

else break;

  

精彩图集

赞助商链接