symbian OS:应用程序的架构——单视图和多视图的对比学习及程序实例

Symbian的程序框架

 

Symbian常用的程序框架是单视图框架和多视图框架两种:单视图框架就是一HelloWord为代表的程序,他是比较简单的程序框架(也是塞班的传统框架),多视图框架也就是我们前面经常有用到的那种双视图程序。

我们还是来回顾一下塞班程序是如何运行起来的。前面已经有提到,塞班运行是从文件appdocumentappui--[view]container按顺序被执行的。塞班当一个塞班程序被激活时,电脑(或手机)从app文件进入,建立一个document文档对象(负责与服务器建立操作关系,这时的手机或模拟器都是用服务器的方式来管理每一个程序和资源的),然后建立一个appui对象(负责程序的视图以及相应用户操作)。

 

单视图框架中,直接使用AppUi管理一个(也可以是几个)container控件容器,AppUi直接拥有(实例化)控件容器。我们还是来看看代码吧,我们建立一个名为Hello的单视图程序(选择使用HelloWord模版),

打开Helloappui.h,看到

class CHelloAppUi : public CAknAppUi

这一句了吗,可以看到AppUi继承自CAKnAppUi,在后面这一句CHelloAppView* iAppView; 还定义一个CHelloAppView的实例(他其实不是view,而是一个container,这个稍后会讲到),而且这个实例将会在构造函数中被实例化、在析构函数中别销毁。

我们再来看看HelloAppView.h这个文件,我们还是来看

class CHelloAppView : public CCoeControl

这一句,我们可以看到,尽管这个文件命名中带有View,但他是继承自CCoeControl类,而这个类管理着很多的标准控件,如标签、编辑框、列表框、按钮等等,所以这个文件应该是Container控件容器,而且Draw  SizeChanged  以及CountComponentControls  ComponentControl 这些函数都是控件容器所特有的呢。

 

多视图框架中,AppUi使用系统的视图服务器来管理若干个View视图,每一个视图都有一个container控件容器,也可以拥有自己的菜单。在AppUi的构造时,把所有的View实例化并添加到视图服务器中,AppUi控制着视图的切换(激活和去激活)。我们还是来看看代码吧,我们建立一个名为Test的多视图程序(选择使用view application模版),打开Testappui.h看这个句子

class CTestAppUi : public CAknViewAppUi

可以看到AppUi继承自CAKnViewAppUi,这是视图服务器,appui负责每一个视图的实例化并加入到视图服务器中,负责各个视图间的切换等工作。

我们再去看看TestView.h文件,可以看到有这样两个函数 DoActivateL和 DoDeactivate。这就是View自身的激活与去激活处理函数。

 

 

看来这样说是不容易清楚的,干脆来个表格吧

 

单视图

 

多视图

Appui管理

实例化Container,直接拥有容器控件

 

利用视图服务器,管理视图加入、切换

实例化

iAppContainer = new (ELeave) CHelloContainer;

iAppContainer->SetMopParent( this );

iAppContainer->ConstructL( ClientRect() );

AddToStackL( iAppContainer ); // 入栈 相应用户

CTestView* view1 = new (ELeave) CTestView;

CleanupStack::PushL( view1 );

view1->ConstructL();

AddViewL( view1 );     // 加入到视图服务器

CleanupStack::Pop();

 

SetDefaultViewL(*view1);  //默认视图

 

销毁

在Appui析构函数中销毁

RemoveFromStack( iAppContainer );

delete iAppContainer;

 

自动调用View中的去激活函数自销毁

 

切换

销毁旧容器控件,然后实例化新的容器控件,设置父窗口、入栈。

菜单命令

Tuid Viewed ;

Viewed.iUid=EshapeDrawerListViewId;

ActibateLocalViewL(Viewed);

Break;

 

执行顺序

DoActivateL()

HandleForegroundEventL(ETrue)

HandleForegroundEventL(EFlase)

DoDeactivate()

 

 

 

 

来个实例更给力。我们建立一个名为Test的多视图程序,现在把他变成只有一个视图的程序(当然还是利用视图管理程序来管理,以后你想有几个视图就有几个视图了)。

修改Test.rss,变成这样的。如果你怕麻烦,就直接Copy复制好了

 

NAME    AWIZ
#include <eikon.rh>
#include "Test.hrh"
#include "Test.rls"
#include <avkon.rsg>
#include <avkon.rh>
#include <avkon.mbg>
#include <appinfo.rh>

RESOURCE RSS_SIGNATURE { }

RESOURCE TBUF { buf = "Test"; }

//程序运行时框架的基本信息
RESOURCE EIK_APP_INFO
    {
    hotkeys = r_test_hotkeys;
menubar = r_test_app_menubar;  
//定义左软键和右软键的类型
    cba     = R_AVKON_SOFTKEYS_SELECTION_LIST; 
    }

//程序运行前,在模拟器资源中的图标和文字信息
RESOURCE LOCALISABLE_APP_INFO r_test_localisable_app_info
    {
    short_caption = qtn_app_short_caption_string;
    caption_and_icon = 
    CAPTION_AND_ICON_INFO
        {
        caption = qtn_app_caption_string;

        number_of_icons = 1;
        icon_file = "\\resource\\apps\\Test_REG.mif";
        };
    }
    
//可能是推出程序的快捷按键吧
RESOURCE HOTKEYS r_test_hotkeys
    {
    control =
        {
        HOTKEY { command = EAknCmdExit; key = 'e'; }
        };
    }

//定义一个视图
RESOURCE AVKON_VIEW r_test_view1
    {
    hotkeys = r_test_hotkeys; 
    cba     = R_AVKON_SOFTKEYS_SELECTION_LIST;    
    }

//定义程序主菜单 
RESOURCE MENU_BAR r_test_app_menubar
    {
    titles =
        {
        MENU_TITLE { menu_pane = r_test_app_menu; txt = "App"; }
        };
    }

RESOURCE MENU_PANE r_test_app_menu
    {
    items =
        {
        MENU_ITEM { command = ETestCmdAppTest; txt = qtn_appl_option_item; },
        MENU_ITEM { command = EAknCmdExit; txt = qtn_appl_exit; }
        };
    }

修改TestAppui.h
#ifndef TESTAPPUI_H
#define TESTAPPUI_H

#include <aknviewappui.h>
#include <aknnavide.h>

class CTestContainer;

class CTestAppUi : public CAknViewAppUi
    {
    public: // // Constructors and destructor    
        void ConstructL();     
        ~CTestAppUi();
        
    public: // New functions
    private:
        void DynInitMenuPaneL(TInt aResourceId,CEikMenuPane* aMenuPane);
        void HandleCommandL(TInt aCommand);
        virtual TKeyResponse HandleKeyEventL(
            const TKeyEvent& aKeyEvent,TEventCode aType);
    };

#endif

修改TestAppui.cpp
#include "TestAppui.h"
#include "TestView.h"
#include <Test.rsg>
#include "Test.hrh"

#include <avkon.hrh>

void CTestAppUi::ConstructL()
    {
    BaseConstructL();

    CTestView* view1 = new (ELeave) CTestView;
    CleanupStack::PushL( view1 );
    view1->ConstructL();
    AddViewL( view1 );      // 加入到视图服务器
    CleanupStack::Pop();    

    SetDefaultViewL(*view1);  //默认视图

    }

CTestAppUi::~CTestAppUi()
   {
   }

void CTestAppUi::DynInitMenuPaneL(
    TInt /*aResourceId*/,CEikMenuPane* /*aMenuPane*/)
    {
    }

TKeyResponse CTestAppUi::HandleKeyEventL(
    const TKeyEvent& aKeyEvent,TEventCode aType)
    {
    //aKeyEvent.iCode == EKeyLeftArrow || aKeyEvent.iCode == EKeyRightArrow )
     return EKeyWasNotConsumed;
    }

void CTestAppUi::HandleCommandL(TInt aCommand)
    {
    switch ( aCommand )
        {
        case EEikCmdExit:
            {
            Exit();
            break;
            }
        case ETestCmdAppTest:
            {
            iEikonEnv->InfoMsg(_L("test"));
            break;
            }
        default:
            break;      
        }
    }

修改Test.mmp,删掉里面的TestView2.cpp和TestContainer2.cpp那两个句子。

    最后,你就可以编译程序了,看看程序变成什么样子的了


你可能感兴趣的:(symbian OS:应用程序的架构——单视图和多视图的对比学习及程序实例)