Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3506988
  • 博文数量: 1450
  • 博客积分: 11163
  • 博客等级: 上将
  • 技术积分: 11101
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-25 14:40
文章分类

全部博文(1450)

文章存档

2017年(5)

2014年(2)

2013年(3)

2012年(35)

2011年(39)

2010年(88)

2009年(395)

2008年(382)

2007年(241)

2006年(246)

2005年(14)

分类: C/C++

2009-07-07 13:01:30

第一步, AppUi 类继承自 CAknViewAppUi,并继承 MAknTabObserver 接口
为什么要继承 MAknTabObserver 接口呢?因为我们在按左右键时,TABGROUP类会发生变化,继承该观察都接口之后,我们就可以利用这个变化来切换不同的视图了。

#include <>

如下所示:
class AppUi : public CAknViewAppUi, MAknTabObserver
{
......

public: /** * iNaviPane * Not Owned by CsifAppUi object. */ CAknNavigationControlContainer* iNaviPane; /** * iTabGroup * Not Owned by CsifAppUi object. */ CAknTabGroup* iTabGroup; /** * iDecoratedTabGroup * Owned by CsifAppUi object. */ CAknNavigationDecorator* iDecoratedTabGroup;

private: // Data /** * iAppView1, The application view 1 * Not owned by CMultiViewsAppUi object. */ CMultiViewsView1* iAppView1; /** * iAppView2, The application view 2 * Not owned by CMultiViewsAppUi object. */ CMultiViewsView2* iAppView2;
}

第二步, 在 AppUi::ConstructL() 函数中作如下操作
AppUi::ConstructL()
    BaseConstructL(EAknEnableSkin);

    iAppView1 = CMultiViewsView1::NewL();
    iAppView2 = CMultiViewsView2::NewL();

    // Transfer ownership to base class
    AddViewL( iAppView1 );
    AddViewL( iAppView2 );

    SetDefaultViewL( *iAppView1 );

第三步,如果要实现 TAB 跳转,则需要在 AppUi::ConstructL() 中填加入下代码:

AppUi::ConstructL()
    BaseConstructL(EAknEnableSkin);

    CEikStatusPane *sp = StatusPane();    

    // Fetch pointer to the default navi pane control
    iNaviPane = static_cast 
( sp->ControlL( TUid::Uid( EEikStatusPaneUidNavi ) ) );
    iDecoratedTabGroup = iNaviPane->ResourceDecorator();
    if ( iDecoratedTabGroup )
    {
iTabGroup = static_cast
 ( iDecoratedTabGroup->DecoratedControl() );
         
         //记着将这句加上, 因为它是将该类放入到TABGROUP类中做为观察者,如果不加的话,当TABGROUP 发生变化时,APPUI类就不会发现变化从而不能切换视图
 iTabGroup->SetObserver( this );
    }

    iAppView1 = CMultiViewsView1::NewL();
    iAppView2 = CMultiViewsView2::NewL();
    
    //CleanupStack::PushL( view1 );
    //view1->ConstructL();
    //AddViewL( view1 );      // transfer ownership to CAknViewAppUi
    //CleanupStack::Pop();    // view1


    // Transfer ownership to base class
    AddViewL( iAppView1 );
    AddViewL( iAppView2 );

    SetDefaultViewL( *iAppView1 );

第2.1步, 在APPUI.H中添加头文件
#include  
#include  
#include  

第2.2步, 将 eikcore.lib 库加入到工程中

第2.3步, 释放资源
AppUi::~AppUi()
        if (iAppView)
{
delete iAppView;
iAppView = NULL;
}
if(iListAppView)
{
delete iListAppView;
iListAppView = NULL;
}

delete iDecoratedTabGroup;

第三步, 在APPUI.CPP 中处理用户按键,如果是方向键,则切换视图。
TKeyResponse AppUi::HandleKeyEventL(
            const TKeyEvent& aKeyEvent, TEventCode aType)
{

     if(iTabGroup == NULL)
     {
         return EKeyWasNotConsumed;
     }

     //如果按下的是左方向键或右方向键
     if(aKeyEvent.iCode==EKeyLeftArrow || aKeyEvent.iCode== EKeyRightArrow)
     {
         return iTabGroup->OfferKeyEventL(aKeyEvent, aType);
     }
     else
     {
         return EKeyWasNotConsumed;
     }

第四步, 重载 TabChangedL 方法,这是一个回调函数
void AppUi::TabChangedL(TInt aIndex)
{
  ActivateLocalViewL(
TUid::Uid(iTabGroup->TabIdFromIndex(aIndex))
      );//激活视图
}

第五步, 视图类继承自 CAknView。 如下所示
class View: public CAknView
......

public: // Functions from base classes from CAknView

        /**
        * Id
        * @return Id Uid value
        */
        TUid Id() const;

        /**
        * HandleCommandL
        * From CAknView, takes care of command handling.
        * @param aCommand Command to be handled
        */
        void HandleCommandL( TInt aCommand );
        
        /**
        * HandleSizeChange
        * Called by HandleResourceChangeL() from CMultiViewsAppUi when layout 
        * is changed.
        * @param aType Type of resources that have changed
        */
        void HandleSizeChange( TInt aType );

        /**
        * DoActivateL
        * From CAknExView, activate an AknView.
        * @param aPrevViewId The id of the previous view
        * @param aCustomMessageId message identifier
        * @param aCustomMessage custom message provided when the view is changed
        */
        void DoActivateL( const TVwsViewId& aPrevViewId,
                          TUid aCustomMessageId,
                          const TDesC8& aCustomMessage );

        /**
        * DoDeactivate
        * From AknView, deactivate an AknView
        * Remove the container class instance from the App UI's stack and
        * deletes the instance
        */
        void DoDeactivate();

private: // Data

        /**
        * iContainer,container for this view
        * owned by CMultiViewsView1 object.
        */
        CMultiViewsContainer1* iContainer;

        /** View Identifier **/
        TUid iIdentifier;

这里需要注意:
第一, View类中没有 Draw ,SizeChanged 和 HandlePointerEventL 方法,这三个方法已经被移到 Container 类中。
第二, 二次构造函数 ConstructL 中从资源文件中创建视图。如下:
void View::ConstructL(const TRect& aRect)
{
BaseConstructL( R_LABELVIEWS_VIEW );
}

第5.1步,在资源文件中增加视图资源
//描述说明,该视图包括一个菜单和一个退出键
RESOURCE AVKON_VIEW r_labelviews_view
{
    menubar = r_labelview_menubar;
    cba = R_AVKON_SOFTKEYS_OPTIONS_EXIT;
}

//每个菜单条有一个标题,而该菜键条标题仅于由一个菜单标题组成,每个菜单标题又由一个菜单面板组成
RESOURCE MENU_BAR r_labelview_menubar
{
        titles =
        {
            MENU_TITLE
            {
                menu_pane = r_labelviews_menu;
            }
        };
}

//每个菜单面板由多个菜单项给成,第一项包括指令和显示文本组成
RESOURCE MENU_PANE r_labelview_menu
{
        items =
        {
            MENU_ITEM
            {
                command = EMultiViewsSwitchToView2;
                txt = STRING_r_mult_switch_to_view2;
            },
            MENU_ITEM
            {
                command = EAknSoftkeyExit;
                txt = STRING_r_mult_exit;
            }
        };
 }

第六步,实现部分

// -----------------------------------------------------------------------------
// CMultiViewsView1::Id()
// Returns View's ID.
// -----------------------------------------------------------------------------
//
TUid CMultiViewsView1::Id() const
    {
    return TUid::Uid( EMultiViewsView1Id );
    }

// -----------------------------------------------------------------------------
// CMultiViewsView1::DoActivateL()
// Activate an MultiView1
// -----------------------------------------------------------------------------
//
void CMultiViewsView1::DoActivateL( const TVwsViewId& /*aPrevViewId*/,
                                    TUid /*aCustomMessageId*/,
                                    const TDesC8& /*aCustomMessage*/)
    {
       if (!iContainer)
        {
        iContainer = new (ELeave) CKeyCaptureContainer;
        iContainer->SetMopParent(this);
        iContainer->ConstructL( ClientRect() );
        AppUi()->AddToStackL( *this, iContainer );
        } 
    }

// -----------------------------------------------------------------------------
// CMultiViewsView1::DoDeactivate()
// DeActivate an MultiView1
// -----------------------------------------------------------------------------
//
void CMultiViewsView1::DoDeactivate()
    {

    if ( iContainer )
        {
        // Remove View1's container form controllStack
        AppUi()->RemoveFromStack( iContainer );
        delete iContainer;
        iContainer = NULL;
        }
    }

// -----------------------------------------------------------------------------
// CMultiViewsView1::HandleCommandL()
// Takes care of Command handling.
// -----------------------------------------------------------------------------
//
void CMultiViewsView1::HandleCommandL( TInt aCommand )
    {

    if ( aCommand == EMultiViewsSwitchToView2 )
        {
        AppUi()->ActivateLocalViewL( TUid::Uid( EMultiViewsView2Id ) );
        }
    else
        {
        AppUi()->HandleCommandL( aCommand );
        }
    }

// -----------------------------------------------------------------------------
// CMultiViewsView1::HandleSizeChange()
// Called by HandleResourceChangeL() from CMultiViewsAppUi when layout is 
// changed.
// -----------------------------------------------------------------------------
//
void CMultiViewsView1::HandleSizeChange( TInt aType )
    {
    if( iContainer )
        {
        iContainer->HandleResourceChange( aType );
        
        if ( aType==KEikDynamicLayoutVariantSwitch )
            {        
            TRect rect;
            AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, rect);
            iContainer->SetRect(rect);
            }
        }         
    }

第七步,在资源文件中加入TAB资源

RESOURCE EIK_APP_INFO
    {
status_pane = r_multiviewstest_status_pane;
    }

RESOURCE STATUS_PANE_APP_MODEL r_multiviewstest_status_pane
    {
     panes =
         {
          SPANE_PANE
              {
              id = EEikStatusPaneUidNavi;
              type = EAknCtNaviPane;
              resource = r_multiviewstest_navi_decorator;
              }
         };
    }

//    r_multiviewstest_navi_decorator
RESOURCE NAVI_DECORATOR r_multiviewstest_navi_decorator
    {
    type = ENaviDecoratorControlTabGroup;
    control = TAB_GROUP
         {
          tab_width = EAknTabWidthWithTwoTabs; // two tabs
         active = 0;
         tabs = {
              TAB
              {
                id = EMultiViewsTestView1Tab; // from application hrh                     
                txt = qtn_view1_tab;
              },
              TAB
              {
                id = EMultiViewsTestView2Tab;
                txt = qtn_view2_tab;
              }
              };
         };
     }

第八步,在头文件 multiviews.hrh 中加入枚举值
enum TMultiViewsTestTabViewId
{
    EMultiViewsTestView1Tab= 1,
    EMultiViewsTestView2Tab
};

第九步,定义Container类

第一步,让类文件继承 CCoeControl 类
例如:
#include
class CTestAppView : public CCoeControl, MCoeControlObserver
{
......

public:
/**
* From MCoeControlObserver
* Acts upon changes in the hosted control's state. 
*
* @param aControl The control changing its state
* @param aEventType The type of control event 
*/
        void HandleControlEventL(CCoeControl* aControl,TCoeEvent aEventType);
}

第二步,在类中声明一个控件
例如:

class CEikLabel; //先声明引用的类
class CContainer : public CCoeControl, MCoeControlObserver
{
......

private:
    CEikLabel iLabel;
}

第三步, 在类中必须填加的方法

class CEikLabel; //先声明引用的类
class CContainer : public CCoeControl, MCoeControlObserver
{
......

public://继承自 CCoeControl
       virtual void Draw( const TRect& aRect ) const
virtual void SizeChanged();
       virtual CCoeControl* ComponentControl( TInt aIndex ) const;
   virtual TInt CountComponentControls() const;
       // this processes key events
virtual TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent, 
                                                                             TEventCode aType);

public: //from MCoeControlObserver
/**
* From MCoeControlObserver
* Acts upon changes in the hosted control's state. 
*
* @param aControl The control changing its state
* @param aEventType The type of control event 
*/
        void HandleControlEventL(CCoeControl* aControl,TCoeEvent aEventType);

private:
CEikLabel iLabel;
}

第四步, 实现部分

先在文件头填加控件的头文件
#include  

下面的各个方法的实现部分, 一定要注意它们之间的顺序,
第一,先创建窗口 CreateWindowL
第二, 创建你自已的控件
第三,设置窗口的大小
第四,激活窗口
void CContainer::ConstructL(const TRect& aRect)
{
// Create a window for this application view
CreateWindowL();
//=====================
 //     在这里添加控件
 //=======================
iLabel = new (ELeave)CEikLabel();
iLabel->SetContainerWindowL(*this);
iLabel->SetTextL(_L("play"));

// Set the windows size
SetRect(aRect);

// Activate the window, which makes it ready to be drawn
ActivateL();
}

CContainer::~ CContainer()
{
//==================
// 在这里释放控件资源
//====================
delete iLabel;
iLabel = NULL;
// No implementation required
}

//当大小发生变化时,调用该函数
void CContainer::SizeChanged()
{
TPoint startPoint(20, 30);
iLabel->SetExtent(startPoint, iLabel->MinimumSize());
DrawNow();
}

//返回所使用的控件
CCoeControl* CContainer::ComponentControl( TInt aIndex ) const
{
switch(aIndex)
{
case 0:
return iLabel;
}
}

//返回控件的数量
TInt CContainer::CountComponentControls() const
{
return 1;
}

void CContainer::Draw( const TRect& aRect ) const
{
CWindowGc& gc = SystemGc();
// TODO: Add your drawing code here
// example code...
gc.SetPenStyle( CGraphicsContext::ENullPen );
gc.SetBrushColor( KRgbGray );
gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
gc.DrawRect( aRect );
}

TKeyResponse CContainer::OfferKeyEventL(const TKeyEvent& aKeyEvent, 
                                                                             TEventCode aType)
{
        switch( aType )
        {
case EEventKey:
{
return iListBox->OfferKeyEventL( aKeyEvent, aType );
}

case EEventKeyUp:
{
if ( aKeyEvent.iScanCode == 14 || aKeyEvent.iScanCode == 15 ||
aKeyEvent.iScanCode == 16 || aKeyEvent.iScanCode == 17 )
{
// Do nothing about it. Let the listbox handle it.
}
else
{
TBuf<100> buf;
GetKeyString( aKeyEvent.iScanCode, buf );

TBuf<256> display;
display.Format( KStringFormat, iIndex++, &buf );

iItems->AppendL( display );
UpdateDisplayL();
return EKeyWasConsumed;
}
}

default:
break;
}

// now it's iListBox's job to process the key event
return iListBox->OfferKeyEventL( aKeyEvent, aType ); 
    }
}

阅读(858) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~