一个适合MCU的分级菜单框架
框架结构体如下:
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); // 退出此菜单会被调用一次
};
菜单的链接实现
/** 连接菜单* @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;}
菜单的调用方式,根据不同的按键执行对应的功能。
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); // 调用当前菜单的OKif(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();
}
本框架没有使用动态内存分配。在菜单分级较多的情况下,没有框架的支持,写起来会显得非常混乱。在框架的支持下,可以将各个菜单功能解耦合,利于后期的维护及扩展。