一个适合MCU的分级菜单框架

框架结构体如下:

cpp 复制代码
struct ui_menu
{
    uint8_t item;                         // 当前选择的子菜单编号
    uint8_t level;                          // 菜单级别,0是最高级别,主菜单。
    struct ui_menu* parent;                 // 父菜单,即上一级菜单 
    struct ui_menu* items[UI_MENU_ITEM_MAX];//此菜单下的子菜单
    uint8_t (*on_Key_Up)(void);             // 返回值,是否是最后一个子项,可根据此返回值执行特定的操作
    uint8_t (*on_Key_Down)(void);           // 返回值,是否是最后一个子项,可根据此返回值执行特定的操作
    struct ui_menu* (*on_Key_Back)(void);   // 返回上一级菜单
    struct ui_menu* (*on_Key_OK)(uint8_t* flag);
    void (*menu_Show)(void);                // 显示逻辑在此处执行
    void (*menu_Enter)(uint8_t item);       // 进入此菜单会被调用一次
    void (*menu_Exit)(void);                // 退出此菜单会被调用一次
};

菜单的链接实现

cpp 复制代码
/*
 * 连接菜单
 * @param in:parent:父菜单,为空则为顶级菜单
 * @param in:item:父菜单下的一个菜单项,不能为空
 * @param in:itemIndex:本菜单功能不使用动态分配,索引不能超过最大索引。
 */
int UI_Menu_Link(ui_menu_t* parent,ui_menu_t* item,uint8_t itemIndex)
{
    if(item == NULL)
    {
        return -1;
    }
    if(itemIndex >= UI_MENU_ITEM_MAX)
    {
        return -1;
    }
    if(parent == NULL)
    {
        return -1;
    }
    item->level = parent->level + 1;        // 将当前项设置为父菜单的下一级
    item->parent = parent;
    parent->items[itemIndex] = item;
    return 0;
}

ui_menu_t* UI_Menu_Top_Get(ui_menu_t* item)
{
    ui_menu_t* top = item;
    if(top != NULL)
    {
        while(top->parent != NULL){
            top = top->parent;
        }
    }
    return top;

    
}

菜单的调用方式,根据不同的按键执行对应的功能。

cpp 复制代码
void UI_Page_Menu_Handler(uint16_t key)
{
    uint16_t keyEvent = key;
    uint8_t isSave = 0;     

    if(keyEvent == KEY_OK)      // 保存参数,进入下一步
    {
        if(curMenu->on_Key_OK)
        {
            curMenu = curMenu->on_Key_OK(&isSave);      // 调用当前菜单的OK
            if(curMenu->menu_Enter)
            {
                if(curMenu->level > lastMenu->level)
                {
                    curMenu->menu_Enter(lastMenu->itemID);
                }
            }
            lastMenu = curMenu;
        }
        else
        {
            isSave = 0xFF;
        }
        
        if(isSave == 1)      // 保存数据
        {

        }
        else if(isSave == 0)
        {

        }        
    }
    else if(keyEvent == KEY_BACK)
    {
        if(curMenu->menu_Exit)
        {
            curMenu->menu_Exit();
        }
        if(curMenu->on_Key_Back)
        {
            curMenu = curMenu->on_Key_Back();
            lastMenu = curMenu;
        }

    }
    else if(keyEvent == KEY_UP)
    {
        if(curMenu->on_Key_Up)
        {
            if(curMenu->on_Key_Up())
            {

            }
            else
            {

            }
        }        
    }
    else if(keyEvent == KEY_DOWN)
    {
        if(curMenu->on_Key_Down)
        {
            if(curMenu->on_Key_Down())
            {

            }
            else
            {

            }
        }
        
    }  
    curMenu->menu_Show();
}

本框架没有使用动态内存分配。在菜单分级较多的情况下,没有框架的支持,写起来会显得非常混乱。在框架的支持下,可以将各个菜单功能解耦合,利于后期的维护及扩展。

相关推荐
开开心心loky11 小时前
[iOS] push 和 present Controller 的区别
ui·ios·objective-c·cocoa
点灯小铭11 小时前
基于STM32单片机的智能粮仓温湿度检测蓝牙手机APP设计
stm32·单片机·智能手机·毕业设计·课程设计
眠りたいです11 小时前
基于脚手架微服务的视频点播系统-播放控制部分
c++·qt·ui·微服务·云原生·架构·播放器
沐欣工作室_lvyiyi11 小时前
基于单片机的智能路灯(论文+源码)
单片机·嵌入式硬件·毕业设计
Yyq1302086968211 小时前
SIT1050 5V 供电,±40V 接口耐压,1Mbps 高速 CAN 总线收发器
单片机·嵌入式硬件
云伴枫轻舞12 小时前
我对 OTA 的理解随记,附GD32/STM32例程
stm32·单片机·嵌入式硬件
LS·Cui13 小时前
单片机按键示例功能
单片机
【ql君】qlexcel13 小时前
MCU上电到运行的全过程
单片机·嵌入式硬件·mcu·启动过程
搞一搞汽车电子13 小时前
S32K3平台eMIOS 应用说明
开发语言·驱动开发·笔记·单片机·嵌入式硬件·汽车
pQAQqa13 小时前
FreeRTOS项目(2)摇杆按键检测
stm32·单片机·嵌入式硬件·freertos