菜单响应
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
在
MTK
手机开发中,菜单响应是非常普遍的事情了,因此非常有必要对此做一下总结。了解其原理才能运用自如。
1
固定添加响应函数
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
此函数用来为单个菜单项添加响应函数,告诉系统那个菜单对应那个响应函数。具体其原理是什么呢?如果让我们自己来实现这个关联的话,我们可能会定义一个类似下面的结构体:
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
同样,
MTK
本身也是使用类似的方法来实现的,不过
MTK
的实现和我们的略有不同:
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
其中
MenuItemIdEnum
和
HiliteFuncName
分别是菜单
ID
和函数名的字符串形式。但是
MTK
是怎么通过函数名字符串和菜单字符串将他们关联起来的呢。由于无法查到内部实现代码,对此只能保留一份困惑。我们先放下这份困惑,往后看,也许后面的知识就能解决我们这份困惑。
总结:这种添加菜单响应函数的方法仅用于固定添加,即只能写死到程序中。
2
实时添加响应函数
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
这种方式可以动态的进行注册菜单项响应函数。它的实现原理和我们上面的类似:
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
看到上面的定义,我们不免有些欣喜,因为我们很能理解这种实现方式,可是又会有些困惑。为什么它和上面的实现方式不同的,并且大小只有
500
,能放下所有的菜单项吗?
MTK
到底遵循那一套机制呢?面对这一连串的问题,我们就不得不理解
SetHiliteHandler
和
ADD_APPLICATION_MENUITEM_HILITE_HANDLER
深层次的区别了。前者其实是针对子菜单而言的,也就是一个主菜单下面的菜单项。这也是它的大小只有
500
的原因,因为
500
对于一个菜单而言已经足够了。如果不够我们自行进行扩展就是了。而后者是针对所有的菜单而言的,包括主菜单和子菜单。因此它的大小就应该很大了,具体定义多少即够用也不太浪费空间呢。这个谁也说不准,干脆我们就不指定固定的大小,根据菜单个数自动改变大小。
#define MAX_MENU_ITEMS MAX_MENU_ITEMS_VALUE
MAX_MENU_ITEMS_VALUE
是菜单枚举的最后一个值。呵呵,是不是很巧妙啊。好,那问题又来了,使用
SetHiliteHandler
函数注册响应函数后,什么时候执行呢?这就涉及到了另外一个函数:
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
这个函数用于获得指定菜单项的响应函数。这个函数会在
ExecuteCurrHiliteHandler_Ext
中调用。
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
这样就执行了我们的菜单响应函数。对于
ExecuteCurrHiliteHandler_Ext
将在下面进行分析。
3
菜单屏幕注册函数
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
这个函数用于针对于某一个菜单屏幕注册菜单高亮函数,它是针对于某一个主菜单下的所有子菜单而言的。因此每进入一个菜单屏幕前都会使用此函数注册高亮函数的。
①
一般的菜单屏幕(菜单型)
RegisterHighlightHandler(ExecuteCurrHiliteHandler);
是极其常用的方式,也是我目前见到的唯一方式。
ExecuteCurrHiliteHandler
就是用于寻找高亮菜单的响应函数并执行。
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
OK
,看完这两个函数,一切都一幕了然了。
②
特殊菜单屏幕
电话簿列表可以理解为一个特殊的菜单屏幕。每个联系人理解为一个菜单项。
这时
RegisterHighlightHandler
的参数的功能是获得高亮项在
g_phb_name_index
中的位置,并将该位置保存下来以便以后使用。
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
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
的表了,从他的定义上很容易证实这一点。
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
![InBlock.gif](https://s1.51cto.com/images/editer/InBlock.gif)
但我们应该清楚定义这个表的文件只是编译后生成的文件。这个文件是怎么生成的呢。这就是我们上面说到的保存菜单字符串和函数字符串的作用了。
MTK
是使用
C
语言中的写文件的方式生成的。
OK
,至此一切都清楚明了了。
转载于:https://blog.51cto.com/ihome/411624