事件处理
本文概述了在应用程序“HandleEvent”函数中处理事件的某些指导原则。 最重要的是正确使用通常由于按键事件 (EVT_KEY) 由用户界面控件生成的 EVT_COMMAND 事件(好拗口,就是某些控件收到EVT_KEY后会生成EVT_COMMAND,再把EVT_COMMAND发给shell,APP又会再处理此事件)。
(汗,让我想起了uiOne中的龌龊的事件传递。。。。)
如《BREW™ API 参考资料》中所述,正确使用菜单、文本等控件是在应用程序事件处理程序内部层叠这些控件的事件。 根据它们的状态判断是否处理该事件并相应地返回 TRUE/FALSE。 在某些情况下,此事件处理包括将事件重新发送到该应用程序的事件处理程序。 这是通过 EVT_COMMAND 完成的。 该事件说明已经通过控件执行操作并提供有关该操作的信息。 例如, IMenuCtl 生成 EVT_COMMAND 说明已经选择某个项目。
下面例示了正确和不正确的事件处理方法。
正确的事件处理
静态布尔型 CMyApp_HandleEvent(CMyApp * pme, AEEEvent evt,
uint16 w, uint32 dw)
{
switch(evt){
case EVT_APP_START:
return(TRUE);
case EVT_APP_STOP:
return(TRUE);
case EVT_COMMAND:
switch(w){
case IDC_MENU_ITEM_1:
...
break;
case IDC_MENU_ITEM_2:
...
break;
case IDC_OK:
...
break;
case IDC_CANCEL:
...
break;
}
return(TRUE);
//或者将下面的code 移到switch(evt)外面,一进入//CMyApp_HandleEvent()即调用
default:
if(pme->m_pMenu && IMENUCTL_HandleEvent(pme->
m_pMenu, evt, w, dw))
return(TRUE);
if(pme->m_pText && ITEXTCTL_HandleEvent(pme->
m_pText, evt, w, dw))
return(TRUE);
if(pme->m_pSKMenu && IMENUCTL_HandleEvent(pme->
m_pSKMenu, evt, w,dw))
return(TRUE);
break;
//end
}
return(FALSE);
}
如果某事件不由某应用程序处理,则事件处理程序必须返回 FALSE。 也就是说,事件处理程序的默认返回值必须是 FALSE。 只有某事件由事件处理程序处理时,才必须返回 TRUE。
即处理流程是:EVT_KEY—> CMyApp_HandleEvent()—> IMENUCTL_HandleEvent() :生成EVT_COMMAND—> CMyApp_HandleEvent()—>处理EVT_COMMAND
不正确的事件处理
静态布尔型 CMyApp_HandleEvent(CMyApp * pme, AEEEvent evt,
uint16 w, uint32 dw)
{
switch(evt){
case EVT_APP_START:
return(TRUE);
case EVT_APP_STOP:
return(TRUE);
case EVT_KEY:
IMENUCTL_HandleEvent(pme->m_pMenu, evt, w, dw);
if(w == AVK_SELECT){
uint16 wID;
wID = IMENUCTL_GetSel(pme->m_pMenu);
switch(wID){
case IDC_MENU_ITEM_1:
...
break;
case IDC_MENU_ITEM_2:
...
break;
}
}
return(TRUE);
default:
return(IMENUCTL_HandleEvent(pme->m_pMenu,evt,w,dw));
}
return(FALSE);
}
上面代码存在的问题是它对菜单的行为进行控制。 它不响应有关事件,而是负责菜单处理。 如果 OEM 或运营商修改菜单控制行为,则它会出现问题。
更糟糕的是,在以后的 BREW™ 版本中,此功能可能不再正常工作,因为某些菜单事件处理将通过传递的事件来完成。 这种更改旨在减少堆栈的使用。 不过,它会导致该应用程序发生故障。
小结:菜单中所有的按键处理都放在了IMENUCTL_HandleEvent()中处理(典型按键事件是“向上”、“向下”、“向左”和“向右”按键,在此函数中都有处理,调用即可实现按上下方向键高亮相应的item),当它收到AVK_SELECT后,它并不直接处理, 而是将该事件转换为EVT_COMMAND 再发给当前的applet, 相当于执行了ISHELL_PostEvent(ISHELL, EVT_COMMAND, ID, dw), 这里的ID 就是增加菜单时给的itemID 值. 某些按键事件如果你希望自己处理,可以在调用IMENUCTL_HandleEvent() 之前将它们给过滤掉,也就是不交给该函数处理.
实际上这是一种事件代理机制: