|
发表于 2018-3-14 18:43:16
|
显示全部楼层
本帖最后由 Gorgon_Meducer 于 2018-3-14 21:26 编辑
如果不同的菜单对应不同的按键,那的确不能直接使用统一的菜单引擎了,但答案也很明显啊。
你在每个菜单的结构体里再加入一个函数指针,指向这个菜单专用的处理引擎函数就行了,
这样对于普通的菜单,那就统一指向一个默认的菜单处理引擎函数;对于有特殊要求的菜单,
就指向自己专用的菜单引擎处理函数就行了。
不知道我说的你是否理解了?
我更新了下菜单的数据结构,希望有所启示:
- #ifndef __FSM_RT_TYPE__
- #define __FSM_RT_TYPE__
- //! \name finit state machine state
- //! @{
- typedef enum {
- fsm_rt_err = -1, //!< fsm error, error code can be get from other interface
- fsm_rt_cpl = 0, //!< fsm complete
- fsm_rt_on_going = 1, //!< fsm on-going
- fsm_rt_wait_for_obj = 2, //!< fsm wait for object
- fsm_rt_asyn = 3, //!< fsm asynchronose complete, you can check it later.
- } fsm_rt_t;
- //! @}
- #endif
- typedef struct __menu_item menu_item_t;
- typedef struct __menut menu_t;
- typedef fsm_rt_t menu_item_handler_t(menu_item_t *);
- struct __menu_item {
- menu_item_handler_t *fnHandle; //!< handler
- menu_t *ptChild; //!< Child Menu
-
- //! depends on your application, you can add/remove/change following members
- char *pchTitle; //!< Menu Title
- char *pchDescription; //!< Description for this menu item
- char chShortCutKey; //!< Shortcut Key value in current menu
- };
- typedef fsm_rt_t menu_engine_t(menu_t *);
- struct __menut {
- menu_item_t *ptItems; //!< menu item list
- uint_fast8_t chCount; //!< menu item count
- menu_t *ptParent; //!< parent menu;
- menu_engine_t *fnEngine; //!< engine for process current menu
- };
复制代码
一个可能的初始化形式是:
- extern fsm_rt_t top_menu_engine(menu_t *ptMenu);
- extern fsm_rt_t top_menu_item_a_handler(menu_item_t *ptItem);
- extern fsm_rt_t top_menu_item_b_handler(menu_item_t *ptItem);
- extern fsm_rt_t top_menu_item_c_handler(menu_item_t *ptItem);
- extern const menu_t c_tTopMenu;
- menu_item_t c_tTopMenuItems[] = {
- {
- top_menu_item_a_handler,
- NULL, //!< child menu
- "Top Menu A",
- "This is Top Menu A",
- },
- {
- top_menu_item_b_handler,
- NULL, //!< child menu
- "Top Menu B",
- "This is Top Menu B"
- },
- {
- top_menu_item_c_handler,
- NULL, //!< child menu
- "Top Menu C",
- "This is Top Menu C"
- }
- };
- const menu_t c_tTopMenu = {
- c_tTopMenuItems, //!< menu item list
- UBOUND(c_tTopMenuItems), //!< menu item count
- NULL, //!< top menu has no parent
- top_menu_engine,
- };
- fsm_rt_t top_menu_item_a_handler(menu_item_t *ptItem)
- {
- return fsm_rt_cpl;
- }
- fsm_rt_t top_menu_item_b_handler(menu_item_t *ptItem)
- {
- return fsm_rt_cpl;
- }
- fsm_rt_t top_menu_item_c_handler(menu_item_t *ptItem)
- {
- return fsm_rt_cpl;
- }
- fsm_rt_t top_menu_engine(menu_t *ptMenu)
- {
- return fsm_rt_cpl;
- }
复制代码
通过加入一些辅助宏,我们可以让这个初始化的菜单的定义过程更简单(只消耗ROM):
- #define __def_menu(__NAME, __PARENT, __ENGINE) \
- extern const menu_t c_tMenu##__NAME; \
- menu_item_t c_tMenu##__NAME##Items[] = {
- #define def_menu(__NAME, __PARENT, __ENGINE) \
- __def_menu(__NAME, (__PARENT), (__ENGINE))
- #define __end_def_menu(__NAME, __PARENT, __ENGINE) \
- }; \
- const menu_t c_tMenu##__NAME = { \
- c_tMenu##__NAME##Items, \
- (sizeof(c_tMenu##__NAME##Items)/sizeof(menu_item_t)), \
- (__PARENT), \
- &(__ENGINE), \
- };
- #define end_def_menu(__NAME, __PARENT, __ENGINE) \
- __end_def_menu(__NAME, (__PARENT), (__ENGINE))
-
-
- #define __extern_menu(__NAME) extern const menu_t c_tMenu##__NAME;
- #define extern_menu(__NAME) __extern_menu(__NAME)
-
- #define __menu(__NAME) c_tMenu##__NAME
- #define menu(__NAME) __menu(__NAME)
- #define __menu_item(__HANDLER, __CHILD_MENU, ...) \
- { \
- &(__HANDLER), \
- (__CHILD_MENU), \
- __VA_ARGS__, \
- },
- #define menu_item(__HANDLER, __CHILD_MENU, ...) \
- __menu_item((__HANDLER), (__CHILD_MENU), __VA_ARGS__)
复制代码
因此,前面初始化的例子就等效的可以简化为:
- extern fsm_rt_t top_menu_engine(menu_t *ptMenu);
- extern fsm_rt_t top_menu_item_a_handler(menu_item_t *ptItem);
- extern fsm_rt_t top_menu_item_b_handler(menu_item_t *ptItem);
- extern fsm_rt_t top_menu_item_c_handler(menu_item_t *ptItem);
- def_menu(TopMenu, NULL, top_menu_engine)
- menu_item(
- top_menu_item_a_handler,
- NULL,
- "Top Menu A",
- "This is Top Menu A"
- )
- menu_item(
- top_menu_item_a_handler,
- NULL,
- "Top Menu B",
- "This is Top Menu B"
- )
- menu_item(
- top_menu_item_a_handler,
- NULL,
- "Top Menu C",
- "This is Top Menu C"
- )
- end_def_menu(TopMenu, NULL, top_menu_engine)
- fsm_rt_t top_menu_item_a_handler(menu_item_t *ptItem)
- {
- return fsm_rt_cpl;
- }
- fsm_rt_t top_menu_item_b_handler(menu_item_t *ptItem)
- {
- return fsm_rt_cpl;
- }
- fsm_rt_t top_menu_item_c_handler(menu_item_t *ptItem)
- {
- return fsm_rt_cpl;
- }
- fsm_rt_t top_menu_engine(menu_t *ptMenu)
- {
- return fsm_rt_cpl;
- }
复制代码
定义好的menu怎么用呢?
需要用到变量的时候,用menu宏,例如:
- menu_t *ptThis = &menu(TopMenu);
复制代码
如果要extern给其它.c文件使用怎么办呢?使用extern_menu宏,例如:
- ...
- extern_menu(TopMenu);
- ...
复制代码
我专门开了一个帖子来详细讨论菜单技术:
https://www.amobbs.com/thread-5688720-1-1.html |
|