轻量级多级菜单控制框架程序(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、示例代码获取链接

下载链接点击:轻量级菜单框架

#include "menu.h" //菜单资源头文件 #include "menu_res.h" //外部显示库函数 #include "lcm.h" /* 名称:C语言两级菜单(对于大内存可扩展N级菜单)V1.0 作者:中国传惠 Transmart gongxd@126.com 单位:山东科技大学 时间:2009-3-4 编译环境: IDE-Version: uVision3 V3.33 Copyright (c) Keil Elektronik GmbH / Keil Software, Inc 2006 License Information: gongxd 微软用户 微软中国 LIC=BU373-A1HZU-EZJW0-DRWR6-C682M-E9HMS Tool Version Numbers: 工具链路径:C:\Keil\C51\BIN\ C Compiler: C51.Exe V8.05a Assembler: A51.Exe Linker/Locator: BL51.Exe V6.00 Librarian: LIB51.Exe V4.24 Hex Converter: OH51.Exe V2.6 CPU DLL: S8051.DLL V3.06 Dialog DLL: DP51.DLL V2.48b Target DLL: C:\KEIL\VW_C.DLL Dialog DLL: TP51.DLL V2.48b 使用说明: 1.向"menu_res.h"中添加菜单列表 2.向 "Menu_Function.h"中添加菜单响应函数声明 3.在"lcm.h"中替换自己的外部显示库函数,可以用类似的宏定义#define DisplayFunction(int,int) MyDisplayFunction(int,int) 其中"lcm.h"的X,Y坐标起始定义为0,0 (0,0)X------> Y | | \|/ */ #include "Menu_Function.h" //菜单条目格式 //{要显示的的菜单文本,子菜单号,功能函数地址) MenuItemStruct code MenuMain[]={ {"主1 条目1",1,Null}, {"主1 条目2",2,Null}, {"主1 条目3",3,Null}, {"功能函数1",MenuHasFunction,MenuFuntion1}, {"主1 条目5",0,Null}, }; MenuItemStruct code MenuSub1[]={ {"次1 条目1",0,Null}, {"次1 条目2",0,Null}, {"功能函数2",MenuHasFunction,MenuFuntion2}, {"次1 条目4",0,Null}, {"次1 条目5",0,Null}, {"次1 条目6",0,Null}, }; MenuItemStruct code MenuSub2[]={ {"次2 条目1",0,Null}, {"次2 条目2",0,Null}, {"次2 条目3",0,Null}, }; MenuItemStruct code MenuSub3[]={ {"次3 条目1",0,Null}, {"次3 条目2",0,Null}, {"次3 条目3",0,Null}, {"次3 条目4",0,Null}, {"次3 条目5",0,Null}, {"次3 条目6",0,Null}, {"次3 条目7",0,Null}, {"次3 条目8",0,Null}, {"次3 条目9",0,Null}, }; //菜单板列表 MenuPanelStruct code MenuPanel[]={ {MenuPanelID(MenuMain)}, {MenuPanelID(MenuSub1)}, {MenuPanelID(MenuSub2)}, {MenuPanelID(MenuSub3)}, };
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大橙子疯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值