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

轻量级多级菜单控制框架程序(C语言)的更多相关文章

  1. 单片机C语言下LCD多级菜单的一种实现方法

    摘要:     介绍了在C 语言环境下,在LCD 液晶显示屏上实现多级嵌套菜单的一种简便方法,提出了一个结构紧凑.实用的程序模型. 关键词: 液晶显示屏; 多级菜单; 单片机; C 语言; LCD 中 ...

  2. Python基础-小程序练习(跳出多层循环,购物车,多级菜单,用户登录)

    一. 从第3层循环直接跳出所有循环 break_flag = False count = 0 while break_flag == False: print("-第一层") wh ...

  3. MVC5+EF6 入门完整教程13 -- 动态生成多级菜单

    稍微有一定复杂性的系统,多级菜单都是一个必备组件. 本篇专题讲述如何生成动态多级菜单的通用做法. 我们不用任何第三方的组件,完全自己构建灵活通用的多级菜单. 需要达成的效果:容易复用,可以根据mode ...

  4. 谈谈MSP430 的框架程序

    最近在学习MSP430f149这块单片机,开始程序也没烧进去,弄了一天,发现串口不能下载,买了个jtag下载器,才搞定.现在也谈谈开始写程序的一些方法吧 程序重要的是框架,有这个基础之后才能行云流水的 ...

  5. Vue2 实现树形菜单(多级菜单)功能模块

    结构示意图 ├── index.html ├── main.js ├── router │ └── index.js # 路由配置文件 ├── components # 组件目录 │ ├── App. ...

  6. 微信小程序开发语言的选择

    微信使用的开发语言和文件很「特殊」. 小程序所使用的程序文件类型大致分为以下几种: ①WXML(WeiXin Mark Language,微信标记语言) ②WXSS(WeiXin Style Shee ...

  7. WPF权限控制框架——【4】抛砖引玉

    写第一篇"权限控制框架"系列博客是在2021-01-29,在这不到一个月的时间里,收集自己零碎的时间,竟然写出了一个"麻雀虽小,五脏俱全"的权限控制框架:对于一 ...

  8. 前端开发css实战:使用css制作网页中的多级菜单

    前端开发css实战:使用css制作网页中的多级菜单 在日常工作中,大家都会遇到一些显示隐藏类菜单,比如页头导航.二维码显示隐藏.文本提示等等......而这些效果都是可以使用纯css实现的(而且非常简 ...

  9. java 24 - 7 GUI之 创建多级菜单窗体

    需求: 创建多级菜单 步骤: A:创建窗体对象(并设置属性和布局) B:创建菜单栏 C:创建菜单和子菜单 D:逐步添加菜单(子菜单添加到菜单中,菜单添加到菜单栏中) E:窗体中设置菜单栏(菜单栏并不是 ...

随机推荐

  1. SpringMVC的数据响应方式-页面跳转

    1.返回字符串形式 直接返回字符串:此种方式会返回字符串与视图解析器的前后缀拼接后跳转 有关视图解析器的拼接请访问此地址 注意:WEB-INF下的资源一般不能访问,因为转发是服务器的操作所以可以访问到 ...

  2. JavaSSM-总结

    Spring框架技术 SSM(Spring+SpringMVC+Mybatis)阶段的学习,也算是成功出了Java新手村. 前面我们已经学习过Mybatis了. 从这里开始,很多的概念理解起来就稍微有 ...

  3. 演示默认学习用户scott,默认密码是tiger

    默认学习用户scott,默认密码是tiger oracle@prd:/home/oracle$sqlplus /nolog SQL> conn scott/tiger ERROR: ORA-28 ...

  4. 『忘了再学』Shell基础 — 8、管道符介绍

    我们之前已经有文章说过管道符了,今天这里再简单总结一下用法. 1.行提取命令grep grep命令的作用,是在指定的文件中,搜索符合条件的字符串. 命令格式: [root@localhost ~ ] ...

  5. docker进阶_docker-compose

    Docker-compose 为什么使用docker-compose 官方介绍 ​ Compose 是一个用于定义和运行多容器 Docker 应用程序的工具.使用 Compose,您可以使用 YAML ...

  6. 最新Mysql大厂面试必会的34问题

    目录 1.mysql的隔离级别 2.MYSQL性能优化 常用5种方式 3.索引详解 1.何为索引,有什么用? 2.索引的优缺点 4.什么情况下需要建索引? 5.什么情况下不建索引? 6.索引的底层数据 ...

  7. XCTF练习题---CRYPTO---wtc_rsa_bbq

    XCTF练习题---CRYPTO---wtc_rsa_bbq flag:flag{how_d0_you_7urn_this_0n?} 解题步骤: 1.观察题目,下载附件 2.下载后是一个文件,不清楚格 ...

  8. 劳动节快乐!手写个核心价值观编码工具 - Python实现

    前言 今天是五一劳动节,祝各位无产阶级劳动者节日快乐! 然后来整活分享一些有趣的东西~ 这个小工具是我大学时做着玩的,对于各位接班人来说,12个词的核心价值观这东西,大家都非常熟悉了,这工具可以实现将 ...

  9. Windows平台安装SQLite3数据库

    Windows平台安装SQLite3数据库 话不多说,开始! 访问SQLite官网下载资源 在搜索引擎中键入SQLite3关键字寻找官网入口或直接点击此处前往SQLite官网,官网界面如下: 点击页面 ...

  10. ThinkPHP V6.0.12在php8.1下验证码出现问题

    一.问题描述 1.项目需求要求使用PHP8.1.*版本 2.运行程序发现验证码不生效报错如下: 二.错误描述 1.报错信息得出:从浮点(数字)到整数的隐式转换将失去精度 三.解决流程 1.找到报错文件 ...