MTK 10A 消息机制

1
MTK 10A 帮助文档
一. 10A MMI 主要新特征
1. 新Event 机制
API:
#define MMI_FRM_SEND_EVENT(_evt, _proc, _user_data) \
mmi_frm_send_event((mmi_event_struct *)(_evt),
(mmi_proc_func)(_proc), (void *)(_user_data))
#define MMI_FRM_POST_EVENT(_evt, _proc, _user_data) \
mmi_frm_post_event((mmi_event_struct *)(_evt), (mmi_proc_func)(_proc),
(void *)(_user_data))
mmi_frm_send_event = 直接函数调用
mmi_frm_post_event 发消息稍后调用(据MTK 说是为了防止循环调用)
mmi_frm_invoke_post_event 可以处理队列里的消息,这个mtk 已经做好了在一
些必要的地方调用
Event 处理机制在MTK 10A mmi framework 代码中很重要, 在后续特征中会有体

2. Callback 管理机制
10A 中callback 其实还是用event 机制实现的
在mmi_cb_mgr_cfg.h 中可以看到如何注册一个event 的callback,也可以通过调
用mmi_ret mmi_frm_cb_reg_event(U16 evt_id, mmi_proc_func call_back, void
*user_data)来注册,一个event 可以注册多个callback,会依次调用,如果有需要
截断后面的处理,则不能返回MMI_RET_OK
MTK 新版本中已有的event 数量已经非常多,也可以自己添加,需要在以后熟
悉代码中慢慢熟悉已有的event的意义
此时的callback event 和上面1 中的event 有些区别的, 使用
mmi_frm_cb_emit_post_event来发送,在mmi_frm_invoke_post_event 中会判断然
后和1 中的event区别处理
3. Screen Group机制
见图形化文档
跟原来的screen机制并不能完全兼容, 如需移植代码需要注意, 独立的功能最好
添加一个group id,否则可以使用已有的group id
4. CUI
Common UI
5. 添加XML 方式描述Mmi Resource
2
可见代码:phonebook.res MTK会解析*.res 文件生成mmi_rp_{APP_NAME}_def.h
兼容以前的添加资源方式
6. 新按键处理
static void process_key_event_routing(mmi_frm_key_evt_struct *key_evt_p)
参考PRST_FRM_NewInputHandler.pdf
7. 新屏幕刷新机制
MTK 为了避免屏幕闪的问题,改在特定的时间刷新屏幕,如果需要马上刷新需
要设置
mmi_frm_set_curr_scr_blt_mode(MMI_FRM_SCR_BLT_IMMEDIATE); (有些
需要频繁刷新屏幕的应用需要)
8. 怎样添加一个新应用
见文档PRST_FRM_HOW_TO_WRITE_APP_10A.pdf
二. MTK History 机制深入分析
1.10A 的屏幕架构
10A 中的屏幕管理,不再像以前那样简单的管理一个数组,出栈入栈,而是维
护一个树,如下图:
Group
Group Group
tail
Group
head
Screeen
head\tail
Screeen
head
Group
tail
Screeen
head\tail
next
Group
tail
Screeen
Screeen
head
Screeen
tail
next
next
next
head
next
这个是总的屏幕集合的一部分,基本上是主菜单一个应用有自己的一个总的
group(也不排除特殊情况, 比如设置菜单),在这个group 下有许多子group(就
好像一个菜单中有很多子菜单) ,子group 中又会有用来显示的screen 以及其它
的group,依次类推,不过最底部(叶子节点)一定会是个screen ,用作显示。
以前的EntryNewScreen 是一个入栈的过程,现在的进入新屏,就需要创建新的
group 连接到已有的父group 的子group 中的尾部, 然后再以新建的group 为父
3
节点创建screen 用作显示,当然这其中也会处理前一个group ,也就是保存历
史的操作。
进屏之后返屏,可以想象返屏就会移除父group 的子group 中的tail 的group
并释放在其申请的内存, 接着激活其前一个节点(可能是group,可能是screen ),
tail 的group 就会是激活的节点。
具体的进出屏幕会在下文详细介绍。
2.进屏流程
由于10A 中也会用到原来的EntryNewScreen 进屏,也会有直接创建screen 进屏
等多种方式进屏, 我在这就只列出一个比较具有象征性的进屏方式。因为现在进
屏比较复杂我就大体例举其调用的主要的几个函数以及他的作用。
1) mmi_frm_group_create (MMI_ID parent_id, MMI_ID group_id,
mmi_proc_func proc, void *user_data) ,看到这个我想都会知道是创建一
个group ,它的父ID,ID 等系列属性也会根据参数来赋值, 值得一提的是
group 是动态申请内存的方式创建,还有在创建的时候,不会把新节点加到
父节点的子节点的尾部。而是先加到shell.scenario_dangle 这个节点下。
2) 创建好group 后,就会进入group , mmi_frm_group_enter (MMI_ID
group_id, mmi_group_enter_flag flag) 进入新的group ,注意在这里他又
会调用add_node 这个函数把group 加入到他的父级group 下,加到尾部,
同时会用remove_node() 这个函数来remove 掉shell.scenario_dangle 下
对应节点,(有点没懂为什么在新建的时候会add 到shell.scenario_dangle
这个节点后,又在紧跟着的entry group 中remove 掉这个节点,是为了防
止在第一次creategroup 之后没有调用entry gourp 么?期待高手解答) 这
步就是加链表的操作了。
3)接着就是用这个函数group_active(group_node_struct *node,
mmi_scenario_evt_struct* evt) ,这个函数会对该node 的父级group 做判
断:
只有在父级group 为shell.scenario_root , 才会调用
mmi_frm_entry_new_screen() ,这个又是我们熟知的进屏函数了,我不再这
一一介绍, 只说一些不同的操作,他不单利用historyData 这个结构体来保
4
存上一个屏幕的信息,也会记录新进的屏幕的信息,还有在记录上一个屏幕
信息的时候不再用mmi_frm_add_history 这个函数来申请内存保存上一个屏
幕控件的历史信息。
接着会inactive 其前一个节点。调用group_inactive 或者scrn_inactive 。
4) group_inactive 会调用scrn_inactive 来inactive 其节点下的(包括本身
节点)节点。那么得分析下scrn_inactive ,这里会调用该node 所记录的退
出函数, 根据进入函数来调用scrn_add_history(scrn_node_struct *node)
来保存历史, 这个改良了53 的保存控件历史的函数, 它统一了各个所有控件
的保存方式,不再是像以前那样对特殊模板独立保存方式。这里同样会申请
内存来保存控件信息, 不过它会根据控件的size 大小来申请内存, 而且都是
保存在node 这个结构体中,同样也可以在退出函数中作保存历史的操作。
5) 以上几步是把上个屏幕的信息保存下来了, 现在要做的是对新的group 的操
作了。现在要做的就是对新group 的操作。这个就要关注下
post_scenario_evt(MMI_ID group_id, U32 scrn_id,
post_scenario_act_enum act, mmi_scenario_evt_struct *evt, U32 type)
这个函数会把参数中的写到post_queue 这个结构体队列中,然后调用
scenario_process_post_evt_ex(U32 type) 来读取队列执行相应写入的操
作,比如激活新group 就会调用group_post_active(group_node_struct
*node, mmi_scenario_evt_struct* evt) 这个函数用shell.active_group
来记录进入的新node。shell.active_scrn 为NULL。
6) 仅仅只有好像只是group 的操作,那么screen 的操作去哪了呢?现在就是
开始screen 的步骤了,和group 一样也会新建screen ,同样也是申请内存,
把screen 加到新的group 下, 调用scrn_active 激活screen , 用
shell.active_scrn 记录新的screen 。这里主要还是介绍下两种进屏幕的方
式mmi_frm_scrn_first_enter 和mmi_frm_scrn_enter ,这两者的区别就在
于前者可以应用显示函数中应用参数(一般都是节点结构体中记录的数据)
还有tab 页的进入调用mmi_frm_scrn_tab_enter ,和scrn 一样最终页调用
scrn_node_enter ,具体流程类似。( 可以看一下mmi_phb_entry_op_option)
具体流程入下图所示(这只是一个比较标准的进屏, 10A 中也有直接申请Sreen
进的,还有用原始的进屏方式等等)
5
Group
Active_group
Screen
Active_scrn New_group
Head\tail
shell.scenario_dan
gle
Head\tail
Group
Active_group
2个小弟了
Screen
Active_scrn
Head
New_group
Tail
Next
shell.scenario_dan
gle
没小弟了⋯ .
Group
Inactive_group
这些操作会写入队
列,靠读取队列执行
相应动作
Screen
Inactive_scrn
这里会申请内存来
记录控件历史
Next New_group
Head Tail
Group
Screen
New_group
Active_group
终于轮到我了。
Next
Head
Tail
Group
Screen Next
New_group
Active_group
我也有小弟了
Head Tail
Screen
Active_scrn
6
3.返回屏幕
1)mmi_frm_group_close_ex (MMI_ID group_id, U32 type) 中会调用
group_close ,而该函数会先关闭该节点的孩子节点,也就是screen 节点,
而scrn_close() 会scrn_inactive()screen 节点后, 在调用
execute_node_deinit(base_node_struct *node,
mmi_scenario_evt_struct* evt) 把 POST_EXECUTE_DEIN的IT操作写进队列
中, 接着调用scenario_process_post_evt_ex 读取队列中的操作执行
execute_node_post_deinit 来释放screen 申请的内存。这么一来原有的
screen 就不在了,对于group 来说也会做类似的操作,同样是先inactive ,
再exit ,最后deinit 都会把操作写进队列,这样一来就结束了显示着的界
面。
2)现在就是要看怎么实现返回的了,其实简单来说就是激活了被释放节点的前
一个节点, 如果该节点是group 会激活该group 下的screen ,如果是screen
就直接激活screen ,调用screen 节点所记录下的entry 函数,实现了返回
的效果。注意,在被释放节点的父节点为shell.scenario_root 时,在返回
时会调用GobackHistory ,来返回历史。这个是我们熟知的方法,也就不在
这一一介绍了。
具体流程如下图所示:
7
Group
Screen
Head
Group
Actvie_group
Tail
Screen
Active_scre
en
Head\tail
next
Group
Screen Group
Actvie_group
Screen
Inctive_screen
一些删屏响应函
数在这调用
shell.scenario_
dangle
Head Tail Head\tail
next
Group
Screen
Group
Actvie_group
Screen
先释放保存控件
申请的内存,再
释放Screen申请的
内存
shell.scenario_
dangle
小弟⋯
Head Tail
next
Group
Active_group
Screen
激活这个节点的操
作已写进队列
Group
Inctvie_group
shell.scenario_
dangle
你敢不走么?
Head\Tail Head\tail
Group
Active_group
Screen
Active_screen
根据本节点保留的控
件信息还原历史
Group
释放内存,这个过程会调用
该节点记录的进入函数,用
户可以按自己需求写该函数
shell.scenario_
dangle
。。。
Head\Tail
8
4.删除屏幕
其实删屏在返回屏幕中已经介绍了他的具体流程, 这里就简单介绍些常用的几个
删屏函数吧:
1)mmi_frm_group_close (MMI_ID group_id) :删除相应ID 的group ,删除group
会连带删除该group 下的所有子节点。
2)mmi_frm_scrn_close_active_id() 顾名思义会删除激活状态下的screen
3)mmi_frm_scrn_close_ex (MMI_ID parent_id, MMI_ID scrn_id,
scrn_close_type_enum flag) 删除指定ID 的screen 。
4)mmi_frm_scrn_multiple_close (MMI_ID parent_id, MMI_ID start_scrn_id,
U8 b_inc_start, U16 count, MMI_ID end_scrn_id, U8 b_inc_end) 这个类
似53 平台上的DeleteHistoryInt() ,用来删除多个屏幕。
注意:如果被删的节点的父节点,只有一个子节点(也就是被删的节点),那么
同样会删除该节点的父节点。
5.插入节点
1 ) mmi_frm_group_insert (MMI_ID parent_id, MMI_ID base_id,
mmi_frm_node_struct *new_node_info, mmi_scenario_node_flag flag)
2 ) mmi_frm_scrn_insert (MMI_ID parent_id, MMI_ID base_id,
mmi_frm_node_struct *new_node_info, mmi_scenario_node_flag flag)
两者都会根据传入的flag 参数确定加入的位置,加节点的流程与进屏加节点类
似,只是位置不同,不再分析流程。
6.一些函数介绍
1.mmi_frm_get_active_scrn_id(MMI_ID *group_id, MMI_ID *scrn_id) 获取激
活的group 和screen 的ID
2.mmi_frm_group_get_active_id(void)
3.mmi_frm_scrn_get_active_id (void )和以前类似,对tab 页也是获取主屏
ID
4.mmi_frm_scrn_tab_get_active_id(void) 这个函数是获取tab 页主屏的ID
5.mmi_frm_scrn_tab_page_get_active_id(void) 获取激活的page 页ID(也就
是子屏ID)
6.mmi_frm_scrn_get_active_gui_buf (void) 这个函数封装了所有screen 的历
史获取,包括tab 页。
7 . mmi_frm_scrn_set_leave_proc (MMI_ID parent_id, MMI_ID scrn_id,
mmi_proc_func proc) 设置删屏响应函数
7.总结
由上可知10A的屏幕管理要比以前的复杂的多, 上面所分析的也是一种常见的屏
幕架构,也会有比较特殊的, 会直接用以前的EntryNewScreen,也会有一个group
下游很多screen 子节点,可是万变不离其中,都是根据节点的增删,维护一个
树,来实现屏幕的切换。
还有些tab 页的进屏没有详细分析,不过也是类似节点的管理,不再一一介绍,
可以根据代码了解过程。主要是进一个主屏,这个主屏链接着树,管理其顺序,
然后主屏下有相应的page 页,激活着的page 页在这个主屏的尾部, 在返回时只
对主屏进行操作,不过在操作中会操作它的子节点。
9
注意:
在10A中也可以用EntryNewScreen,不过有几点限制:
1.如果前后都是EntryNewScreen,可以。
2.如果前面是节点,那么该节点的父节点必须为shell.scenario_root
3.如果后面是节点,那么该节点的父节点必须为shell.scenario_root
终上所述, 也就是说EntryNewScreen 进的screen 可以理解为
shell.scenario_root 这个节点的子节点。
以上就是我的收获了,希望有帮助,谢谢。
三.资源添加
1、文件结构
目录一: plutommi\MMI\FirstApp
目录二: plutommi\MMI\FirstApp\FirstAppInc (该结构未改变)
文件列表:
FirstAppDefs.h:用于存放本程序所需要的类型,结构,常量的定义
FirstAppProt.h:用于存放本程序中的所有函数声明, 但此文件只被本文件的源程
序所加载
FirstAppGprot.h:也是用于存放函数声明,但是此文件是用于别的程序加载,即
此文件中的函数声明的都是对外的接口
FirstAppResDef.h:用于存放本资源ID 的定义接口
目录三: plutommi\MMI\FirstApp\FirstAppSrc (该结构未改变)
FirstAppSrc.c 程序的主源文件
目录四: plutommi\MMI\FirstApp\FirstAppRes (新的目录)
FirstApp.res:资源文件定义,包含字串、图片、菜单、屏幕等的定义,该文件实
际为一个标准xml 文件
ref_list_FirstApp.txt :该模块多国语言字串定义(目前发现该文件并未生效,不
知道是否是设置问题)
2、将文件加入项目
修改下的三个文件:
1)mmi_app.lis:此文件用来申明MMI 所要编译的所有源文件,添加如下一行:
plutommi\MMI\FirstApp\FirstAppSrc\FirstAppSrc.c
2)mmi_app.inc:此文件用来指明MMI 所有头文件所在目录,同样添加:
plutommi\MMI\FirstApp\FirstAppInc
3)mmi_app.pth:此文件用来指明MMI 所有源文件所在目录,添加:
10
plutommi\MMI\FirstApp\FirstAppSrc
4)在plutommi\Customer\ResGenerator\MakeFile文件中添加如下一行:
-I "../../MMI/FirstApp/FirstAppInc"\
3、应用程序ID 定义
1)在基础ID 统一定义文件plutommi\MMI\Inc\mmi_res_range_def.h (原来为
MMIDataType.h)中找到如下定义块:
RESOURCE_BASE_ENUM_BEGIN()
/********************************************************************
******************
* Declare resource ID range below
*********************************************************************
*****************/
⋯⋯
/********************************************************************
******************
* Declare resource ID range above
*********************************************************************
*****************/
RESOURCE_BASE_ENUM_END()
在其中添加:
#ifdef __MMI_FIRSTAPP__
RESOURCE_BASE_RANGE(FIRSTAPP, 50),
#endif
2)找到如下定义块:
/* Beginning of resource table */
RESOURCE_BASE_TABLE_BEGIN()
⋯⋯
/* End of resource table */
RESOURCE_BASE_TABLE_END()
11
在块中间末尾位置添加:
/********************************************************************
********
* FirstApp
*********************************************************************
********/
#ifdef __MMI_FIRSTAPP__
#define FIRSTAPP_BASE ((U16) GET_RESOURCE_BASE(APP_FIRSTAPP))
#define FIRSTAPP_BASE_MAX ((U16)
GET_RESOURCE_MAX(APP_FIRSTAPP))
RESOURCE_BASE_TABLE_ITEM_PATH(APP_FIRSTAPP,
".\\MMI\\FirstApp\\FirstAppRes\\")// 这里较之前有所变化
#endif
4、字串、图片、屏幕资源的添加
先来说字串、图片、屏幕资源ID 的添加。10A 版本中对资源定义的改动比较大,
稍微对比一下新老版本,你会发现很多原来很大的文件变小了,而多出来了很
多.res后缀的文件,这就是新版本的资源定义文件。10A 版本仍部分保持了老版
本的定义方式, 不过笔者建议采用新版本的方式来定义资源, 而且与之前相比新
版本的资源定义要方便不少。读者可以随便找一个res文件,会看到如下定义格
式:
/* Needed header files of the compile option in XML files, if you need others need to
add here */
#include "mmi_features.h"
#include "custresdef.h"
/* Need this line to tell parser that XML start, must after all #include. */
<?xml version="1.0" encoding="UTF-8"?>
/* APP tag, include your app name defined in MMIDataType.h */
<APP id="APP_FIRSTAPP">/* 这里定义的id 必须和之前定义的APP 的ID 一致
*/
/* When you use any ID of other module, you need to add
that header file here, so that Resgen can find the ID */
<!--Include Area-->
<!-----------------------------------------------------String Resource
Area----------------------------------------------------->
/* String ID of you Application, we will get string from ref_list.txt for all
12
languages */
<STRING id="STR_ID_APP_FIRSTAPP_HELLO"/>/* 在这里添加自己
的字串ID */
/* 这里说下, 字串的内容定义和之前的版本一样放在
YourProjectPath\plutommi\Customer\CustResource\PLUTO_MMI\ref_list.txt 下,为
了更好的兼容, 最好将你自己定义的字串重新规整到
YourProjectPath\plutommi\MMI\FirstApp\FirstAppRes\ref_list_FirstApp.txt 下,具体
定义方式和ref_list.txt 类似,参考本博客文章《MTK 编程起步——建立新APP
和资源定义》*/
<!-----------------------------------------------------Image Resource
Area------------------------------------------------------>
/* Image Id and path of you Application , you can use compile option in Path, but
need out of "" */
<IMAGE
id="IMG_ID_APP_FIRSTAPP_HELLO">CUST_IMG_PATH"\\\\MainLCD\\\\FirstA
pp\\\\HELLO.BMP"</IMAGE>
/* 这里定义自己的图片ID 和路径,注意图片现在的CUST_IMG_PATH 路
径是在YourProjectPath\plutommi\Customer\Images\FTE320x480,请将图片文件夹
放在这里,然后打包整个MainLCD 文件夹为image.zip(改了mtk_resgenerator.cpp
的可以不用打包) */
<!------------------------------------------------------Menu Resource
Area------------------------------------------------------>
/* Only MENUITEM need compile option, MENUITEM_ID does not need */
/* 这里定义你的菜单ID ,具体定义方法稍后给出*/
<!------------------------------------------------------Other
Resource---------------------------------------------------------->
<SCREEN id="SCR_ID_APP_FIRSTAPP_HELLO"/>/* 这里定义你的屏幕
ID */
</APP>
这个res文件类似与xml 文件,不过你可以在其中使用一些C 的预处理命令和注
释。使用这种方式你不需要自己去定义res_app_firstapp.c,系统会在这个文件中
搜索ID 并自动生成名为mmi_rp_app_firstapp_def.h和mmi_rp_app_firstapp.c的文
件,并在后者中定义对应的populate函数。至于res文件中各标签和其属性定义,
请参看MTK 官方文档10A_MMI_Resource_Training.pdf 。
13
5、菜单添加
菜单由于有上下级关系,定义要相对复杂些,这里先介绍几个标签: MENU 、
MENUITEM 和MENUITEM_ID 。MENU 是用来定义菜单树的标签, MENUITEM
是用来定义单个菜单项的标签, MENUITEM_ID 是用来在MENU 树中安置菜单
项的标签。下面来讨论菜单的定义。
新版本中菜单的定义方式有很多种, 现介绍最常用的三种方式, 其它方式请读者
参看上面给出的MTK 官方文档。
方法一: MENU 中包含MENUITEM_ID 方式定义
这种方式采用如下格式:
<MENUITEM id="SUBMENU1" str="STR_SUBMENU1"/>
<MENUITEM id="SUBMENU2" str="STR_SUBMENU2"/>
<MENU id="MENU1" type="OPTION" str="STR_MENU1"
highlight="HighlightMenu1" hint="HintMenu1">
<MENUITEM_ID>SUBMENU1</MENUITEM_ID>
<MENUITEM_ID>SUBMENU2</MENUITEM_ID>
</MENU>
采用这种方式要在MENU 体外申明对应MENUITEM 的定义,可以放在引用
MENU 之前也可在其后,但MENU 中MENUITEM_ID 包含的内容必须是已定义
的MENUITEM 的ID,如果不存在系统将会将该菜单忽略。另外提一点,为了
和先前的版本兼容, MTK 提供了@OID:前缀,用来引用原先在c 文件中定义的
菜单ID ,使用方法是将其放在<MENUITEM_ID></MENUITEM_ID> 标签对之间
即可,例如: <MENUITEM_ID>@OID:SUBMENU3</MENUITEM_ID> 。不过引
用前请使用<INCLUDE file="XXXResDef.h"/> 引用你ID 所在文件,将其至于
<!--Include Area-->下。
方法二:直接将MENUITEM 定义在MENU 中,格式如下:
<MENU id="MENU1" type="OPTION" str="STR_MENU1"
highlight="HighlightMenu1" hint="HintMenu1">
<MENUITEM id="SUBMENU1"
str="STR_SUBMENU1">SUBMENU1</MENUITEM_ID>
<MENUITEM id="SUBMENU2"
str="STR_SUBMENU2">SUBMENU2</MENUITEM_ID>
</MENU>
这种方式不需要在MENU 体外定义对应MENUITEM ,只需要放在MENU 标签
内同时定义MENUITEM 信息即可。
14
方法三:嵌套MENU ,格式如下:
<MENU id="MENU1" type="OPTION" str="STR_MENU1"
highlight="HighlightMenu1" hint="HintMenu1">
<MENU id="SUBMENU1" type="OPTION" str="STR_SUBMENU1"
highlight="HighlightSubMenu1" hint="HintSubMenu1"></MENU>
<MENU id="SUBMENU2" type="OPTION" str="STR_SUBMENU2"
highlight="HighlightSubMenu2" hint="HintSubMenu2"></MENU>
</MENU>
采用这种方式使得菜单的定义一次完成, 也易于理解, 但是当属性较多层次较深
的时候可能显得较乱。这种方式是直观的MENU 树表现方式,显示了子菜单与
父级菜单的对应关系。有些读者可能对MENU 和MENUITEM 有些迷茫,笔者
认为,在大部分时候MENU 和MENUITEM 可以通用,你可以把他们看成一种
东西( MENU )。你可以将方法三第二行替换成方法一或方法二的形式。不过如
果有SUBMENU1 有子菜单的时候, 方法三可以直接嵌套在对应MENU 体之中,
而方法一或方法二则需在MENU 方法体外做如下定义:
<MENU id="SUBMENU1" type="OPTION" str="STR_SUBMENU1"
highlight="HighlightSubMenu1" hint="HintSubMenu1">
⋯⋯
</MENU>
以上三种方法可以根据需要混合使用。最后为了完整实现菜单功能, 别忘了添加
对应菜单的highlight 和hint 函数。说到highlight 和hint 函数,这里有必要提一
下,不是所有菜单都可以直接在res文件中添加highlight 和hint 选项来实现的,
如果你发现你的highlight 和hint 不起作用,请使用模拟器跟踪一下同类高亮函
数, 会发现其高亮处理在类似mmi_ret
mmi_phnset_gpio_menu_handler(cui_menu_event_struct *menu_evt, MMI_ID
parent_gid)和static void mmi_phnset_gpio_select_menu(mmi_menu_id id, MMI_ID
parent_id)的函数中使switch (menu_evt->highlighted_menu_id){case SUBMENU1:}
或switch (id){case SUBMENU1:} 进行多分支进行的。其中前一个函数的作用是
点选左键或点触该菜单项所执行的事件即原来高亮函数中的
SetLeftSoftkeyFunction,而后一个函数则是高亮该菜单项所执行的函数即原来的
高亮函数。而hint 函数存在于类似static mmi_ret
mmi_phnset_disp_setup_sub_menu_entry_handler(cui_menu_event_struct *param)
中,switch (param->parent_menu_id){case MENU1:}对父级菜单ID 进行判断并执
行相应初始化函数, hint 函数位于对应父级菜单的初始化函数中。注意这里一定
是父级菜单而不是本菜单, 因为hint 函数的加载都是在进入包含该菜单的父级菜
单中进行的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值