轻量级多级菜单控制框架程序(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;            /*!< &#x5F53;&#x524D;&#x9009;&#x9879;&#x7684;&#x4E2D;&#x6587;&#x5B57;&#x7B26;&#x4E32;&#x63CF;&#x8FF0; */

    const char     *pszEnDesc;          /*!< &#x5F53;&#x524D;&#x9009;&#x9879;&#x7684;&#x82F1;&#x6587;&#x5B57;&#x7B26;&#x4E32;&#x63CF;&#x8FF0; */

    menusize_t      subMenuNum;         /*!< &#x5F53;&#x524D;&#x9009;&#x9879;&#x7684;&#x5B50;&#x83DC;&#x5355;&#x6570;&#x76EE;, &#x5B50;&#x83DC;&#x5355;&#x6570;&#x76EE;&#x4E3A;0&#x5219;&#x8868;&#x793A;&#x4E0B;&#x4E00;&#x7EA7;&#x975E;&#x83DC;&#x5355;&#x754C;&#x9762;, &#x4F1A;&#x6267;&#x884C;&#x975E;&#x83DC;&#x5355;&#x529F;&#x80FD;&#x51FD;&#x6570; */

    struct MenuRegister *pSubMenu;      /*!< &#x5F53;&#x524D;&#x9009;&#x9879;&#x7684;&#x5B50;&#x83DC;&#x5355;&#x5185;&#x5BB9; */

    ShowMenuCallFun_f pfnShowMenuFun;   /*!< &#x5F53;&#x524D;&#x9009;&#x9879;&#x7684;&#x5B50;&#x83DC;&#x5355;&#x663E;&#x793A;&#x6548;&#x679C;&#x51FD;&#x6570;, &#x4E3A;NULL&#x5219;&#x5EF6;&#x7EED;&#x4E0A;&#x7EA7;&#x83DC;&#x5355;&#x663E;&#x793A;&#x6548;&#x679C; */

    MenuCallFun_f     pfnEnterCallFun;  /*!< &#x5F53;&#x524D;&#x9009;&#x9879;&#x786E;&#x5B9A;&#x8FDB;&#x5165;&#x65F6;&#x9700;&#x8981;&#x6267;&#x884C;&#x7684;&#x51FD;&#x6570;, &#x4E3A;NULL&#x4E0D;&#x6267;&#x884C; */

    MenuCallFun_f     pfnExitCallFun;   /*!< &#x5F53;&#x524D;&#x9009;&#x9879;&#x8FDB;&#x5165;&#x540E;&#x5728;&#x9000;&#x51FA;&#x65F6;&#x9700;&#x8981;&#x6267;&#x884C;&#x7684;&#x51FD;&#x6570;, &#x4E3A;NULL&#x4E0D;&#x6267;&#x884C; */

    MenuCallFun_f     pfnRunCallFun;    /*!< &#x5F53;&#x524D;&#x9009;&#x9879;&#x7684;&#x975E;&#x83DC;&#x5355;&#x529F;&#x80FD;&#x51FD;&#x6570;, &#x53EA;&#x6709;&#x5F53;&#x83DC;&#x5355;&#x6570;&#x76EE;&#x4E3A;0&#x6709;&#x6548;, &#x4E3A;NULL&#x4E0D;&#x6267;&#x884C; */

    void             *pExtendData;      /*!< &#x5F53;&#x524D;&#x9009;&#x9879;&#x7684;&#x83DC;&#x5355;&#x663E;&#x793A;&#x6548;&#x679C;&#x51FD;&#x6570;&#x6269;&#x5C55;&#x6570;&#x636E;&#x5165;&#x53C2;, &#x53EF;&#x81EA;&#x884C;&#x8BBE;&#x7F6E;&#x8BE5;&#x5185;&#x5BB9; */
}MenuRegister_t;

/* Exported constants ------------------------------------------------------------------------------------------------*/
/* Exported macro ----------------------------------------------------------------------------------------------------*/

#define GET_MENU_NUM(X)    (sizeof(X) / sizeof(MenuRegister_t))

/* Exported functions ------------------------------------------------------------------------------------------------*/

/* &#x83DC;&#x5355;&#x521D;&#x59CB;&#x5316;&#x548C;&#x53CD;&#x521D;&#x59CB;&#x5316; */
extern int Menu_Init(MenuRegister_t *pMainMenu, uint8_t num, ShowMenuCallFun_f fpnShowMenu);
extern int Menu_DeInit(void);

/* &#x83DC;&#x5355;&#x529F;&#x80FD;&#x8BBE;&#x7F6E; */
extern menubool Menu_IsEnglish(void);
extern int Menu_SetEnglish(menubool isEnable);

/* &#x83DC;&#x5355;&#x9009;&#x9879;&#x663E;&#x793A;&#x65F6;&#x9700;&#x8981;&#x4F7F;&#x7528;&#x7684;&#x529F;&#x80FD;&#x6269;&#x5C55;&#x51FD;&#x6570; */
extern int Menu_UpdateShowBase(MenuShow_t *ptMenuShow, menusize_t showNum);

/* &#x83DC;&#x5355;&#x72B6;&#x6001;&#x83B7;&#x53D6;&#x51FD;&#x6570; */
extern menubool Menu_IsRun(void);
extern menubool Menu_IsMainMenu(void);
extern menubool Menu_IsAtMenu(void);

/* &#x83DC;&#x5355;&#x64CD;&#x4F5C; */
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);

/* &#x83DC;&#x5355;&#x8F6E;&#x8BE2;&#x5904;&#x7406;&#x4EFB;&#x52A1; */
extern int Menu_Task(void);

4、示例代码显示效果

示例代码采用的平台是命令行输出输入显示效果

demo中提供了如何实现图形菜单(主菜单有点粗糙)、普通列表菜单、右侧弹窗菜单(更多设置)等效果演示,菜单样式可自由扩展,足够自由;快捷菜单操作、中英文切换演示。(windows中编译需要将 demo.c转 GBK 编码,Linux 转 utf8 编码,不然可能出现汉字乱码的问题)

轻量级多级菜单控制框架程序(C语言)

以下是通过单片机驱动 OLED 显示的菜单界面显示效果

轻量级多级菜单控制框架程序(C语言)

5、示例代码获取链接

下载链接点击:轻量级菜单框架(最新的功能可切换 develop 分支)

轻量级多级菜单控制框架程序(C语言)

轻量级多级菜单控制框架程序(C语言)

Original: https://www.cnblogs.com/const-zpc/p/16364420.html
Author: 大橙子疯
Title: 轻量级多级菜单控制框架程序(C语言)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/581967/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 嵌入式软件开发中必备软件工具

    1、前言 作为一个软件开发人员,除了程序能力素养方面外,还应该熟练地使用各种常用的辅助工具,所谓”工欲善其事,必先利其器”;通过这些工具能提升自己的专业素养…

    Linux 2023年6月7日
    096
  • 【socket】基于poll和epoll通信温度上报

    网络socket通信 * – poll函数 – epoll函数 – poll代码实现 – epoll代码实现 poll函数 poll…

    Linux 2023年6月13日
    087
  • 离职,问题就解决了吗?

    刚入职场的那几年,我经常对工作有各种抱怨。回想起来,有两次冲动的不必要的离职,或者说应该干得更久一点。一旦有了离职的想法,整个人每天都纠结是去还是留,这种纠结成倍的放大焦虑,让自己…

    Linux 2023年6月6日
    098
  • rm命令弱爆了!

    大家好,我是良许。 创建、删除和修改文件是用户在 Linux 系统中执行的非常常见操作。大家都知道,在 Linux 系统里使用 rm 命令删除单个文件时,几乎一瞬间就完成了。但是如…

    Linux 2023年6月14日
    091
  • redis在php中的基本使用

    //使用autoload加载相关库,这边重点就是为了require $file; spl_autoload_register(function($class) { $file = …

    Linux 2023年5月28日
    085
  • Windows批处理一键添加hosts文件

    批处理一键添加hosts文件 此脚本主要用于安装一些学习软件时需屏弊一些网站,双击一键修改。 @echo off echo 获取Administrator权限 cacls.exe …

    Linux 2023年6月8日
    082
  • PTA 《基础编程题目集》 6-6 求单链表结点的阶乘和

    本题要求实现一个函数,求单链表L结点的阶乘和。这里默认所有结点的值非负,且题目保证结果在int范围内。 函数接口定义: int FactorialSum( List L ); 其中…

    Linux 2023年6月8日
    0125
  • mac redis安装与使用,连接远程服务器 redis

    brew install redis@6.2 #后面@接版本号可指定版本,也可以不指定版本 brew services start redis redis-cli redis-cl…

    Linux 2023年5月28日
    090
  • 基于LNMP快速简单搭建wordpress平台

    一、WordPress 简介 WordPress是一种使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。也可以把WordPress当…

    Linux 2023年6月7日
    091
  • [转]Redis cluster failover

    今天测试了redis cluster failover 功能,在切换过程中很快,但在failover时有force 与takeover 之分 [RHZYTEST_10:REDIS:…

    Linux 2023年5月28日
    077
  • 在Linux命令行内的大小写转换

    在编辑文本时大小写常常是需要注意的地方,大小写的转换是很枯燥而繁琐的工作,所幸,Linux 提供了很多能让这份工作变得容易的命令。接下来让我们看看都有哪些完成大小写转换的命令。 t…

    Linux 2023年6月14日
    0109
  • MHA实现MySQL的高可用性

    对主节点进行监控,可实现自动故障转移至其它从节点;通过提升某一从节点为新的主节点,基于主从复制实现,还需要客户端配合实现。 目前MHA主要支持一主多从的架构,要搭建MHA,要求一个…

    Linux 2023年6月7日
    0100
  • 模拟一个简单的tomcat

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Linux 2023年6月11日
    0101
  • 巧用 JuiceFS Sync 命令跨云迁移和同步数据

    近年来,云计算已成为主流,企业从自身利益出发,或是不愿意被单一云服务商锁定,或是业务和数据冗余,或是出于成本优化考虑,会尝试将部分或者全部业务从线下机房迁移到云或者从一个云平台迁移…

    Linux 2023年6月14日
    096
  • [ Skill ] 如何获取库中的 top cell

    https://www.cnblogs.com/yeungchie/ top cell 的一个特点就是没有被其他的单元所调用,下面举例获取某个库中的 top cell。 1. 获取…

    Linux 2023年6月7日
    078
  • 红警快捷键图示

    最近,实验室的同学们 周末偶尔会玩一玩红警,回忆一下童年,挺愉快的。下面记录一下快捷键,方便操作; 看到B站上红警08,还有对应的快捷键教学视频,也可以直接学习一下; https:…

    Linux 2023年6月14日
    0105
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球