一.HandleListBoxEventL(CEikListBox* aListBox, TListBoxEvent aListBoxEvent)
其實就是使用了Observer模式,其中ListBox的父控件是Observer。
假設iListBox的父控件爲CMyContainer
1. CMyContainer要實現MEikListBoxObserver接口
2. iListBox構造完成後要調用
iListBox->SetListBoxObserver(this);
3. 當在iListBox中選中某個Item時,iListBox就會通過MEikListBoxObserver接口通知父控件。可以這樣 處理這個通知:
void CMyContainer::HandleListBoxEventL(CEikListBox* /*aListBox*/,TListBoxEvent aEventType )
{
if (( aEventType == MEikListBoxObserver::EEventEnterKeyPressed)||
( aEventType== MEikListBoxObserver::EEventItemClicked ))
{
// 如果當前選中的是第二項
if(iListBox->CurrentItemIndex()==2)
{
// 則調用其它函數,或者
// 1. 切換到其它視圖(如果你的視圖繼承自CAknView),或者
AppUi()->ActivateLocalViewL(TUid::Uid(ETheViewID));
// 2. 切換到其它視圖(如果你的視圖繼承自CCoeControl)
// AppUi()->HandleCommandL(ECmdSwithToOtherView)
// 自己要AppUi類的HandleCommandL()中處理ECmdSwithToOtherView命令完成切換
}
}
}
二.virtual TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
這個函數專門用於處理鍵盤事件,如果對程序的交互和運行需要通過鍵盤控制,那麼視圖類就應該去實現這個方法。如果類實現這個方法,特別需要注意的是,若對象沒有對鍵盤事件作出響應那麼應該返回EKeyWasNotConsumed ,反之,若對象對該鍵盤事件做出了響應那麼就要返回EKeyWasConsumed。當鍵盤事件發生時,控制框架調用每一個在控件棧中對象的OfferKeyEventL()函數,直到他們中其中的一個可以處理這個鍵盤事件並返回EKeyWasConsumed。
參數:
const TKeyEvent& aKeyEvent :鍵盤事件。TKeyEvent 類描述了鍵盤事件的細節,他包括四個屬性,分別是iCode, iModifiers, iRepeats, iScanCode 。當處理一個TKeyEvent的時候,TStdScanCode型的iScanCode通常被TKeyCode型的iCode取代。
TEventCode aType :鍵盤事件類型,包括:EEventKey, EEventKeyUp or EEventKeyDown
返回值指明對象是否處理了這個鍵盤事件。
任意一個鍵盤的按鍵事件都將導致三個獨立的事件:EEventKeyDown, EEventKey和EEventKeyUp,事實上他們觸發的順序也是這個樣子的。爲可以獲得可以被OfferKeyEventL()函數處理的鍵盤事件,應用程序必須調用CCoeAppUi::AddToStackL()方法,把控件壓入到棧中。這只是對控件起作用,而不是組成控件的控件組件。複合控件如果有需要的話也可以把鍵盤事件傳遞給他們的組件控件,但是組件控件本身並不可以在控制棧上。
如果一個類覆蓋了 CCoeControl::OfferKeyEventL() 方法那麼他同時也要覆蓋InputCapabilities() 虛函數,返回一個TCoeInputCapabilities 對象,這個對象的屬性符合OfferKeyEventL()函數的行爲。通常沒有必要在內部調用InputCapabilities() 方法,而這個方法也一般被UI控制框架調用。
三、 virtual void HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
HandleKeyEventL一般用在AppUi中,Container中一般是使用OfferKeyEventL。HandleKeyEventL處理按鍵和所有來自OfferKeyEventL返回的OfferKeyEventL沒有定義的按鍵事件。
對於symbian操作系統上按鍵事件的捕獲,既可以通過UI中的HandleKeyEventL也可以通過view中的OfferKeyEventL,這兩個函數都是通過重載基類中的相應函數來實現的。使用這兩個函數的主要區別在於使用OfferKeyEventL前需把對應的view壓入控件棧(AddToStackL),否則捕獲不到該控件對應的按鍵輸入,而HandleKeyEventL 則不需要壓入控件棧,可以處理全局按鍵事件。這兩個函數根據實際情況分別使用,當多個view時最好用OfferKeyEventL,這樣便於控制,可在各個view中分別對按鍵輸入做不同的相應。另外,如果同時定義了這兩個函數,關於他們的執行順序,有按鍵事件時其先被傳遞到控件棧中的OfferKeyEventL,如果OfferKeyEventL返回EKeyWasConsumed(被消耗),則不再傳到HandleKeyEventL中,否則傳遞到HandleKeyEventL在做處理。
當用戶按下一個鍵後,keyboard hardware就會生成一箇中斷,由keyboard driver捕捉,之後分解出這次按鍵事件的key code,然後driver將它發送到系統端的一個線程——被稱爲window server,而window server又會把它發向在window group中擁有焦點的那個應用程序中,這個步驟是使用一個control environment(CONE)來完成的,它是window server和user interface library之間的一個API函數。
從api函數中可以看出這個處理過程當windows server發送一個按鍵的事件便調用AppUI中的HandleWsEventL(),HandleWsEventL()方法首先調用CCoeControl::OfferKeyEventL()如果OfferKeyEvent()返回EKeyWasNotConsumed則繼續調用AppUI中的HandleKeyEventL()。如果OffKeyEventL()處理了事件則返回EKeyWasConsumed。
如果想直接調用AppUI中的HandleKeyEventL()可以通過set ECoeStackFlagRefusesAllKeys 來省去調用OfferKeyEventL()。
每次按鍵都會產生3個事件類型1 EEventKeyDown,2 EEventKeyUp,3 EEventKeyDown;可以從OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)中的aType中得到事件類型。aKeyEvent是一個struct可以得到按鍵的更多屬性,eg:iCode指名按了哪個鍵(鍵名在e32keys.h中)iRepeats可以判斷是重複按鍵還是長按鍵。如果想改變系統的按鍵重複率可以通過RWsSession 的SetKeyboardRepeatRate方法來設置。
S60手機默認情況下是不能接受連續按鍵的且只有先按下的鍵可以被接受(也就是按鍵阻塞,電源鍵和編輯鍵默認爲非按鍵阻塞)。可以通過s60提供的CAKnAppUI中的SetKeyBlockMode()方法來取消按鍵阻塞。
四、void HandleControlEventL (CCoeControl* aControl,TCoeEvent aEventType)
純虛方法HandleControlEventL()來接收和處理按鈕事件。
void CBasic_M1000AppView::HandleControlEventL(CCoeControl* aControl,TCoeEvent aEventType)
{ //First check the control the event is coming from
if ( aControl == iSendButton)
{
_LIT(KTEXT,"Click");
switch (aEventType)
{
case EEventPointer:
iLabel->SetTextL(KTEXT);
iLabel->DrawDeferred();
break;
default:
break;
}
}
}