一个适合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();
}

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

相关推荐
木子单片机1 天前
基于51单片机温度检测报警
stm32·单片机·嵌入式硬件·51单片机·keil
hazy1k1 天前
51单片机基础-步进电机控制
stm32·单片机·嵌入式硬件·51单片机
清风6666661 天前
基于单片机的智能收银机模拟系统设计
数据库·单片机·毕业设计·nosql·课程设计
第二层皮-合肥1 天前
RTC时钟原理
单片机·嵌入式硬件
Element_南笙1 天前
吴恩达新课程:Agentic AI(笔记2)
数据库·人工智能·笔记·python·深度学习·ui·自然语言处理
SmartSoftHelp开发辅助优化1 天前
C# WinForm 编程高手:程序,进程,线程。程序,窗体,UI,后台。是如何协调工作的?深度解析>SmartSoftHelp魔法精灵工作室
microsoft·ui·c#
小莞尔2 天前
【51单片机】【protues仿真】基于51单片机送带计数器系统
c语言·单片机·嵌入式硬件·物联网·51单片机
云知谷2 天前
【嵌入式基本功】单片机嵌入式学习路线
linux·c语言·c++·单片机·嵌入式硬件
光子物联单片机2 天前
STM32G474单片机开发入门(十五)CAN通信功能详解及实战
stm32·单片机·嵌入式硬件·mcu
A9better2 天前
嵌入式开发学习日志40——stm32之I2C协议层
stm32·单片机·嵌入式硬件·学习