[转]菜单响应(ADD_APPLICATION_MENUITEM_HILITE_HANDLER SetHiliteHandler)

菜单响应函数
2010-10-27 21:09:20
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。 http://ihome.blog.51cto.com/2033151/411624
                                                                         菜单响应
       MTK 手机开发中,菜单响应是非常普遍的事情了,因此非常有必要对此做一下总结。了解其原理才能运用自如。
1 固定添加响应函数
ADD_APPLICATION_MENUITEM_HILITE_HANDLER(MenuID, HiliteHandler);
此函数用来为单个菜单项添加响应函数,告诉系统那个菜单对应那个响应函数。具体其原理是什么呢?如果让我们自己来实现这个关联的话,我们可能会定义一个类似下面的结构体:
typedef void (*Fun)( void);
typedef struct menu_hilite_handler
{
  U16 nMenuItemID;
        Fun HiliteFun;
}MENU_HILITE_HANDLER;
同样, MTK 本身也是使用类似的方法来实现的,不过 MTK 的实现和我们的略有不同:
RESGEN_MENU_HILITE_HANDLER    nMenuHiliteHandlers[MAX_MENU_ITEMS];
typedef struct resgen_menu_hilite_handler
{
        U16 nMenuItemId;                                                    
S8    MenuItemIdEnum[MAX_MENUID_ENUM];                
S8    HiliteFuncName[MAX_HANDLER_NAME];    
} RESGEN_MENU_HILITE_HANDLER;
其中 MenuItemIdEnum HiliteFuncName 分别是菜单 ID 和函数名的字符串形式。但是 MTK 是怎么通过函数名字符串和菜单字符串将他们关联起来的呢。由于无法查到内部实现代码,对此只能保留一份困惑。我们先放下这份困惑,往后看,也许后面的知识就能解决我们这份困惑。
 
总结:这种添加菜单响应函数的方法仅用于固定添加,即只能写死到程序中。
 
2 实时添加响应函数
void SetHiliteHandler(U16 itemid, FuncPtr hiliteFuncPtr);
 
这种方式可以动态的进行注册菜单项响应函数。它的实现原理和我们上面的类似:
typedef struct
{
        U32         menu_id;
        FuncPtr hilite_hdlr;
}mmi_frm_hilite_hdlr_struct;


static    mmi_frm_hilite_hdlr_struct    
mmi_frm_int_hilite_hdlr_table[MMI_FRM_MAX_HILITE_HDLR];
#define MMI_FRM_MAX_HILITE_HDLR 500
看到上面的定义,我们不免有些欣喜,因为我们很能理解这种实现方式,可是又会有些困惑。为什么它和上面的实现方式不同的,并且大小只有 500 ,能放下所有的菜单项吗? MTK 到底遵循那一套机制呢?面对这一连串的问题,我们就不得不理解 SetHiliteHandler ADD_APPLICATION_MENUITEM_HILITE_HANDLER 深层次的区别了。前者其实是针对子菜单而言的,也就是一个主菜单下面的菜单项。这也是它的大小只有 500 的原因,因为 500 对于一个菜单而言已经足够了。如果不够我们自行进行扩展就是了。而后者是针对所有的菜单而言的,包括主菜单和子菜单。因此它的大小就应该很大了,具体定义多少即够用也不太浪费空间呢。这个谁也说不准,干脆我们就不指定固定的大小,根据菜单个数自动改变大小。
#define MAX_MENU_ITEMS  MAX_MENU_ITEMS_VALUE
MAX_MENU_ITEMS_VALUE 是菜单枚举的最后一个值。呵呵,是不是很巧妙啊。好,那问题又来了,使用 SetHiliteHandler 函数注册响应函数后,什么时候执行呢?这就涉及到了另外一个函数:
FuncPtr mmi_frm_get_hilite_hdlr(U16 menu_id);
 
这个函数用于获得指定菜单项的响应函数。这个函数会在 ExecuteCurrHiliteHandler_Ext 中调用。

currFuncPtr = mmi_frm_get_hilite_hdlr((U16)hiliteItemID);

if (currFuncPtr)
{
     (*currFuncPtr) ();
}
这样就执行了我们的菜单响应函数。对于 ExecuteCurrHiliteHandler_Ext 将在下面进行分析。
 
3 菜单屏幕注册函数
void RegisterHighlightHandler( void (*f) (S32 item_index));
 
这个函数用于针对于某一个菜单屏幕注册菜单高亮函数,它是针对于某一个主菜单下的所有子菜单而言的。因此每进入一个菜单屏幕前都会使用此函数注册高亮函数的。
    一般的菜单屏幕(菜单型)
RegisterHighlightHandler(ExecuteCurrHiliteHandler); 是极其常用的方式,也是我目前见到的唯一方式。 ExecuteCurrHiliteHandler 就是用于寻找高亮菜单的响应函数并执行。
void ExecuteCurrHiliteHandler(S32 hiliteid)
{

     ExecuteCurrHiliteHandler_Ext(hiliteid);
     …
}
void ExecuteCurrHiliteHandler_Ext(S32 hiliteid)
{
        FuncPtr currFuncPtr = NULL;
        S32 hiliteItemID;
        currHiliteID = (U16) hiliteid;
         if (g_mask_hilite_mask != 0xFFFFFFFF)
        {
                 /* If the screen uses MaskHiliteItems */
                U8 i;    
                U8 noOfChild = (U8) GetNumOfChild(g_mask_hilite_partent_id);
                S32 index = -1;

                MMI_ASSERT(noOfChild <= 32);

                 /* calculate the real index of the menu */
                 for (i = 0; i < noOfChild; i++)
                {
                         if (IsBitSet(g_mask_hilite_mask, i))
                        {
                                index++;
                        }
                         if (index == hiliteid)
                        {
                                 break;
                        }
                }
                hiliteItemID = GetSeqItemId_Ext((U16) currParentID, (S16) i);
                currFuncPtr = mmi_frm_get_hilite_hdlr((U16)hiliteItemID);
        }
         else
#endif /* __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__ */
        {
                 /* check if menuitem is hidden */
                hiliteItemID = GetSeqItemId_Ext((U16) currParentID, (S16) hiliteid);        
                currFuncPtr = mmi_frm_get_hilite_hdlr((U16)hiliteItemID);
        }

         if (currFuncPtr)
        {
                (*currFuncPtr) ();
        }
}
OK ,看完这两个函数,一切都一幕了然了。
       特殊菜单屏幕
电话簿列表可以理解为一个特殊的菜单屏幕。每个联系人理解为一个菜单项。
这时 RegisterHighlightHandler 的参数的功能是获得高亮项在 g_phb_name_index 中的位置,并将该位置保存下来以便以后使用。
g_phb_cntx.active_index = i;
g_phb_cntx.active_index_second = i;
OK ,至此基本上常用的菜单注册我们都见到了,下面我们来解决我们上面的困惑。 ADD_APPLICATION_MENUITEM_HILITE_HANDLER SetHiliteHandler 的机制到底有什么区别。 MTK 到底采用的是哪种机制呢?为了理解这个我们可以想到一个常识,即高亮菜单一般型时都会执行 ExecuteCurrHiliteHandler 函数,而这个函数是通过 mmi_frm_get_hilite_hdlr 获得菜单高亮函数的。 OK ,至此已经很明了了。 ADD_APPLICATION_MENUITEM_HILITE_HANDLER SetHiliteHandler 都是通过 mmi_frm_get_hilite_hdlr 获得高亮函数的。我们只需看 mmi_frm_get_hilite_hdlr 的实现就 OK 了。从 mmi_frm_get_hilite_hdlr 的实现上我们可以两个表:
mmi_frm_int_hilite_hdlr_table
mmi_frm_const_hilite_hdlr_table
第一个表就是我们刚才提到的 SetHiliteHandler ,那么下面一个就是 ADD_APPLICATION_MENUITEM_HILITE_HANDLER 的表了,从他的定义上很容易证实这一点。
const mmi_frm_hilite_hdlr_struct mmi_frm_const_hilite_hdlr_table[] = {
        {MAIN_MENU_PHONEBOOK_MENUID, highlight_mainmenu_phonebook},

};
但我们应该清楚定义这个表的文件只是编译后生成的文件。这个文件是怎么生成的呢。这就是我们上面说到的保存菜单字符串和函数字符串的作用了。 MTK 是使用 C 语言中的写文件的方式生成的。
 
OK ,至此一切都清楚明了了。

本文出自 “乘风破浪” 博客,请务必保留此出处http://ihome.blog.51cto.com/2033151/411624

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值