MTK 高亮處理機制


1介紹:
本文旨在介紹MTK平臺高亮機制的處理邏輯,相信能對剛入手MTK平臺的同學有一定幫助,也能給平時爲了項目進度和其他原因,對 MTK的這些基本常識不求甚解,只能依葫蘆畫瓢的添加菜單和處理函數的同學一個警醒和幫助,能主動去深入瞭解問題和提高自己。
本人從事MTK的時間也不長,上面的話有些託大,對新手還是說得過去的。文檔中有些地方不正確和清楚的,歡迎評論和討論。
2相關函數和變量列表:
voidRegisterHighlightHandler(void(*f)(S32item_index))
註冊窗口的通用高亮處理函數。
MMI_list_highlight_handler
通用高亮處理函數的全局變量指針。
voidExecuteCurrHiliteHandler(S32hiliteid)
當前高亮菜單項的通用處理函數,它會找到菜單項對應的處理函數。一般在窗口創建過程中被創建 RegisterHighlightHandler(ExecuteCurrHiliteHandler)。
FuncPtrmmi_frm_get_hilite_hdlr(U16menu_id)
獲取menu_id對應的菜單高亮函數,從兩個函數指針數組裏獲取。先查找動態菜單的高亮函數指針數組,這個是在程序中動態添加的數組;如果找不到,再到靜態數組裏查找,這個數組是在編譯過程中生成的,通常我們在res_mainmenu.c等函數裏增加的菜單會被資源生成工具編譯成一個靜態數組。
mmi_frm_int_hilite_hdlr_table[]動態數組。
mmi_frm_const_hilite_hdlr_table[] 靜態數組。
currParentID
當前父窗口全局變量
voidSetHiliteHandler(U16itemid,FuncPtrhiliteFuncPtr)
設置動態高亮數組的MENUID及它相對應的處理函數,一般用在自定義的菜單項。比如在圖片瀏覽、JAVA應用、WAP記錄等不可預期菜單項數目的環境,我們不可能做靜態的MENUID和處理函數,就需要用到動態的實現方式。
hintData[][]
[待確認]:這是一個動態菜單的數據緩衝,和MENUID一一對應。通俗一點說,就是菜單的顯示字符串。網上有文章對此以及 ConstructHintsList()理解應該有誤,主要是因爲代碼裏該函數註釋說是處理靜態的,應該是註釋錯了。引用一段描述:
3、ConstructHintsList()
ConstructsHintListforastaticmenuscreen
voidConstructHintsList(U16parentID,U8**hintArray)
{。。。。。。
(*maxHiliteInfo[hiliteItemID[i]].hintFuncPtr) (idx);//SetHintHandler註冊的函數的函數在此被執行
hintArray[idx]=hintData[idx]; //該語句是該函數的核心,就是將全局變量hintData[idx]數組地址
//賦給用戶傳過來的指針數組;至於hintData[idx]中是否有數據不
//管;hintData[idx]的數據會在調用SetHintHandler註冊的函數時對其
//進行初始化;要記住 SetHintHandler註冊的函數在SetHiliteHandler註冊的
//函數之前執行。
我認爲ConstructHintsList()是創建動態菜單的,時間關係,待分析。
3高亮機制說明:
3.1使用流程
每個窗口進入後基本都有類似下面的一段程序:
。。。。。。
EntryNewScreen(EM_DEBUG_INFO_SCR,NULL,EntryEMDebugInfo,NULL);
guiBuffer=GetCurrGuiBuffer(EM_DEBUG_INFO_SCR);
nItems=GetNumOfChild(EM_DEBUG_INFO_MENUID);
GetSequenceStringIds(EM_DEBUG_INFO_MENUID,ItemList);
SetParentHandler(EM_DEBUG_INFO_MENUID);
RegisterHighlightHandler(ExecuteCurrHiliteHandler);
ShowCategory52Screen(。。。)
SetRightSoftkeyFunction(GoBackHistory,KEY_EVENT_UP);
。。。。。。
3.2分析
這是窗口建立過程的一個通用處理結構,這裏簡單說明一下,每個函數的具體實現和功能請閱讀代碼。
EntryNewScreen 初始化建立一個窗口需要的變量和過程,並退出上一個窗口,清除按鍵處理函數等;
SetParentHandler很重要,設置當前父窗口全局變量的MENUID,用來定位到當前是在哪一個窗口,後面依據他來在菜單樹中查找到高亮的菜單項的MENUID,找到菜單項的MENUID後,通過mmi_frm_get_hilite_hdlr(U16menu_id) 可以找到菜單項對應的高亮函數;RegisterHighlightHandler把ExecuteCurrHiliteHandler註冊成一個通用的高亮處理函數,我們只要告訴ExecuteCurrHiliteHandler當前高亮的菜單項的MENUID,它就能找到執行函數並開始執行了。到這裏就應該已經基本明白了高亮機制了,弄明白了其實也很簡單的^_^;
ShowCategory52Screen()只是一個窗口界面繪製函數,和事件處理邏輯沒有關係。
SetRightSoftkeyFunction(GoBackHistory,KEY_EVENT_UP) 等函數設置這個窗口要響應哪些按鍵事件,並設置好相應的處理函數。
3.3高亮函數觸發過程
RegisterHighlightHandler把ExecuteCurrHiliteHandler註冊成一個通用的高亮處理函數,實際上是給 MMI_list_highlight_handler函數指針賦值。觸發則需要調用MMI_list_highlight_handler。
由於MTK平臺支持各種菜單形式,比如純文本的菜單、帶CHECKBOX的、帶RADIO的、帶一個圖片的、帶兩個圖片的、兩行的。我們現在只對一種標準菜單進行分析,其他形式的分析方法相同。
standard_list_highlight_handler(S32item_index)裏會執行註冊的高亮處理函數 MMI_list_highlight_handler,而standard_list_highlight_handler本身又是一個註冊函數,在 wgui_fixed_list_create_text_menu()裏會被註冊到 MMI_fixed_list_menu.item_highlighted,MMI_fixed_list_menu是菜單組件的數據結構,包含有菜單組件從顯示到功能處理函數的所有數據,具體每個組件怎麼被顯示,怎麼響應功能按鍵就不在這裏討論了,後續我可能會寫出文檔,有興趣的同學自己看代碼,效果會更好。
這裏簡單說一下,MMI_fixed_list_menu.item_highlighted在這個組件裏,會被 gui_fixed_list_menu_switch_highlighted_item()函數來執行,而 gui_fixed_list_menu_switch_highlighted_item()則在上下按鍵執行的時候被執行,比響應上按鍵的函數是 voidfixed_list_goto_previous_item(void),它調用 voidgui_fixed_list_menu_goto_previous_item(fixed_list_menu*m),而 voidgui_fixed_list_menu_goto_previous_item(fixed_list_menu*m)則調用 gui_fixed_list_menu_switch_highlighted_item(),整個觸發過程就完成了。
關於上下按鍵的註冊,則在wgui_fixed_list_create_text_menu()裏有: if(flag&WGUI_LIST_MENU_DISABLE_VOL_KEY)
register_fixed_list_keys_ex();
else
register_fixed_list_keys();
來註冊按鍵事件處理函數,其實現過程很簡單:
voidregister_fixed_list_keys(void)
{
SetKeyHandler(fixed_list_goto_previous_item,KEY_UP_ARROW,KEY_EVENT_DOWN);
SetKeyHandler(fixed_list_goto_next_item,KEY_DOWN_ARROW,KEY_EVENT_DOWN);
SetKeyHandler(fixed_list_goto_previous_item,KEY_VOL_UP,KEY_EVENT_DOWN);
SetKeyHandler(fixed_list_goto_next_item,KEY_VOL_DOWN,KEY_EVENT_DOWN);
}
關於如何實現按鍵事件的響應、按鍵的處理邏輯,又是一個專題了。大致包括鍵盤中斷、去抖、鍵盤映射、檢測、進程通信、應用部分按鍵處理機制等,有機會再寫出文檔。
4相關知識點說明:
4.1初始化相關
 高亮的一些全局變量會在InitEvents()裏進行初始化,在event.c文件裏。這個函數在開機過程中的一個調用棧關係如下:
InitEvents();
InitEventHandlersBeforePowerOn();
voidMMI_task(oslEntryType*entry_param)
 InitEvents();還會在InitFramework()中被調用,而InitFramework()會由於開機的狀態不同,如USB開機、鬧鐘開機等,調用流程也不盡相同。具體的可參見我的另一篇應用開機流程的文檔。
 4.2菜單結構及查找
4.2.1菜單數數組示意
constCUSTOM_MENUmtk_nCustMenus[]={
{1,0,18,0,16,2,10933,11062,(U16*)nOrderMenuItem_0},
{2,0,3,1,0,1,26218,26085,(U16*)nOrderMenuItem_1},
{3,2,0,1,0,1,555,0,(U16*)0},
{4,2,0,1,0,1,552,0,(U16*)0},
{5,2,0,1,0,1,26173,0,(U16*)0},
{0,0,0,0,0,0,0,0,(U16*)0},
{0,0,0,0,0,0,0,0,(U16*)0},
{0,0,0,0,0,0,0,0,(U16*)0},
{0,0,0,0,0,0,0,0,(U16*)0},
{0,0,0,0,0,0,0,0,(U16*)0},
{0,0,0,0,0,0,0,0,(U16*)0},
。。。。。。。。
}
 CUSTOM_MENUnCustMenus[MAX_MENU_ITEMS];
4.2.2通過父窗口MENUID及高亮INDEX找到高亮窗口 MENUID
U16GetSeqItemId_Ext(U16parent_item_id,U16index)
{
/*----------------------------------------------------------------*/
/*LocalVariables*/
/*----------------------------------------------------------------*/
U8i=0,idx=0;
U16item_id=0;
U8child_count=(U8)nCustMenus[parent_item_id-1].nNumofMenuItem;
 /*----------------------------------------------------------------*/
/*CodeBody*/
/*----------------------------------------------------------------*/
#ifdefDEVAPP_RESOURCE
if(parent_item_id>=MENU_ID_DEVAPP_START)
{
returnDevAppGetSeqItemId_Ext(parent_item_id,index);
}
#endif
 for(i=0;i<child_count;i++)
{
item_id=nCustMenus[parent_item_id-1].nOrderMenuItemId[i];
if(!mmi_frm_test_menu_item_hide(item_id))/*theitemisnothidden*/
{
if(idx==index)
{
break;
}
else
{
idx++;
}
}
}
MMI_TRACE(MMI_FW_TRC_G2_GUI,MMI_RESGEN_ALL_MENU_HIDE,parent_item_id);
returnitem_id;
}
 4.2.3通過高亮窗口MENUID找到對應的高亮函數
FuncPtrmmi_frm_get_hilite_hdlr(U16menu_id)
{
/*----------------------------------------------------------------*/
/*LocalVariables*/
/*----------------------------------------------------------------*/
U32index;
 /*----------------------------------------------------------------*/
/*CodeBody*/
/*----------------------------------------------------------------*/
 /*Firstlysearchthedynamictable*/
if(mmi_frm_binary_search((U32)menu_id,(mmi_frm_pair_data_struct*)mmi_frm_int_hilite_hdlr_table,
(U32)mmi_frm_int_hilite_hdlr_count,&index))
{
returnmmi_frm_int_hilite_hdlr_table[index].hilite_hdlr;
}
/*Andthensearchtheconstanttable.Theconstanttableisgenerantedbyresgen.*/
elseif(mmi_frm_binary_search((U32)menu_id,
(mmi_frm_pair_data_struct*)mmi_frm_const_hilite_hdlr_table,
(U32)ARRAY_COUNT(mmi_frm_const_hilite_hdlr_table),&index))
{
returnmmi_frm_const_hilite_hdlr_table[index].hilite_hdlr;
}
else
{
returnNULL;
}
}
本文來源於無聲無息 http://www.imeans.net/ , 原文地址:http://www.imeans.net/post/201004/44.html

 

發佈了81 篇原創文章 · 獲贊 6 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章