在 Unix/Linux 字符終端環境下開發具有圖形化界面(TUI)的應用程序,curses/ncurses 庫是標準選擇。本專案實現一個高度可配置、無需重新編譯即可擴展功能的下拉菜單系統,靈感來源於 Windows 應用程序的菜單欄。核心設計:菜單結構與顯示參數完全外部化到文本配置文件,實現「數據驅動界面」。
格式:!菜單代號!項順序號!菜單項名稱!外掛程序名稱!下級菜單代號!
!0!1!文件操作!0!10! // 主菜單項1,有子菜單10
!0!2!系統設置!0!20! // 主菜單項2,有子菜單20
!0!3!格式化磁盤!format /dev/rfd0135ds18!0! // 主菜單項3,執行外部命令,無子菜單
!10!1!讀取文件!read_file!0! // 子菜單10 項1,內部函數
!10!2!寫入文件!write_file!0!
菜單代號=0 表示主菜單。外掛程序=0 表示調用內部函數或進入子菜單。下級菜單=0 表示無子菜單(葉子節點)。項順序號 兼作熱鍵(如數字鍵 1-9)。格式:!菜單代號!上級代號!邊框標志!寬度!行數!列數!起始X!起始Y!
!0!-1!1!30!10!1!5!5! // 主菜單:有框,寬30,10行1列,位置(5,5)
!10!0!1!25!5!1!10!10! // 子菜單10:父0,有框,寬25,5行1列,位置(10,10)
// 雙向鏈表節點:菜單項
struct menu {
short menu_code; // 所屬菜單代號
short item_order; // 項順序/熱鍵
char item[20]; // 顯示名稱
char prog[80]; // 外掛程序/內部命令
short submenu_code; // 子菜單代號
struct menu *next, *prev; // 雙向鏈表指針
};
// 菜單顯示配置
struct menuconf {
short menu_code, last_code;
short bord_flag; // 0無框 1有框
short m_wight, m_lengh, m_col; // 寬、高(行)、列數
short m_bx, m_by; // 起始座標
};
// 窗口管理 (curses WINDOW*)
WINDOW *menuwin, *boxwin, *curw, *lastw[MAX_M], *workwin;
initial():initscr()、cbreak()、noecho()、keypad() 標準 curses 初始化。getmenuconf(code):解析 menu.conf 指定行,填充 m_conf 全局結構。解析器按 ! 分隔字段,atoi/strcpy 賦值。getitem():讀取 menu.def,篩選屬於當前 menu_no 的項,構建雙向鏈表 head,並創建 curses 窗口 menuwin、邊框窗口 boxwin。domenu()核心狀態機:
scrpos:當前高亮項指針。curpos:當前項在頁內的線性索引 (0-based)。wgetch(curw) 獲取按鍵:| 按鍵 | 動作 |
|---|---|
| Enter | 若有子菜單 → 遞歸進入 domenu() (保存父菜單狀態到棧 lastw, lastscr, lastmenucur);若為外部命令 → endwin() 恢復終端執行 system();若為內部函數 → 調用對應處理。 |
| Esc/q/Q/0 | 返回上級菜單 (恢復父窗口、高亮位置、配置);若無父菜單 (last_code=-1) → 退出程序。 |
| 方向鍵 | 更新 scrpos、curpos,處理換頁/捲動 (wdeleteln/winsertln + dispnextline/dispprevline),調用 nomlastpos() 恢復舊項正常顏色,revcurpos() 高亮新項 (A_STANDOUT 屬性)。 |
| R/刷新鍵 | wrefresh(curscr) 重繪全屏。 |