輕量級多級選單控制框架程式(C語言)

2022-06-17 18:01:54

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 分支)