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. java-GUI编程之AWT组件

    AWT中常用组件 基本组件 组件名 功能 Button Button Canvas 用于绘图的画布 Checkbox 复选框组件(也可当做单选框组件使用) CheckboxGroup 用于将多个Che ...

  2. 无需debug,通过抽象模型快速梳理代码核心流程

    上一篇我们通过DSM来确定了核心对象并构建了抽象模型.本篇是<如何高效阅读源码>专题的第八篇,我们来基于抽象模型来梳理核心流程. 本节主要内容: 如何通过抽象模型来梳理核心流程 从类名和注 ...

  3. 『现学现忘』Git基础 — 4、Git下载与安装

    目录 1.Git下载 2.Git在Windows下的详细安装 3.验证Git是否安装成功 1.Git下载 进入官方地址下载Git客户端:https://git-scm.com/download/win ...

  4. 2021牛客暑期多校训练营3 J 思维

    传送门 J-Counting Triangles_2021牛客暑期多校训练营3 (nowcoder.com) 题目 Goodeat finds an undirected complete graph ...

  5. WEB安全信息收集

    目录 信息收集 子域名&敏感信息 敏感信息收集--Googlehack 敏感信息收集--收集方向 空间测绘引擎域名资产收集 子域名收集 WEB指纹 端口扫描 IP查询 cms识别 WAF识别 ...

  6. 在MAUI中使用Masa Blazor

    Masa Blazor是什么 在此之前我们已经介绍过什么是Masa Blazor,以及如何使用Masa Balzor,如果还有不了解Masa Blazor的同学可以看我上篇文章[初识Masa Blaz ...

  7. SpringJDBC和事务控制

    SpringJDBC和事务控制 主要内容 1.基本配置 <!--依赖导入--> <dependencies> <!-- 添加相关的依赖坐标 --> <!-- ...

  8. 用浏览器快速开启Docker的体验之旅

    互联网科技发展创造了很多奇迹,比如我今天要提到的 docker 技术就是其一.我很早就关注它(在2015年写过这方面的博客),那会儿还只是一个开源项目,现在已经是一个行业事实标准了,它推动了云原生的变 ...

  9. CentOS开机流程详解

    一个执着于技术的公众号 开机流程 BIOS: (Basic Input Output System)基本输入输出系统,它是一组固化到计算机内主板上一个ROM芯片上的程序,保存着计算机最重要的基本输入输 ...

  10. maccms10二开批量入库和资源打包

    批量入库 因为maccms自带的采集采集起来很慢,而且很多资源站的采集接口不能对内容排序,导致最旧的数据最后入库.用java写个采集程序,采集完入库的时候发现不能一次性入库多个数据,导致入库也很慢,所 ...