深入探索Symbian多視圖程序開發

Author:孫東風

Date:04/01/2008

http://blog.csdn.net/dongfengsun/article/details/2234513

        我們知道,在大多數GUI的Applications中,視圖之間的切換是極其頻繁的。那麼如何組織這些視圖以及視圖之間的通訊,就成爲大多數Applications所要面對的問題。

在Symbian中多視圖應用程序之間的視圖管理可以用下圖來表示:

其中AppUI管理AppView,而AppView又管理Container。

AppUI繼承自CAknViewAppUi,其管理AppView的代碼如下:

CAppView1* iView1 = new(ELeave) CAppView1;
CleanupStack::PushL( iView1 );
videoView->ConstructL();
AddViewL( iView1 );
CleanupStack::Pop();// view1

CAppView2* iView2 = new(ELeave) CAppView2;
CleanupStack::PushL( iView2 );
userView->ConstructL();
AddViewL( iView2);
CleanupStack::Pop();// view2

SetDefaultViewL(*iView1);

而其中每個View又繼承自

class CAppView1: public CAknView , public MCoeControlObserver

class CAppView2: public CAknView , public MCoeControlObserver

View之間要想實現自由的切換,就必須定義一個TUid作爲自身的唯一標識並實現CAknView的方法

// UID of view
const TUid KViewId = {1};     

/**
* From CAknView returns Uid of View
* @return TUid uid of the view
*/
TUid Id() const;

那麼從一個View跳轉到另一個View就需要下面的代碼

((CAknViewAppUi*)(iEikonEnv->AppUi()))->ActivateLocalViewL( TUid::Uid( 3 ));或

static_cast<CApplicationAppUi*>(iEikonEnv->AppUi())->ActivateLocalViewL( TUid::Uid( 3 ));

 

        上面的代碼講述了AppUI如何管理衆多的View以及View之間的切換,那麼下面講述每個View是如何管理它裏面衆多的Containers的。

        首先要明白View繼承自CAknView,它做爲Container(繼承自CCoeControl)的容器通過以下的代碼激活某個Container

iContainer = new (ELeave) CApplicationContainerSetting;       
iContainer->ConstructL( KFullScreen );
iContainer->SetMopParent(this);
iContainer->SetObserver(this);
iContainer->SetApplicationDbEngine(iDbEngine);
AppUi()->AddToStackL( *this, iContainer );

        那麼在DoActivateL()中通過以上代碼放置初始顯示的Container。

那麼View是如何管理衆多的Container的呢?

從以上代碼可以看出,負責Container管理的View都繼承自MCoeControlObserver,而iContainer->SetObserver(this)則把當前的Container註冊到MCoeControlObserver,從而實現了View對其內部Container的監聽。

View中繼承自MCoeControlObserver的接口void HandleControlEventL(CCoeControl* aControl,TCoeEvent aEventType)則負責每個Container所報告的事件的處理。

注意:如果View中並沒Container,那麼就沒必要繼承自MCoeControlObserver。

而Container繼承自CCoeControl(它是HandleControlEventL的一個參數),CCoeControl中提供下面的方法對View中的HandleControlEventL()報告事件。

  case EStdKeyDevice1: //右鍵
  {
   ReportEventL((MCoeControlObserver::TCoeEvent)ECmdDeleteVideoContainer);
   break;
  }

而View通過以下方法對上面代碼所報告的事件進行處理。

void CAppView1::HandleControlEventL(CCoeControl* aControl,TCoeEvent aEventType)
{
 switch(aEventType)
 {

case EMenuItemCmdBack:
  {
   ((CAVASAppUi*)(iEikonEnv->AppUi()))->HandleCommandL(EEikCmdExit);
   break;
  }
case ECmdDeleteVideoContainer:
  {
   break;
  }
default:
  break;
 }
}

從上面的分析可以看出:

AppView通過繼承自CAknView並通過ActivateLocalViewL()切換視圖。

而AppView通過繼承自MCoeControlObserver監聽衆多的Container,並在HandleControlEventL()裏對Container所報告的事件進行響應。


/////////////////////////////////////////////

APPUI類負責視圖的創建和切換,它繼承自CAknViewAppUi ,調用AppUi()->ActivateLocalViewL(uid)方法根據Tuid可以激活視圖。

所有的視圖必須在視圖服務器(CAknViewAppUi )類註冊纔可以使用。(註冊方法如:AddViewL(iMainView);)

在任意時刻只有一個視圖處於激活狀態。視圖必須在資源文件中定義,每一個視圖都可以有自己的菜單,所以定義視圖也定義各自的cba按鈕類型和菜單項。定義完後在二階構造中調用BaseConstructL( aResId );函數構造視圖。視圖類繼承自CAknView ,它有以下三個方法必須覆寫:

 TUid Id() const; //根據id判斷視圖,此id 在hrh 文件中定義

 void DoActivateL( const TVwsViewId& aPrevViewId,
                          TUid aCustomMessageId,
                          const TDesC8& aCustomMessage );   //負責激活視圖或容器

此函數中構造容器類對象,容器類繼承自CcoeControl.負責視圖的顯示

  void DoDeactivate();  //負責刪除視圖或容器

每個視圖類有自己的命令處理函數 void HandleCommandL( TInt aCommand ); 處理自己的菜單命令也可以調用AppUi類的菜單命令處理(AppUi()->HandleCommandL( aCommand );)

注意:使用AppUi()需要 #include <aknviewappui.h>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章