程序源码研读
KeyEvent处理
OberserverView类中有多个控件,每一个空间都以ObserverView的视图窗口作为自己的窗口,通过HandleCommandL中判别是哪个控件实现对应控件菜单项的相应函数。各个控件菜单项的不同是通过其控件对应的RSSI资源文件来设定。也就是由控件iTabIndex来决定菜单项---就是在ShowTab函数中实现对不同控件的MenuBar的构建,同时刷新导航项、导航修饰符等。所以ObserverView视图中控件的iTabIndex的值非常重要。
应该而言,加入控件栈中的控件应该按照顺序扫描OfferKeyEventL函数,那如何让ObserverView页面实现捕获左右键切换到其他控件上去呢?
在AppUi中重写了HandleKeyEventL函数,通过此函数的再进行KeyEvent的派送。也就是这样的过程,控件栈中都没有控件消耗到此KeyEvent就交给了AppUi函数的HandleKeyEventL函数,此函数经过上面说的iTableIndex来实现ObserverView中的控件的切换(兜了个圈回来)。
HandleKeyEventL in SDK:
This function is called by HandleWsEventL() if a key event occurred but none of the controls in the app UI's control stack consumed it.
Key events are sent to the application by the window server. A key press generates three separate key events in the order EEventKeyDown, EEventKey, and EEventKeyUp. Controls and app UIs are usually only interested in EEventKey events.
This default implementation simply returns EKeyWasNotConsumed. It may need to be overridden if the derived app UI needs to handle certain key events itself. For example, in some applications, arrow keys may be used to navigate between views. In this case, the app UI should override this function to consume the arrow keys.
论坛:
AppUi()->AddToStackL(...) This will add the container to the stack, such that the container will receive event notification when key press etc. The last one into the stack will be the first one to be notified. So the AppUi will the last one to receive the event.
HandleKeyEventL处理按键和所有来自OfferKeyEventL返回的OfferKeyEventL没有定义的按键事件。
论坛上一个例子说明
我在一个CAPPUI类中加入了三个view,而每个view中都包含一个Ccoecontrol类,我想问的是:应用程序默认的是显示第一个view,我现在通过APPUI类中的ActivedLocalView(ID)来切换到第二个view,我在第二个view的Ccoecontrol中设置了handlekeyevent,我想当我按下OK件时程序能从第二个view切换到第一个view和第三个view,当我不知道怎么做,请高手指点,急!先谢谢了
论坛答案:
TKeyResponse CYourContainer::OfferKeyEventL( const TKeyEvent& aKeyEvent, TEventCode aType )
{
if( aType == EEventKey )
{
switch( aKeyEvent.iCode )
{
case EKeyOk:
{
CAknViewAppUi *ui = static_cast<CAknViewAppUi*>( CEikonEnv::Static()->AppUi() );
ui->ActivateLocalViewL( viewId, messageId, customMessage );
break;
}
default:
return EKeyWasNotConsumed;
}
}
return EKeyWasNotConsumed;
}
此种方法当然没问题,如果对于一个视图中的多个控件的话还是得用上面的做法(可以构建不同的Menu、状态窗口等)。
还有一个函数是重点提到的HandleWsEventL函数
HandleWsEventL in SDK
Handles events sent to the application by the window server.
This function is called whenever the window server sends key or pointer events or some other special events to the application. It calls one of a number of functions, according to the type of event.
For key events, it calls CCoeControl::OfferKeyEventL() for each control on the control stack, beginning with the control at the top (position 0) until a control consumes it. If no control on the stack consumes the key event, the app UI's HandleKeyEventL() is called. Note that CCoeControl::OfferKeyEventL() is not called for controls whose ECoeStackFlagRefusesAllKeys flag is set.
For pointer events, CCoeControl::ProcessPointerEventL() is called on the control specified in aDestination.
For pointer buffer ready events, ProcessPointerBufferReadyL() is called on the control specified in aDestination.
For other events, for instance focus change events, this function calls one of the following CCoeAppUi private virtual functions:
HandleForegroundEventL()
HandleSwitchOnEventL()
HandleSystemEventL()
HandleScreenDeviceChangedL()
HandleApplicationSpecificEventL().
All these functions have empty implementations in this class, and are implemented by derived classes, if required.
所以Event的消息派发路径大致为:
KeyEvent => AppUi::HandleWsEvent() => CEikMenuBar::OfferKeyEventL() => AppUi::ProcessCommandL() => AppUi::HandleCommandL() [or CAknView::HandleCommandL()]
KeyEvent => AppUi::HandleWsEvent() => CcoeControl::OfferKeyEventL(控件栈中的所有) => AppUi::HandleKeyEvent => ViewSwitch
OfferKeyToAppL又是干什么用的呢?
SDK说:Called if a key which is not used by the menu is pressed while the observer's menu is displaying.
中文意思是此函数在[(当观察者的菜单显示状态下)菜单没用的键被按下的时候]调用,也就是在菜单一级二级三级子菜单在弹出状态下按到其他键(比如按数字键)的处理方法,重写这个函数就能用数字键来实现菜单的快捷操作(当然是在菜单弹出情况下才有用)。如果要实现比如按下数字键实现快捷菜单操作的话,请看前面(当然这里说一下也无妨,如果控件用OffkeyEventL直接检测到KeyEvent,则可以对控件实现此键的快捷操作,如果View想使用KeyEvent的话,让控件别处理此KeyEvent直接交给AppUi->HandleWsEvent => AppUi->HandleKeyEvent => 再交给View类处理)。

浙公网安备 33010602011771号