S60基本程序框架

来源:互联网 发布:淘宝产品主图素材 编辑:程序博客网 时间:2024/06/05 21:13

S60的框架和MFC有类似,它们同样都有application, document, view和control等,s60也是消息传递的机制,也有callback,诚然symbian里最大的特点就是清除栈和活动对象,它们两者的重要性无法替代,也是这个操作系统所特有的。

下面就来剖析一个典型的hello world框架,具体代码可以见SDK里的实例。

这个程序展示了一个基础的应用程序框架,大家可以在上面扩展出更加复杂的程序,呵呵,那是后话了。

下面列出了一个最小的symbian OS应用程序所包括的文件:

HelloWorldBasic.cpp

——The DLL entry point

HelloWorldBasicApplication.cpp

HelloWorldBasicApplication.h

——An Application that creates the new blank document and defines the application UID.

HelloWorldBasicDocument.cpp

HelloWorldBasicDocument.h

——A Document object that represents the data model and is used to construct the App UI.

HelloWorldBasicAppUi.cpp

HelloWorldBasicAppUi.h

——An App Ui(Application User Interface) object that handles the commands generated from menu options.

HelloWorldBasicAppView.cpp

HelloWorldBasicAppView.h

——An App View(Application View)object that displays data to the screen.

HelloWorldBasicView.rss

——The resource file. The describes the application's menus and string resources.

下图展示了这个实例所用到的类图:

File:Class gram.gif

上图显示了一个标准应用程序所使用的类的家族图,可以仔细看看,好东西:)

1、Launch sequence and command handling

这里详细阐述了当程序运行以及用户选择菜单选项时,发生在各对象之间的交互顺序。下面做成了一个图,按顺序进行了逐一的阐释。 Image:lanuch_seq.gif

下面就图上标注的消息来一一说明:

1、应用程序启动,框架装入应用程序DLL,E32Dll method被调用。

2-3、框架调用函数NewApplication,这里生成了一个HelloWorldBasicApplication类的实例,并返回一个指向它的指针。接下来框架会使用这个指针来完成程序的构造。

4、框架调用AppDllUid以获得实际程序的UID,这个UID做什么用的哪,例如,如果一个程序正在运行,而要启动这个程序的另一个实例,这时该运行的程序就会被切换到前台,而不是重新生成一个。

5-8、框架在调用CHelloWorldBasicApplication对象的CreateDocumentL函数,这就生成了一个应用程序文档并返回一个指向它的指针。从而使得框架可以直接调用Document的某些功能。而文档对象也通过调用自己的静态函数NewL获得创建。

9、框架调用AppDllUid,来观察是否要从文件系统中装入一个文件。这里的示例不需要永久存储某些信息,因此不需要与之相关的东西。

10-11、框架调用文档对象的CreateAppUi方法,从而生成了一个App UI对象并返回一个指向它的指针。

12、框架通过调用App UI对象的ContructL函数来完成其构造,事实上在这里完成了App UI想做的所有初始化。

13、ContructL函数首先调用的是App UI基类的BaseContructL函数,这里处理了一些相关事宜,如读入一个与该程序相关的资源文件。

14-16、AppUi调用了AppView类的NewL函数来生成其实例,这里也是用的双重构造。

17、框架调用了Draw函数,怎么调用的还不是因为它从Application->Document->Ui->View不管是直接拥有还是间接拥有,framework到现在都有了无限的调度权利,呵呵。这样调用Draw后就绘制了view。

18-20、无论用户何时选择一个菜单选项,HandleCommandL都被框架所调用,并传递一个参数aCommand,它指明了用户所选择的命令。在这里示例中App UI生成了一个Information note,并显示了它。

下面来详细解释一番

1.1 Entery point

Image:entrypoint.gif

当程序运行时,E32Dll is called with the argument aReason. 参数可以是下面几种类型:EDllProcessAttach, EDllThreadAttach, EDllThreadDetach or EDllProcessDetach.

E32Dll是一个全局函数,被当作DLL的入口。这个函数必须存在,否则程序就会启动失败。

在这个示例中,函数仅仅简单的返回一个KErrNone表示没有发生任何问题,我们可以使用这个入口点来初始化或重置一个thread local storage an application might require.

最后,注意尽管这个DLL入口可以被模拟器所调用,但它并不一定就能被目标机器缺省调用,如需要,则要加下面的语句在MMP文件中:

EPOCCALLDLLENTRYPOINTS

1.2 Creating the Application object Image:application.gif

注意, NewApplication方法必须为导出函数,这可以通过在前面加上关键字EXPORT_C来完成,这里关键字不能少,否则就会link fail.

The framework calls the function that is exported by the application at ordinal 1 in the DLL,这就意味着定义在DEF文件中的第一个函数应该是NewApplication函数。By default, the tool chain automatically ensures that this is the case for a Symbian OS application.

注意,这里new CHelloWorldBasicApplication并没有使用常见的Symbian OS'new (ELeave)'方法,而只用了c++风格的'new',这是因为一个TRAP harness(陷阱捕捉)这时还没有创立。如果系统不能为新的实例分配内存,那这时返回的指针就是NULL,The framework checks for, and copes with, this possibility.

1.3 Getting the application's UID

Image:uid.gif

AppDllUid可以获得应用程序的UID,否则程序也将链接失败。

1.4 Creating the Document object

Image:document.gif

The Application object is responsible for creating an instance of the Document object. However, it is not required to destroy it. Destruction of the Document object is performed by the framework.

1.5 Creating the App UI and View objects

Image:appui.gif

注意AppUi对象的生成并不需要使用Symbian OS的双重构造函数,取而代之的是c++构造函数,生成后一个指针返回给框架,其后框架会调用ConstructL函数来完成构造。这样App UI的所有权被传递到框架所有,而文档则没有义务去析构它。

1.6 Redrawing the screen

Image:redrawing.gif

当view需要被重绘时,由框架来调用Draw方法。这里包括所有需要绘制到view上的代码。注意框架仅仅调用Draw以回应一般的system事件,如,框架在程序启动时可以自动的调用Draw方法,when the options menu disappears, and if the application regains focus.

编程者并不能直接调用Draw,它要求在调用前系统的graphics context处于激活状态,如果编程者希望进行屏幕的重绘,则只能调用DrawNow方法。

注意Draw函数是不能异常退出的,这是因为该函数能被框架直接调用,而框架是不知道如何处理可能发生的异常的。因此Draw自己需要捕捉和处理可能发生的错误。

1.7 Handling commands

Image:command.gif

用户选择菜单选项时,由框架来调用App Ui对象的HandleCommandL函数,这里aCommand参数是一个int值,指明了用户所选择的命令。HandleCommandL会据此来判断不同的命令以分别调度执行。

2 Handling key events

如果程序需要响应用户的按键,那么AddToStackL函数则必须要在AppUi对象的ConstructL中显式的调用,将AppView对象做为其参数,这样就把AppView对象加入到控件栈中()。

Image:keyevents.gif

如果view在control stack中,则无论用户按下哪个键,OfferKeyEventL函数都会被调用。这里有参数指明了按键事件的类型(key down, key press or key up)

Image:offerkey.gif

当App Ui对象释放后,AppView必须从堆栈中移出。这样可以通过调用AppUi对象析构函数的RemoveFromStack来完成。

removefromstack[1]

3 The Symbian OS resource file

资源文件描述了程序的菜单字符串资源,如果需要的话都可以本地化处理,它的语法有自己的特殊性,下面来看。

/*
* ===========================================================================
*  Name        : Helloworldbasic.rss
*  Part of     : Helloworldbasic
*  Interface   :
*  Description :
*  Version     :
*
*  Copyright (c) 2005-2006 Nokia Corporation.
*  This material, including documentation and any related
*  computer programs, is protected by copyright controlled by
*  Nokia Corporation.
* ===========================================================================
*/

NAME HELL NAME必须是资源文件中头一个非注释的语句,它应该在1~4个字符之间。名称应该为大写(小写也是可以的,不过在编译时会自动转为大写)这个语句块通常用来唯一性的标识这个资源文件,这就使得程序可以有多个资源文件,而只有一个共同的名称。

#include <eikon.rh>

#include <avkon.rh>

#include <avkon.rsg>

这里#includes包含了各种资源的定义,有一般的EIKON组件的定义也有指定AVKON资源的定义。

#include "HelloWorldBasic.hrh"

HRH文件包含了所有菜单命令的一个集合枚举(enumeration),菜单选项中每个命令都有个命令标识,就定义在这里,如:
/** HelloWorld enumerate command codes */
enum THelloWorldIds
{
  EHelloWorldCommand1 = 1 // start value must not be 0
};
    RESOURCE RSS_SIGNATURE
    {
    }
这个命令和和NAME语句联系在一起使用的。 This allows a developer to query what the offset for a particular resource file is. The offset is calculated by converting the 4 letters following the NAME statement into an offset value. Whithout this statement it is not possible to find the offset for a particular resource file at run time. RESOURCE TBUF r_default_document_name

buf="";

这里定义了和这个程序联系在一起的缺省的文件名,这个文件名可以当做参数被传递到CAknDocument的OpenFileL(TBool aDoOpen, const TDesC& aFilename, RFs& aFs)方法中,这使应用程序可以在启动时打开一个缺省的文件。如果这里为空,那缺省的文件名就是程序名一样。

RESOURCE EIK_APP_INFO
{
menubar = r_helloworldbasic_menubar;
cba = R_AVKON_SOFTKEYS_OPTIONS_EXIT;

这个结构定义了应用程序的各种资源,它定义了缺省的菜单选项——在r_helloworldbasic_menbar中,以及缺省的softkey(CBA)按钮,在AVKON中,默认是Options和Exit。

注意在这里菜单栏r_helloworldbasic_menubar必须是小写,所有定义RSS中的资源实例都要是小写。当他们被程序所引用时,就要变成大写。这是因为symbian OS资源编译器工作的缘故。

RESOURCE MENU_BAR r_helloworldbasic_menubar

titles =

MENU_TITLE

menu_pane = r_helloworldbasic_menu;

};

The menubar resource should contain a single menu pane that holds the items for the Options menu. If the menu bar contains more than one menu pane, then all the items from the various menu panes are shown on the Options menu.

RESOURCE MENU_PANE r_helloworldbasic_menu

items =

MENU_ITEM

command = EHelloWorldBasicCommand1;
    txt = "Command 1";
},
MENU_ITEM

command = EAknSoftkeyExit;
txt = "Exit";

};

menu pane有一个菜单项目列表,它包括了一个命令ID和要匹配显示的文本。当菜单被选中时这个命令ID被传递到AppUi的HandleCommandL中,而文本则显示在菜单中表示其代表的选项含义。

原创粉丝点击