輕量級多級菜單控制框架程式(C語言)
1、前言
作為嵌入式軟體開發,可能經常會使用命令行或者顯示器等設備實現人機交互的功能,功能中通常情況都包含 UI 菜單設計;很多開發人員都會有自己的菜單框架模組,防止重複造輪子,網上有很多這種菜單框架的程式碼,但是大多耦合性太強,無法獨立出來適配不同的菜單設計。
本文介紹一個降低了耦合性,完全獨立的菜單框架,菜單顯示風格和顯示平台完全由自己根據需求設計,而菜單操作統一由菜單模組處理即可,提高程式的移植性。
2、介紹
菜單框架程式碼主要特點有:
- 採用鏈表方式實現多級菜單(通過配置選擇採用動態分配或者數組實現)
- 菜單框架作為獨立模組,拒絕和按鍵模組、顯示模組進行耦合
- 在十分獨立的情況下,也保證不受菜單的顯示風格和顯示平台影響,可自由選擇設計顯示風格和顯示平台
- 快捷菜單操作等
- 可以採用表驅動的方式初始化菜單,提高程式碼的可讀性
3、程式碼功能
源文件部分程式碼如下:
/**
* @brief 菜單初始化
*
* @param[in] pMainMenu 主菜單註冊資訊
* @param[in] num 主菜單數目
* @param[in] fpnShowMenu 主菜單顯示效果函數
* @return 0,成功; -1,失敗
*/
int Menu_Init(MenuRegister_t *pMainMenu, uint8_t num, ShowMenuCallFun_f fpnShowMenu)
{
MenuCtrl_t *pMenuCtrl = NULL;
#if MENU_MAX_DEPTH != 0
sg_currMenuDepth = 0;
#endif
if ((pMenuCtrl = NewMenu()) != NULL)
{
pMenuCtrl->pLastMenuCtrl = NULL;
pMenuCtrl->pfnShowMenuFun = fpnShowMenu;
pMenuCtrl->pMenuInfo = pMainMenu;
pMenuCtrl->menuNum = num;
pMenuCtrl->currPos = 0;
pMenuCtrl->isRunCallback = 0;
sg_tMenuManage.pCurrMenuCtrl = pMenuCtrl;
return 0;
}
return -1;
}
頭文件部分程式碼如下:
/**
* @brief 菜單資訊註冊結構體
*
*/
typedef struct MenuRegister
{
const char *pszDesc; /*!< 當前選項的中文字元串描述 */
const char *pszEnDesc; /*!< 當前選項的英文字元串描述 */
menusize_t subMenuNum; /*!< 當前選項的子菜單數目, 子菜單數目為0則表示下一級非菜單介面, 會執行非菜單功能函數 */
struct MenuRegister *pSubMenu; /*!< 當前選項的子菜單內容 */
ShowMenuCallFun_f pfnShowMenuFun; /*!< 當前選項的子菜單顯示效果函數, 為NULL則延續上級菜單顯示效果 */
MenuCallFun_f pfnEnterCallFun; /*!< 當前選項確定進入時需要執行的函數, 為NULL不執行 */
MenuCallFun_f pfnExitCallFun; /*!< 當前選項進入後在退出時需要執行的函數, 為NULL不執行 */
MenuCallFun_f pfnRunCallFun; /*!< 當前選項的非菜單功能函數, 只有當菜單數目為0有效, 為NULL不執行 */
void *pExtendData; /*!< 當前選項的菜單顯示效果函數擴展數據入參, 可自行設置該內容 */
}MenuRegister_t;
/* Exported constants ------------------------------------------------------------------------------------------------*/
/* Exported macro ----------------------------------------------------------------------------------------------------*/
#define GET_MENU_NUM(X) (sizeof(X) / sizeof(MenuRegister_t))
/* Exported functions ------------------------------------------------------------------------------------------------*/
/* 菜單初始化和反初始化 */
extern int Menu_Init(MenuRegister_t *pMainMenu, uint8_t num, ShowMenuCallFun_f fpnShowMenu);
extern int Menu_DeInit(void);
/* 菜單功能設置 */
extern menubool Menu_IsEnglish(void);
extern int Menu_SetEnglish(menubool isEnable);
/* 菜單選項顯示時需要使用的功能擴展函數 */
extern int Menu_UpdateShowBase(MenuShow_t *ptMenuShow, menusize_t showNum);
/* 菜單狀態獲取函數 */
extern menubool Menu_IsRun(void);
extern menubool Menu_IsMainMenu(void);
extern menubool Menu_IsAtMenu(void);
/* 菜單操作 */
extern int Menu_Reset(void);
extern int Menu_Enter(void);
extern int Menu_Exit(uint8_t isReset);
extern int Menu_SelectPrevious(uint8_t isAllowRoll);
extern int Menu_SelectNext(uint8_t isAllowRoll);
/* 菜單輪詢處理任務 */
extern int Menu_Task(void);
4、示例程式碼顯示效果
示例程式碼採用的平台是命令行輸出輸入顯示效果
demo中提供了如何實現圖形菜單(主菜單有點粗糙)、普通列表菜單、右側彈窗菜單(更多設置)等效果演示,菜單樣式可自由擴展,足夠自由;快捷菜單操作、中英文切換演示。(windows中編譯需要將 demo.c轉 GBK 編碼,Linux 轉 utf8 編碼,不然可能出現漢字亂碼的問題)
以下是通過單片機驅動 OLED 顯示的菜單介面顯示效果
5、示例程式碼獲取鏈接
下載鏈接點擊:輕量級菜單框架(最新的功能可切換 develop 分支)