1、 对于MTK平台中高亮事件的简单分析,仅涉及MMI层的应用
牵涉函数:
void SetHiliteHandler( U16 itemid, FuncPtr hiliteFuncPtr );
void RegisterHighlightHandler( void (*f)(S32 item_index) );/*注册窗口的通用处理函数*/
void ExecuteCurrHiliteHandler( S32 hiliteid );/*当前高亮项的通用处理函数,它会找到菜单项对应的出来函数;一般窗口创建过程中被创建RegisterHighlightHandler(ExecuteCurrHiliteHandler)。*/
原理: 1. RegisterHighlightHandler(ExecuteCurrHiliteHandler)
A. ExecuteCurrHiliteHandler函数
通过当前高亮菜单的ID : hiliteItemID
执行与此ID关联的执行函数: maxHiliteInfo[hiliteItemID].entryFuncPtr
B. RegisterHighlightHandler函数
将上述函数指针(句柄)传给全局变量 MMI_list_highlight_handler 以便调用
通过RegisterHighligtHnder函数我们就可以知道,对于不同类型的菜单会有不同的全局变量,通过才这样的全局变量,系统其他部分的代码就可以直接使用该全局变量进行对高亮函数的调用。要注意的是对于每一个屏幕来说index都是从零开始的。
/*****************************************************************************
* FUNCTION
* RegisterHighlightHandler
* DESCRIPTION
* Registers the highlight handler to be called in menu screens
* PARAMETERS
* f [IN] Is a pointer to a highlight handler function
* This [IN] Is a zero based index of the highlighted menuitem.
* RETURNS
* void
*****************************************************************************/
void RegisterHighlightHandler(void (*f) (S32 item_index))
{
MMI_list_highlight_handler = f;
MMI_matrix_highlight_handler = f;
MMI_circular_3D_highlight_handler = f;
}
/*****************************************************************************
* FUNCTION
* ExecuteCurrHiliteHandler
* DESCRIPTION
* This function finds out the current highlight menu item's handler and executes it with clear KEY_RIGHT_ARROW key handler. Sometimes the sub menu items may be hidden and the sub menu item index will be different. This function also handle this case.
【此函数用于查找并执行当前高亮菜单项的处理程序同时清除右方向按键处理响应。有时,子菜单项可能会被隐藏和子菜单项索引有所不同,这个函数也处理这种情况。】
* PARAMETERS
* hiliteid [IN] ID of the item for which highlight handler needs to be executed.
* RETURNS
* void
*****************************************************************************/
void ExecuteCurrHiliteHandler(S32 hiliteid)
{
/* To avoid the arrow left key to entry unexpected function, while other APP need they shall register again as BY request. */
ClearKeyHandler(KEY_RIGHT_ARROW, KEY_EVENT_DOWN);
ExecuteCurrHiliteHandler_Ext(hiliteid);
}
通过该函数的注释就可以知道:当在一个菜单窗口中移动光标时,光标每动到一个菜单项时,系统(可能是Framwork模块)就会调用函数ExecuteCurrHiliteHandler_Ext找到对于菜单项的高亮处理函数并执行;因为ExecuteCurrHiliteHandler是去找该高亮函数,说明该函数已经在系统注册好了,那么该菜单项的高亮处理函数是在什么时候被注册的呢?就是在每个模块的初始化函数中,例如闹钟模块的AlmInit()初始化函数。
另外注意的一点时,ExecuteCurrHiliteHandler只用于静态菜单,所谓静态菜单,就是在枚举GLOBALMENUITEMSID中有明确ID定义的菜单项。
还有一点是,该函数在查找子菜单项时会自动忽略掉那些隐藏的菜单项;如果你在你的业务逻辑中使用了如下的语句:
RegisterHighlightHandler(ExecuteCurrHiliteHandler);
则,如果你要获得KEY_RIGHT_ARROW键的功能 就必须重新向framework模块注册。否则KEY_RIGHT_ARROW键是没有任何相应的,因为每当高亮一个菜单项时ExecuteCurrHiliteHandler就被执行一次,同时KEY_RIGHT_ARROW键的功能也就没clear一次。那么在那里重新加入KEY_RIGHT_ARROW键的功能,就在每个菜单项的高亮相应函数中,注意该菜单中每个菜单项高亮响应函数中都必须加入重新设置KEY_RIGHT_ARROW键的功能函数。
2. 关联高亮ID与执行函数
void SetHiliteHandler(U16 itemid, FuncPtr hiliteFuncPtr)
该函数将ID与函数关联:
maxHiliteInfo[itemid].entryFuncPtr = hiliteFuncPtr ;
itemid是传入的菜单ID, hiliteFuncPtr是传入的高亮执行函数
Note:
Please distinguish the function SetHiliteHandler from
RegisterHighlightHandler() which is provided by UI layer.
SetHiliteHandler() is for single menu item;
RegisterHighlightHandler() is global for all menu items.
【请区分函数SetHiliteHandler和RegisterHighlightHandler,它是由用户界面层提供的。SetHiliteHandler是用于单个菜单项;RegisterHighlightHandler()是用于全局所有菜单项。SetHintHandler这个函数用于注册的菜单项的处理程序。如果菜单项是预先定义,都会使用SetHintHandler来设置高亮菜单显示处理程序。】
2、SetHintHandler()
DESCRIPTION: This function is used for register the handler for the menu item. If the menu items are pre-definable, the applications use this function to set the highlight handlers.(注意处的注释,说明了要用此函数向framework注册高亮函数,则该菜单项ID必须已经提前被定义好了,也就是说必须是静态菜单项)。
[注意] void SetHiliteHandler(U16 itemid, FuncPtr hiliteFuncPtr) 与
void ExecuteCurrHiliteHandler(S32 hiliteid)函数的参数区别,前者是itemid而后者是hiliteid,后者使用高亮菜单索引hiliteid和currParentID取得真正的itemid。参加如下代码:
void ExecuteCurrHiliteHandler_Ext(S32 hiliteid)
{
FuncPtr currFuncPtr = NULL;
S32 hiliteItemID; /*定义菜单项ID变量 */
currHiliteID = (U16) hiliteid;
if (currParentID == 0)
{
return;
}
/* check if menuitem is hidden */
hiliteItemID = GetSeqItemId_Ext((U16) currParentID, (S16) hiliteid); //返回真正的菜单项ID:hiliteItemID.
currFuncPtr = mmi_frm_get_hilite_hdlr((U16)hiliteItemID);
//currFuncPtr = maxHiliteInfo[hiliteItemID].entryFuncPtr;
if (currFuncPtr)
{
(*currFuncPtr) ();
}
}
会先执行SetHintHandler注册的函数,然后执行RegisterHighlightHandler注册的函数。注意SetHintHandler注册的函数是在ConstructHintsList()中被调用执行的,并不是在菜单高亮时被执行的,菜单高亮时只执行了RegisterHighlightHandler注册的函数。ConstructHintList将APP传入的指针数组于全局数组hintData[idx]相关联;而SetHitHandler注册的函数完成对全局数组hintData[idx]的赋值。
3 、ConstructHintsList()
Constructs Hint List for a static menu screen
void ConstructHintsList(U16 parentID, U8 **hintArray)
{
U8 i, noOfChild;
U16 hiliteItemID[MAX_SUB_MENUS];
U8 idx = 0;
noOfChild = (U8) GetNumOfChild(parentID);
for (i = 0; i < noOfChild; i++)
{
hiliteItemID[i] = GetSeqItemId((U16) parentID, (S16) i);
/* check if menuitem is hidden */
if (!mmi_frm_test_menu_item_hide(hiliteItemID[i]))
/* the menuitem is not hidden */
{
if (maxHiliteInfo[hiliteItemID[i]].hintFuncPtr)
{
(*maxHiliteInfo[hiliteItemID[i]].hintFuncPtr) (idx);
//SetHintHandler注册的函数的函数在此被执行hintArray[idx] = hintData[idx];//该语句是该函数的核心,就是将全局变量hintData[idx]数组地址//赋给用户传过来的指针数组;至于hintData[idx]中是否有数据不管;hintData[idx]的数据会在调用SetHintHandler注册的函数时对其进行初始化;要记住SetHintHandler注册的函数在SetHiliteHandler注册的函数之前执行。
idx++;
}
else
{
hintArray[idx++] = NULL;
}
}
}
}
4. FuncPtr mmi_frm_get_hilite_hdlr(U16menu_id)
获取menu_id对应的菜单高亮函数,从两个函数指针数组里获取。先查找动态菜单的高亮函数指针数组,这个是在程序中动态添加的数组;如果找不到,再到静态数组里查找,这个数组是在编译过程中生成的,通常我们在res_mainmenu.c等函数里增加的菜单会被资源生成工具编译成一个静态数组。
mmi_frm_int_hilite_hdlr_table[]动态数组。
mmi_frm_const_hilite_hdlr_table[] 静态数组。