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

Unix下用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, " 不能打開菜單定義文件 ");
   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;
 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved