程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 用C編寫類Windows菜單

用C編寫類Windows菜單

編輯:關於C語言

在開發程序時,程序的界面、開放性是兩個非常重要的方面,目前,在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, "\n不能打開菜單定義文件\n");
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;
}
if ( i==m_conf.m_col ) {
getyx(curw, x, y);
if (x==0) {
lastcurpos += m_conf.m_col;
/* 實現向下卷屏 */
winsertln(curw); dispprevline("U");
}
else {
curpos-=m_conf.m_col;
}
scrpos = mpos;
if ( m_conf.m_lengh!=1)
nomlastpos();
revcurpos();
}
break;
case KEY_DOWN: /* 下光標鍵 */
lastcurpos = curpos; lastscrpos = scrpos;
mpos = scrpos;
for(i=0; i/td>
if ( mpos->next != NULL )
mpos=mpos->next;
else
break;
}
if ( i==m_conf.m_col ) {
getyx(curw, x, y);
if (x==m_conf.m_lengh-1) {
lastcurpos -= m_conf.m_col;
/* 實現向上卷屏 */
wmove(curw, 0, 0); wdeleteln(curw); dispnextline("D");
}
else
curpos+=m_conf.m_col;
scrpos = mpos;
if ( m_conf.m_lengh!=1)
nomlastpos();
revcurpos();
}
break;
default:
beep();
break;
}
}
}
/* 反顯當前項函數 */
void revcurpos()
{
wattrset(curw, A_STANDOUT);
wmove(curw, curpos/m_conf.m_col,
(curpos%m_conf.m_col)*m_conf.m_wight/m_conf.m_col+m_conf.m_col);
wprintw(curw, "%s", scrpos->item);
wattrset(curw, A_NORMAL);
wrefresh(boxwin);
}
/* 正常顯示上一項函數 */
void nomlastpos() {
wmove(curw, lastcurpos/m_conf.m_col, (lastcurpos%m_conf.m_col)
*m_conf.m_wight/m_conf.m_col+m_conf.m_col);
wprintw(curw, "%s", lastscrpos->item);
}
/* 顯示一頁函數 */
void disponepage(first)
struct menu *first;
{
short col, row;
begin=first; /* begin 為本頁首指針 */
for(row=0; row/td>
for(col=0; col/td>
/* m_conf.m_wight/m_col為每一菜單項應占列數*/
wmove(curw,row,col*m_conf.m_wight/m_conf.m_col+m_conf.m_col);
wprintw(curw, "%s", first->item);
wrefresh(curw);
last = first;
first = first->next;
if (first == NULL) {
break;
}
}
}
}
/* 顯示上一行函數 */
void dispprevline(flag)
char flag[2]; /* L-左光標引起 U-上光標引起 */
{
struct menu *tmppos;
int tmpcurpos;
tmpcurpos = curpos;
tmppos = scrpos;
if ( flag[0] == 'U') {
while ( tmpcurpos % m_conf.m_col != 0) {
tmppos = tmppos->prev;
tmpcurpos--;
}
tmppos = tmppos->prev;
}
for (tmpcurpos = m_conf.m_col-1; tmpcurpos >= 0; tmpcurpos--) {
wmove(curw, 0, (tmpcurpos%m_conf.m_col)
*m_conf.m_wight/m_conf.m_col+m_conf.m_col);
wprintw(curw, "%s", tmppos->item);
begin = tmppos; /*begin 為本頁首指針*/
last = tmppos;
tmppos = tmppos->prev;
if (tmppos == NULL)
break;
}
wrefresh(curw);
}
/* 顯示下一行函數 */
void dispnextline(flag)
char flag[2];/* R-右光標引起 D-下光標引起 */
{
struct menu *tmppos;
int tmpcurpos;
tmpcurpos = curpos;
tmppos = scrpos;
if ( flag[0] == 'D') {
while ( tmpcurpos % m_conf.m_col != m_conf.m_col-1) {
tmppos = tmppos->next; tmpcurpos++;
}
tmppos = tmppos->next;
}
for (tmpcurpos = 0; tmpcurpos < m_conf.m_col; tmpcurpos++) {
wmove(curw, m_conf.m_lengh-1, (tmpcurpos%m_conf.m_col)
*m_conf.m_wight/m_conf.m_col+m_conf.m_col);
wprintw(curw, "%s", tmppos->item);
last=tmppos;/* last 為本頁最後一個結點指針 */
begin=tmppos; tmppos = tmppos->next;
if (tmppos == NULL)
break;
}
}
/* 取指定菜單參數函數 */
void getmenuconf(menu_code)
short menu_code;
{
FILE *fp;
char menu_buff[0x100];
if ((fp = fopen("menu.conf", "r"))==NULL) {
fprintf(stderr, "can not open menu config file");
return;
}
while( fgets(menu_buff, 0x100, fp)!=NULL ) {
get_m_conf(menu_buff);
if (m_conf.menu_code == menu_code)
break;
}
return ;
}
/* 取指定菜單參數處理函數 */
void get_m_conf(menu_conf)
char *menu_conf;
{
register i, j, k;
char buff[20];
j = k = 0;
for (i = 0; i < strlen(menu_conf); i++) {
if ( menu_conf[i] == '!' ) {
j++;
if ( j == 1) {
k = i+1;
continue;
}
switch(j) {
case 2:
memcpy(buff, &menu_conf[k], i-k);
buff[i-k]=0;
m_conf.menu_code = atoi(buff);
k=i+1;
break;
case 3:
memcpy(buff, &menu_conf[k], i-k);
buff[i-k]=0;
m_conf.last_code = atoi(buff);
k=i+1;
break;
case 4:
memcpy(buff, &menu_conf[k], i-k);
buff[i-k]=0;
m_conf.bord_flag = atoi(buff);
k=i+1;
break;
case 5:
memcpy(buff, &menu_conf[k], i-k);
buff[i-k]=0;
m_conf.m_wight = atoi(buff);
k=i+1;
break;
case 6:
memcpy(buff, &menu_conf[k], i-k);
buff[i-k]=0;
m_conf.m_lengh = atoi(buff);
k=i+1;
break;
case 7:
memcpy(buff, &menu_conf[k], i-k);
buff[i-k]=0;
m_conf.m_col = atoi(buff);
k=i+1;
break;
case 8:
memcpy(buff, &menu_conf[k], i-k);
buff[i-k]=0;
m_conf.m_bx = atoi(buff);
k=i+1;
break;
case 9:
memcpy(buff, &menu_conf[k], i-k);
buff[i-k]=0;
m_conf.m_by = atoi(buff);
k=i+1;
break;
default:
break;
}
}
}
}
/* 取指定項參數處理函數 */
void get_m_item(menu_item)
char *menu_item;
{
register i, j, k;
char buff[80];
j = k = 0;
for (i = 0; i < strlen(menu_item); i++) {
if ( menu_item[i] == '!' ) {
j++;
if ( j == 1) {
k = i+1;
continue;
}
switch(j) {
case 2:
memcpy(buff, &menu_item[k], i-k);
buff[i-k] = 0;
m_item.menu_code = atoi(buff);
k=i+1;
break;
case 3:
memcpy(buff, &menu_item[k], i-k);
buff[i-k] = 0;
m_item.item_order = atoi(buff);
k=i+1;
break;
case 4:
memcpy(buff, &menu_item[k], i-k);
buff[i-k] = 0;
strcpy(m_item.item,buff);
k=i+1;
break;
case 5:
memcpy(buff, &menu_item[k], i-k);
buff[i-k] = 0;
strcpy(m_item.prog,buff);
k=i+1;
break;
case 6:
memcpy(buff, &menu_item[k], i-k);
buff[i-k] = 0;
m_item.submenu_code = atoi(buff);
k=i+1;
break;
default:
break;
}
}
}
}
void initial() /* 自定開啟 curses 函式 */
{
initscr();
cbreak(); nonl(); noecho();
intrflush(stdscr,FALSE);
keypad(stdscr,TRUE);
refresh();
}
/* 按鍵等待函數 */
void keycont()
{
fprintf(stderr, "按鍵繼續..."); getchar();
}
/* 運行可執行程序函數 */
void execprog()
{
system("clear");
fprintf(stderr, "%s:\n", scrpos->item);
system(scrpos->prog);
keycont(); initial();
touchwin(boxwin); touchwin(curw); keypad(curw, TRUE);
wrefresh(boxwin); wrefresh(curw);
}
/* 清除窗口函數 */
void clearwin()
{
wmove(boxwin, 0, 0);
wclrtobot(boxwin); wrefresh(boxwin); delwin(curw); delwin(boxwin);
}

三 編譯說明

該程序可用如下命令編譯(在SCO OpenServer 5.05下編譯通過):

cc -o menu menu.c -lcurses

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved