1、前言

作为嵌入式软件开发,可能经常会使用命令行或者显示屏等设备实现人机交互的功能,功能中通常情况都包含 UI 菜单设计;很多开发人员都会有自己的菜单框架模块,防止重复造轮子,网上有很多这种菜单框架的代码,但是大多耦合性太强,无法独立出来适配不同的菜单设计。

本文介绍一个降低了耦合性,完全独立的菜单框架,菜单显示风格和显示平台完全由自己根据需求设计,而菜单操作统一由菜单模块处理即可,提高程序的移植性。


2、介绍

菜单框架代码主要特点有:

  • 采用链表方式实现多级菜单(通过配置选择采用动态分配或者数组实现)
  • 菜单框架作为独立模块,拒绝和按键模块、显示模块进行耦合
  • 在十分独立的情况下,也保证不受菜单的显示风格和显示平台影响,可自由选择设计显示风格和显示平台
  • 快捷菜单操作等
  • 可以采用表驱动的方式初始化菜单,提高代码的可读性

3、代码功能

源文件部分代码如下:

  1. /**
  2. * @brief 菜单初始化
  3. *
  4. * @param[in] pMainMenu 主菜单注册信息
  5. * @param[in] num 主菜单数目
  6. * @param[in] fpnShowMenu 主菜单显示效果函数
  7. * @return 0,成功; -1,失败
  8. */
  9. int Menu_Init(MenuRegister_t *pMainMenu, uint8_t num, ShowMenuCallFun_f fpnShowMenu)
  10. {
  11. MenuCtrl_t *pMenuCtrl = NULL;
  12. #if MENU_MAX_DEPTH != 0
  13. sg_currMenuDepth = 0;
  14. #endif
  15. if ((pMenuCtrl = NewMenu()) != NULL)
  16. {
  17. pMenuCtrl->pLastMenuCtrl = NULL;
  18. pMenuCtrl->pfnShowMenuFun = fpnShowMenu;
  19. pMenuCtrl->pMenuInfo = pMainMenu;
  20. pMenuCtrl->menuNum = num;
  21. pMenuCtrl->currPos = 0;
  22. pMenuCtrl->isRunCallback = 0;
  23. sg_tMenuManage.pCurrMenuCtrl = pMenuCtrl;
  24. return 0;
  25. }
  26. return -1;
  27. }

头文件部分代码如下:

  1. /**
  2. * @brief 菜单信息注册结构体
  3. *
  4. */
  5. typedef struct MenuRegister
  6. {
  7. const char *pszDesc; /*!< 当前选项的中文字符串描述 */
  8. const char *pszEnDesc; /*!< 当前选项的英文字符串描述 */
  9. menusize_t subMenuNum; /*!< 当前选项的子菜单数目, 子菜单数目为0则表示下一级非菜单界面, 会执行非菜单功能函数 */
  10. struct MenuRegister *pSubMenu; /*!< 当前选项的子菜单内容 */
  11. ShowMenuCallFun_f pfnShowMenuFun; /*!< 当前选项的子菜单显示效果函数, 为NULL则延续上级菜单显示效果 */
  12. MenuCallFun_f pfnEnterCallFun; /*!< 当前选项确定进入时需要执行的函数, 为NULL不执行 */
  13. MenuCallFun_f pfnExitCallFun; /*!< 当前选项进入后在退出时需要执行的函数, 为NULL不执行 */
  14. MenuCallFun_f pfnRunCallFun; /*!< 当前选项的非菜单功能函数, 只有当菜单数目为0有效, 为NULL不执行 */
  15. void *pExtendData; /*!< 当前选项的菜单显示效果函数扩展数据入参, 可自行设置该内容 */
  16. }MenuRegister_t;
  17. /* Exported constants ------------------------------------------------------------------------------------------------*/
  18. /* Exported macro ----------------------------------------------------------------------------------------------------*/
  19. #define GET_MENU_NUM(X) (sizeof(X) / sizeof(MenuRegister_t))
  20. /* Exported functions ------------------------------------------------------------------------------------------------*/
  21. /* 菜单初始化和反初始化 */
  22. extern int Menu_Init(MenuRegister_t *pMainMenu, uint8_t num, ShowMenuCallFun_f fpnShowMenu);
  23. extern int Menu_DeInit(void);
  24. /* 菜单功能设置 */
  25. extern menubool Menu_IsEnglish(void);
  26. extern int Menu_SetEnglish(menubool isEnable);
  27. /* 菜单选项显示时需要使用的功能扩展函数 */
  28. extern int Menu_UpdateShowBase(MenuShow_t *ptMenuShow, menusize_t showNum);
  29. /* 菜单状态获取函数 */
  30. extern menubool Menu_IsRun(void);
  31. extern menubool Menu_IsMainMenu(void);
  32. extern menubool Menu_IsAtMenu(void);
  33. /* 菜单操作 */
  34. extern int Menu_Reset(void);
  35. extern int Menu_Enter(void);
  36. extern int Menu_Exit(uint8_t isReset);
  37. extern int Menu_SelectPrevious(uint8_t isAllowRoll);
  38. extern int Menu_SelectNext(uint8_t isAllowRoll);
  39. /* 菜单轮询处理任务 */
  40. 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. NodeJS学习day2

    今天还是接着学习IO,主要方面是文件路径相关操作 练习代码如下: const fs = require('fs') // 执行C:\CS\Node.js>node .\day2\fsRoad.j ...

  2. php实验一专属跳转博文

    今天完成了php关于设计个人博客主页的实验一作业. 这是php实验一作业中博客的跳转链接页.  

  3. 谈谈.NET Core下如何利用 AsyncLocal 实现共享变量

    前言 在Web 应用程序中,我们经常会遇到这样的场景,如用户信息,租户信息本次的请求过程中都是固定的,我们希望是这种信息在本次请求内,一次赋值,到处使用.本文就来探讨一下,如何在.NET Core 下 ...

  4. 使用Kubeadm搭建高可用Kubernetes集群

    1.概述 Kubenetes集群的控制平面节点(即Master节点)由数据库服务(Etcd)+其他组件服务(Apiserver.Controller-manager.Scheduler...)组成. ...

  5. HCIE笔记-第一节-网络的基本概念

    R&S= 路由交换 Datacom =数通 =数据通信 某个设备产生了数据之后,借助整体的网络到达目的地的过程. 网络历史 -- 数通为什么产生? 1946年:世界上第一台计算机诞生.军事 科 ...

  6. PyTorch 广播机制

    PyTorch 广播机制 定义 PyTorch的tensor参数可以自动扩展其大小.一般的是小一点的会变大,来满足运算需求. 规则 满足一下情况的tensor是可以广播的. 至少有一个维度 两个ten ...

  7. GO 前后端分离开源后台管理系统 Gfast v2.0.4 版发布

    更新内容:1.适配插件商城,开发环境从后台直接安装插件功能:2.代码生成细节修复及功能完善(支持生成上传文件.图片及富文本编辑器功能):3.增加swagger接口文档生成:4.更新goframe版本至 ...

  8. win10屏幕亮度无法调节,已解决

    一.问题背景 最近遇到了屏幕亮度无法调节的问题,屏幕特别亮,亮瞎眼的那种,安装各种驱动和修改注册表都不起作用,右键显示器设置根本找不到亮度调节,有时候可以找到但是调节不起作用. 二.发现原因 经过各种 ...

  9. 详解MySQL索引

    原文链接详解MySQL索引 索引介绍 索引是帮助MySQL高效获取数据的数据结构.在数据之外,数据库系统还维护着一个用来查找数据的数据结构,这些数据结构指向着特定的数据,可以实现高级的查找算法. 本文 ...

  10. 用户与安全 -(1)Linux用户及组管理

    关注「开源Linux」,选择"设为星标" 回复「学习」,有我为您特别筛选的学习资料~ 前言 Linux 是多用户多任务操作系统,换句话说,Linux 系统支持多个用户在同一时间内登 ...