symbian系统开发培训_第1页
symbian系统开发培训_第2页
symbian系统开发培训_第3页
symbian系统开发培训_第4页
symbian系统开发培训_第5页
已阅读5页,还剩73页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

SymbianOS开发培训InspurCommunicationInformationSystemsCo.,Ltd

第一页,共七十八页。SymbianOS概述

1998年6月,诺基亚(NOKIA)、摩托罗拉(MOTOROLA)、爱立信(ERICSSON)、三菱(MITSUBISHI)和Psion在英国伦敦共同投资成立Symbian公司。这个公司成立的目的是为了能够设计并开发出一种可以在手机及其他类似的移动通讯终端产品上运行的开放性操作系统,以此来推动高端智能移动电话及类似的终端产品尽快进入大众消费领域。之后有西门子(SIEMENS)、三星(SAMSUNG)、松下(Panasonic)、索尼爱立信(SonyEricsson)等手机厂商相继入资,现如今,Symbian操作系统的智能手机已经占据了世界智能手机市场超过80%的份额。第二页,共七十八页。SymbianOS概述

Symbian是一个实时性、多任务的纯32位操作系统,具有功耗低、内存占用少等特点,非常适合手机等移动设备使用,经过不断完善,可以支持GPRS、蓝牙、SyncML、以及3G技术。Symbian是一个标准化的开放式平台,任何人都可以为支持Symbian的设备开发软件。与微软产品不同的是,Symbian将移动设备的通用技术,也就是操作系统的内核,与图形用户界面技术分开,能很好的适应不同方式输入的平台,也可以使厂商可以为自己的产品制作更加友好的操作界面,符合个性化的潮流第三页,共七十八页。SymbianOS概述

目前SymbianOS手机有三种开发SDK:NokiaSeries80:主要机型有Nokia9200系列NokiaSeries60:主要机型包括诺基亚7650、6600、西门子SX1等UIQ2、UIQ3:SonyEricssonP800,P900SonyEricssonP900第四页,共七十八页。开发平台搭建安装ActivePerl(x86和x64分别对应32位和64位cpu)jre(java的应用平台)SymbianOSSDK(建议安装在盘符根目录下)(C++)开发工具第五页,共七十八页。手机软件开发过程:开发平台搭建第一步:安装开发软件,搭建开发环境(下面主要介绍series60sdk,其余类似)第二步:在模拟器上开发调试(以VC环境开发为例)第三步:生成sis文件,在手机上安装运行第六页,共七十八页。几种开发环境:开发平台搭建VisualC++6.0BorlandC++Builder6CarbideC++第七页,共七十八页。开发平台搭建Symbian工程aifdatagroupincsrcsis工程基本目录结构:1.aif用来存放程序图标2.data用来存放运行所需要的资源文件.rss。3.group中比较重要的几个文件:bld.inf、*.mmp。4.inc和src存放工程头文件和源代码文件。5.sis用来存放程序打包所需要的pkg文件,打包后生成的安装文件.sis也存放在此处。第八页,共七十八页。bld.inf声明build的相关信息通常只包括这次build会引用到的mmp文件。例如:PRJ_MMPFILES

hello.mmp2..mmp文件保存工程编译相关信息,主要内容如下

TARGEThello.app//目标名称TARGETTYPEapp//目标类型UID0x100039CE0x07B9DE87//UID唯一系统标示符TARGETPATH\system\apps\hello//目标路径SOURCEPATH..\src//源代码存放位置SOURCEhelloApp.cpp//源代码列表…

开发平台搭建第九页,共七十八页。

SOURCEPATH..\data//资源文件路径RESOURCEhello.rss//资源文件LANGSC//默认英语

USERINCLUDE.USERINCLUDE..\inc//头文件路径SYSTEMINCLUDE.\epoc32\include//系统包含文件目录LIBRARYeuser.libapparc.libcone.libeikcore.libLIBRARYeikcoctl.libavkon.lib//库文件3.UIDUID1-第一个UID(类型):

UID1用来设定该应用程序是一个执行程序(executablefile)还是一个数据文件(datafile).UIDvalueNumericvalue(Hex)MeaningKExecutableImageUid0x1000007A.exe可执行文件KDaynamicLibraryUid0x10000079.dll.app.ldd,.pdd文件KDirect0x10000037directKPermanent0x10000050permanent第十页,共七十八页。UID2-第二个UID(子类型):

UID2-具体含义取决于UID1的值:如果UID1是KExecutableImageUid,UID2不使用,所以UID2的值可以随意取。如果UID1是KDynamicLibraryUid,UID2将会是:

如果UID1是KDirect或者KPermanent,那么UID2将是:UIDvalueNumericvalue(Hex)MeaningKSharedLibraryUid0x1000008D.dllKUidApp0x100039CE.appKLogicalDeviceDriverUid0x100000AFalogicaldecivedriver(.ldd)KPhysicalDeviceDriverUid0x100039D0aphysicaldevicedriver(.pdd)UIDvalueNumericvalue(Hex)MeaningKUidAppDllDoc0x10003A12indicatesthisisacreatedbyan.apptostoreuserdata(i.e,adocument)KUidAppInfoFile0x10003A38IndicatesthisisanAIFfile(atypeof)第十一页,共七十八页。UID3-第三个UID(子子类型):

每个独立的应用程序有一个唯一的UID3值,它也被用作安全ID(secureID),对于UIKON应用程序而言,用于关联数据文件和程序:1.

对于dll和exe文件,它辩识特定的二进制(itidentifiedtheparticularbinary)。2.

对于.app(UIKON应用程序),它辩识特定的应用程序(itidentifiedtheparticularapplicationprogram).3.

对于由.apps创建的文件存储(),它辩识和该文件相关的应用程序(itidentifiestheapplicationprogramassociatedwiththisfile).4.

对于其他文件存储(),它没有典型的用途(但是你可以自定义它的用途)

第十二页,共七十八页。Symbian命名约定

Symbian大致分了四种类C:C前缀表示类从CBase派生并应该基于堆构造。T:T前缀表示一个简单类,这种类不拥有任何额外的资源。如Tint、TReal等基本数据类型。R:R前缀表示一个资源类,它包含其它位置拥有资源的句柄。M:M前缀表示一个接口类,它定义了接口但需要派生类实现。结构(struct)类型作为T类对待,因为它也不拥有任何额外的资源,它的前缀通常是T(但也有一些以S开头)。enumTColors{ERed,//尽量用E开头,尽量用枚举EGreen}成员变量的名字以i开头,参数名以a开头classTMyClass{

TIntiMyValue;

voidMyAddFunc(TIntaArg1,TIntaArg2);

voidMyAddFunc(TIntaArg1,TIntaArg2);voidMyAddFuncL(TIntaArg1,TIntaArg2);-------->后缀L的约定是该函数可能产生异常退出;voidMyAddFuncLC(TIntaArg1,TIntaArg2);

---------->后缀LC的约定表示成功完成之后,返回值会被压入清理栈中;(栈不保存)};

Symbian编程规范和基本框架第十三页,共七十八页。Symbian命名约定常量应加前缀KconstCIntKMyconstant;宏全部为大写#defineMY_HARDCODED_VALUE(25)

Symbian四个主要的应用软件框架类

针对右图Graphics,UI程序应该具备的基本功能类:视图(View)、文档(Document)、应用程序(Application)、应用程序UI(ApplicationUI)。所有的S60UI应用程序都具有一些基本功能:

提供一个用户界面,用于显示信息并允许用户进行交互。

响应各种用户启动的事件,比如用户选择一个菜单项。

响应系统启动的不同事件,比如导致屏幕重绘的window服务器事件。

能够保存和恢复应用程序数据。可以唯一性的向框架标志自身。向框架提供有关应用程序的描述性信息,比如图标和标题等。Symbian编程规范和基本框架第十四页,共七十八页。Symbian四个主要的应用软件框架类一个程序只能有一个文档,可以有多个视图。必须创建下面的每个方法,才能提供最小的S60应用程序:

所有S60UI都实现一个全局函数E32DLL(),当应用程序启动时,框架将首先调用该函数,该函数也称为DLL入口点,应用程序必须存在该函数。

框架调用Ne(),创建Application类,其基类是CAknApplication.Application类创建应用程序类的Document对象,并返回它的指针,以后框架使用该指针完成应用程序的创建。

由框架调用AppDllUid()返回应用程序的UID。该函数必须返回在.mmp文件中指定的值。Document基类是CAknDocument.

Document对象通过CreateAppUiL创建获取AppUi类的指针。AppUi类的基类是CAknAppUi或者

CAknVie,它是用来处理应用程序事件,如操作菜单,操作视图,切换视图等等。View是控制类(c类),在屏幕上显示数据,用户与界面交互,传递命令给AppUi。Symbian编程规范和基本框架第十五页,共七十八页。Symbian处理内存泄漏的手段1.Trap和TrapD处理异常

TInterr;

Trap(err,CreateObject());//需要先定义err变量TrapD(err,CreateObject());//不需要定义err变量2.CleanupStack

它是处理内存泄漏的又一重要手段CFoo*p=new(ELeave)CFoo();CleanupStack::PushL(p)p->SomeFunctionL();//可能异常退出,使得deletep得不到调用CleanupStack::Pop();

deletep;Symbian二阶段构造在Symbian中,如果在一个类的构造函数中需要执行某些比如申请内存等操作,那么有可能会Leave。如果Leave的话,这个时候这个类的析构函数是不会被调用,因为还没有初始化完,也就没法把自己加入CleanupStack,那么那些申请了的内存可能会因为没有变量引用而造成内存泄漏。因此在Symbian中类的构造函数中不能有可能会Leave的代码。

Symbian编程规范和基本框架第十六页,共七十八页。Symbian二阶段构造初始化一个类确实需要执行某些可能会Leave的函数,这就是Symbian中要求的两阶段初始化了。第一阶段,也就是在构造函数中执行一些不会Leave的初始化工作。然后是第二阶段,把这个实例推进CleanupStack,再执行第二阶段的可能会Leave的代码。当然,在析构函数中,要能够处理部分初始化的情况,也就是实例没有初始化成功,也能释放那些已经申请的内存或资源。

CGraphicsAppView::CGraphicsAppView(){}CGraphicsAppView*CGraphicsAppView::NewL(constTRect&aRect){CGraphicsAppView*self=NewLC(aRect);CleanupStack::Pop(self);returnself;}CGraphicsAppView*CGraphicsAppView::NewLC(constTRect&aRect){CGraphicsAppView*self=new(ELeave)CGraphicsAppView;CleanupStack::PushL(self);self->ConstructL(aRect);returnself;}voidCGraphicsAppView::ConstructL(constTRect&aRect){CreateWindowL();SetRect(aRect);}Symbian编程规范和基本框架第十七页,共七十八页。描述符描述符是用来存储文本和二进制的基本类抽象类(Abstract):(TDes、TDesC、TDes8、TDesC8),描述符的基类,仅提供接口和基本功能,不能被实例化,一般只用作函数的参数。文字常量(Literal):(TlitC、_LIT()),用于存储文字字符串(literalstring),即C中字符串常量,通常使用_LIT()这种方式,也有_L(),_L8()这种方式。栈类(Buffer):(TBuf、TBufC、TBuf8、TBufC8),数据存储于栈上,最基本的描述符变量类型,大小在编译时确定,包含描述符本身数据,使用最为普遍,具体方法如下堆类(Heap):(HBufC、HBufC8),数据存储于堆上,大小在运行时确定,也就是用来处理动态申请的描述符类。在C/C++中用过动态内存的都知道,动态内存是啥回事,这里堆类描述符用的时候,也是差不多,由于堆描述符没有构造函数,所以只能声明为指针类型,通过堆描述符类内静态函数NewL方法申请内存,具体方法如下HBufC*errorTitleCode=HBufC::NewLC(50);HbufC*unUseCode=NULL;指针类(Pointer):(TPtr、TPtrC、TPtr8、TPtrC8),本身不包含描述符数据,但是包含长度数据,而且还包含一个指向位于描述符之外数据的指针。Symbian基本语法第十八页,共七十八页。描述符关系简图

Symbian基本语法第十九页,共七十八页。描述符的使用文字描述符常量

_LIT(KMyFile,“c:\System\Apps\MyApp\My”);它可以在任何使用TDesC&的地方使用。//常用的通知函数NEikonEnvironment::MessageBox(_L("Error:initfound!"));//数字转字符串TBuf16<20>buf;//TIntiNum=20;buf.Format(_L("%d"),iNum

);栈描述符栈类描述符声明时必须指定描述符的最大长度,否则无法声明和定义,举例如下://直接从字符串中构造_LIT(Ktext,"TestText");TBufC<10>Buf(Ktext);//或从字符串赋值TBufC<10>Buf2;Buf2=Ktext;//从已有的对象中生成新的TBufCTBufC<10>Buf3(Buf2);Symbian基本语法第二十页,共七十八页。描述符的使用栈描述符

尽管这里的对象表示数据是不能被修改的(因为有个后缀C代表了常量的意思),但仍然有两种方式可以用来修改数据内容:这里的数据可以用赋值的方式替换掉;使用Des()函数构造出一个TPtr对象,这样就可以用它来修改数据。_LIT(Ktext,"TestText");

_LIT(Ktext1,"TestText”);_LIT(KXtraText,"New:");TBufC<10>Buf1(Ktext);//Buf1长度为9内容“TestText”TBufC<10>Buf2(Ktext1);//Buf2长度为10内容“Test1Text”//通过赋值的方式改变数据Buf2=Buf1;//Buf2长度变为9内容“TestText”//通过使用Des()生成指针改变TBufC的数据TPtrPointer=Buf1.Des();//删除后四个字符Pointer.Delete(Pointer.Length()-4,4);//Buf1长度变为5内容“Test”

//增加新的数据Pointer.Append(KXtraText);//Buf1长度为9内容为“TestNew:”//也可以使用下列方式改变数据

TBufC<10>Buf3(NewText);Pointer.Copy(Buf3);//Buf1长度为4,内容为New1//或直接从字符串里获得数据Pointer.Copy(NewText1);//Buf1长度为4,内容为New2Symbian基本语法第二十一页,共七十八页。描述符的使用栈描述符可修改的描述符TBuf,TBuf8就不用通过那么复杂的方法来实现修改,它直接可以用Copy、Delete等方法,但是无论可修改的还是不可修改的,一旦指定最大的数据长度后,最大长度就不能进行修改了修改的只是数据内容,而数据内容修改的受限条件是不能超过声明或定义时的最大长度。堆描述符堆描述符HBufC,HbufC8虽然都是不可修改类型的,但是它仍然具有构造和修改,与栈描述符不同的是:首先对内存需要显示释放,其次是堆描述符没有最大长度的限制,任何时候都可以用ReAlloc()函数重新申请分配。有两种方式来生成一个堆描述符示例:

//第一种方式用New(),NewL(),或NewLC()

HBufC*Buf=HBufC::NewL(15);

//第二种方式是采用Alloc(),AllocL()或AllcLC()来处理_LIT(KText,"TestText");

TBufC<10>

CBuf=KText;

HBufC*Buf1=CBuf.AllocL();

CleanupStack::PushL(Buf1);堆描述符的修改方式:

//1.赋值方式改变其数据的方法

_LIT(KText1,"Text1");

*Buf1=KText1;

Symbian基本语法第二十二页,共七十八页。描述符的使用堆描述符堆描述符的修改方式://2.通过可修改指针来改变数据的方式

TPtrPointer=Buf1->Des();

Pointer.Delete(Pointer.Length()-2,2);

//删除数据

_LIT(KNew,"New:");

Pointer.Append(KNew);

//添加数据重新申请内存Buf1=Buf1->ReAllocL(KText().Length()+KNew().Length());CleanupStack::PushL(Buf1);释放内存

deleteBuf;

Buf=NULL;指针描述符不可修改的指针TPtrC可用TBuf和TBufC构造出TPtrC对象

_LIT(KText,"TestCode");

TBufC<10>Buf(KText);

//或者为TBuf<10>Buf(KText);

TPtrC

Ptr(Buf);//使用构造函数初始化

TPtrC

Ptr1;

Ptr1.Set(Buf);//利用set函数初始化Symbian基本语法第二十三页,共七十八页。描述符的使用指针描述符不可修改的指针TPtrC

用TText*构造TPtrC

constTText*text=_S("HelloWorld\n");

TPtrCptr(text);

//或者

TPtrCPtr2;

Ptr2.Set(text);

//如果要存储TText的一部分数据,我们使用下列方法

TPtrC

ptr4(text,5);

从另一个TPtrC中构造TPtrC

constTText*text1=_S("HelloWorld\n");

TPtrCPtr3(text1);

//从一个TPtrC中获得另一个TPtrC

TPtrCp1(Ptr3);

//或

TPtrCp2;

p2.Set(Ptr3);可修改的TPtr同不可修改的指针描述符构造方法基本类似,区别在于,不可修改的指针描述符TPtrC的函数始终是不可修改的,因此没有Insert,Delete等函数,并且没有Des()函数,但有Alloc(),Compare(),Find(),Mid(),Size()等函数。Symbian基本语法第二十四页,共七十八页。动态数组

在传统c/c++中经常会使用数组来存储序列,它是具有相同数据类型的数据元素的集合,通过数组可以很方便的实现数据元素的访问等相关操作。动态数组是一个类的模板,可以接受各种各样的数据类型,SymbianOS主要提供了3类动态数组:

RArray<classT>,RPointerArray<classT>,CArray<classT>活动对象

在symbianos中活动对象是一种非抢先式多任务处理的机制,是symbianos中一个十分重要的概念。可用于替代SymbianOS中的多线程。使用活动对象可获得的好处是:在同一个线程中运行的活动对象之间进行切换的代价要比线程上下文的切换代价低,这使得对于各种资源比较紧张的SymbianOS来说,使得活动对象更适合事件驱动多任务。

概念:一个活动对象必须派生自基类CActiveclassCActive:publicCBase{

public:

enumTpriority

{

EPriorityIdle=-100;

EPriorityLow=-20;

EPriorityStandard=0;

EPriorityUserInput=10;

EPriorityHigh=20;

}

Symbian基本语法第二十五页,共七十八页。活动对象

public:

IMPORT_C~CActive();

IMPORT_CvoidCancel();//删除未完成请求的函数

……

IMPORT_CvoidSetPriority(TIntaPriority);

InlineTBoolIsActive()const;

……

protected:

IMPORT_CCActive(TIntaPriority);

IMPORT_CvoidSetActive();

virtualvoidDoCancel()=0;//两个纯虚函数,继承类必须实现它们

virtualvoidRunL()=0;//处理函数

IMPORT_CvirtualTIntRunError(TIntaError);

public:

TrequestStatusiStatus;//代表请求状态

…….

private:

TBooliActive;

…….

}构造时也会有一个优先级值来决定它们如何被调度Cancel和DoCancel用来取消发出的请求,Docancel是一个纯虚函数,需要由派生类实现。Cancel的功能就是调用DoCancel,如果用户取消当前请求调用Cancel而不是DoCancel,但在代码中要实现DocancelSymbian基本语法第二十六页,共七十八页。活动对象IsActive确定活动对象是否处于活动状态SetActive激活活动对象,一般在调用请求后紧接着调用它。RunL异步事件处理函数,当一个请求完成时,活动对象调度器会调用这个函数,进行下一步处理RunError当RunL函数出现异常时会出现RunError函数,它也是纯虚函数,需要派生类实现。

具体例子见文档。文件管理symbian系统采用了C/S(客户端/服务器)的架构。对于文件操作,系统有一个文件系统管理的服务器。程序通过联结这个文件管理服务器来进行文件。在symbianos中,Flash(闪存)通常被定义在c盘,symbian智能手机中还有一个ROM存储器通常被映射在z盘,用户的许多文件也存放在z盘。其他可移动存储(如存储卡)则映射在d,e等盘符。symbian开发环境下各盘符对应的映射关系:客户机c:盘对应开发平台中sdk的\epoc32\wins\c目录客户机d:盘对应开发平台中sdk的\epoc32\wins\d目录客户机z:盘对应开发平台中sdk的\epoc32\release\wins\urel\z目录或者\epoc32\release\wins\urel\z文件命名规则一个完整的symbianos文件应该包含以下四个部分1.驱动器名,即盘符2.路径,从根目录到或当前会话目录起到文件经过的所有目录路径3.文件名,遵循c/c++命名规范4.文件扩展名例如:c:\my就是合法的文件名,一个完整的文件名不能超过255个字符。Symbian基本语法第二十七页,共七十八页。文件管理文件访问流程1.应用程序要进行文件读写之前,必须建立应用程序与文件服务器的连接,这种连接也称会话(session),Sysmbianos中提供RFs类来实现这个功能,该类提供了Connect()和Close()函数来建立和关闭连接。RFsfsSession;//建立RFs类的对象User::LeaveIfError(fsSession.Connect());//建立连接,为防止出现异常放User::LeaveIfError中

fsSession.Close();//用完关闭连接2.文件服务器可以实现文件的读、写、删、建,通过R(RFsaFs,constTDesC&aName,TUnita)打开文件。通过Write()和Read()可以实现文件的写和读。R()用于建立新文件。删除文件可以使用RFs的Delete()。3.另一种比较重要的文件读写方式----流(Stream)文件输出流RWriteStream和文件输入流RReadStream文件输出六主要使用RWriteStream的派生类R将数据外化为流,它需要先打开一个文件,打开文件的两种方式:OpenL:当文件不存在会产生异常,所以必须保证文件存在Replace:文件存在删除并重建新的,不存在就创建,因每次都创建文件,会带来额外开销。例子:

Rwriter; writer.PushL();//writeroncleanupstack User::LeaveIfError(writer.Replace(iCoeEnv->FsSession(),*i,E)); writer<<*iText; //writethetext writer.CommitL(); CleanupStack::PopAndDestroy();//释放资源从存储中读取数据的方法就是将以上的过程反向Symbian基本应用第二十八页,共七十八页。数据库管理

Symbian系统的DBMS提供了创建与维持数据库的功能,通过本地调用和SQL调用,其可以对数据库进行安全可靠的数据访问。这种调用支持事务/回滚机制用以保证所有数据被写入或数据为空的情形获得支持。DBMS的管理结构和元素任何Symbian系统的DBMS都采用层次性的结构—最底层是保存数据库的文件仓库。Symbian操作系统的DBMS是一个功能强大,或为轻量集的数据库关系系统实现。它支持普通的添加/查找/检索/更新/删除功能,同时它还支持基本的结构化查询语言(StructuredQueryLanguage:SQL),数据定义语言(DataDefinitionLanguage:DDL)和数据建模语言(DataModelingLanguage:DML)语句处理。永久文件存储系统和流Symbian系统的DBMS依赖于文件服务器提供的资源,Symbian系统所的永久文件存储和流能提供系统所需要的底层存储功能。永久文件系统通过使用CPermanent来获得,它是一个源自C的具体类。这些类在文件存储API中定义,可为DBMS提供组建模块。创建数据库(1)RDbStoreDatabase:通过文件存储打开的数据库,提供了进行数据库操作的API,独占使用数据库,不可共享使用。(2)RDbNamedDatabase:通过文件名打开的数据库,同样提供API。使用C/S模式,可以共享使用(3)CDbColSet:数据库字段的集合,可用于在数据库中创建表格。(4)使用到的库和头文件:ws32.libedbms.libd32dbms.hf32file.hs32file.h创建步骤:(1)数据库类的声明:将RFs和RDbStoreDatabase声明为数据成员。classCMiapSampleDatabase:publicCBase

{

Symbian基本应用第二十九页,共七十八页。数据库管理public:

//SomeFunctions

private:

RFsiFsSession;

RDbStoreDatabaseiDb;};

(2)创建数据库:

首先打开一个文件流存储(),通过调用RDbStoreDatabase::CreateL(CStreamStore*aStore)来创建数据库。最后将文件流提交。

_LIT(K,"C:\\DataBase.db");

C*=CPermanent(iFsSession,K,E);

CleanupStack::PushL();

>SetTypeL(>Layout());

TStreamIdid=iDb.CreateL();

>SetRootL(id);

>CommitL();

CleanupStack::PopAndDestroy();

iOpen=ETrue;

iDb.Close();Symbian基本应用第三十页,共七十八页。数据库管理(3)创建表格:

通过文件流存储打开数据库:

_LIT(K,"C:\\DataBase.db");

C*=CPermanent(iFsSession,K,E);

>SetTypeL(>Layout());

iDb.OpenL(,>Root());

添加字段:

_LIT(KId,"Id");

_LIT(KText,"Text");

_LIT(KTableName,"Table");

TDbColIdCol(KId,EDbColText);

TDbColTextCol(KText,EDbColText);

CDbColSet*ColSet=CDbColSet::NewLC();

ColSet->AddL(IdCol);

ColSet->AddL(TextCol);

创建表格:

User::LeaveIfError(iDb.CreateTable(KTableName,*ColSet)); 释放不使用的内存:

CleanupStack::PopAndDestroy(ColSet);

CleanupStack::PopAndDestroy();Symbian基本应用第三十一页,共七十八页。数据库管理(4)创建索引:

TDbKeyColIdKey(KId);

CDbKey*key=CDbKey::NewLC();

key->AddL(IdKey);

User::LeaveIfError(iDb.CreateIndex(KTableName,KTableName,*key));

CleanupStack::PopAndDestroy(key);

首先创建一个索引对象,将其添加到索引集合中,通过调用RDbStoreDatabase::CreateIndex(constTDesC&aName,constTDesC&aTable,constCDbKey&aKey)创建表格,最后清除不使用的内存。(5)插入记录:

_LIT(KIdText,"100001");首先打开数据库。打开表:

RDbTabletable;

CleanupClosePushL(table);

User::LeaveIfError(table.Open(iDb,aTableName,table.EUpdatable));

获取字段集合:

CDbColSet*ColSet=table.ColSetL();

CleanupStack::PushL(ColSet);

添加记录:

table.Reset();

table.InsertL();

table.SetColL(ColSet->ColNo(KId),KIdText);

table.PutL();

CleanupStack::PopAndDestroy(2);//清除内存:注意:每插入一条记录,就必须调用table.InsertL(),设置完值后,必须调用table.PutL()提交。Symbian基本应用第三十二页,共七十八页。(6)查询记录:

首先打开数据库和表。

TPtrCptrc;

for(table.FirstL();table.AtRow();table.NextL())

{

table.GetL();

ptrc.Set(table.ColDes(colSet->ColNo(KId)));

}

table.FirstL()将焦点设置为第一条记录,table.AtRow()验证下一条记录是否存在,table.NextL()将焦点移动到下一条记录。

每查询一条记录,必须调用table.GetL();

使用TPtrC::Set()将查询结果写进描述符。(7)执行SQL语句:

首先打开数据库。 TBuf<256>SQL;

SQL.Append(_L("//SomeSQL"));

RDbUpdateDbUpdate;

TIntincStat=DbUpdate.Execute(iDb,SQL,EDbCompareNormal);

incStat=DbUpdate.Next();

while(incStat==1)

{

incStat=DbUpdate.Next();

}

DbUpdate.Close();Symbian基本应用第三十三页,共七十八页。

SymbianGUI编程60系列用户界面显示器规范如下:分辨率:176像素(宽)×208像素(高)正方形像素物理尺寸:约35mm(宽),41mm(高), 对应约0.2mm的象素点距。颜色数(4096色或更多)第三十四页,共七十八页。

SymbianGUI编程第三十五页,共七十八页。SymbianGUI编程显示器按照一定的层次结构进行布局。布局由被称为窗口(windows)和窗格(panes)的组件构建。屏幕(Screen)是最顶层的显示组件,对应于物理屏幕的整个象素区域。窗口(Window)屏幕(screen)是窗口的唯一父组件。一般情况下一个窗口会充满整个屏幕,但有时也存在一些小窗口(临时性的),它们只占据屏幕的一部分,环绕其周围的部分是可见的。每个应用程序都在自己的窗口中运行。应用程序也可以调用其它的临时窗口。

窗格(Pane)窗格是窗口(window)的子组件。一个窗口可以包含多个窗格,而每个窗格又可以包含多个子窗格,如此等等。不含有子组件的底层组件被称为元素(element)。

应用窗口应用窗口是覆盖整个屏幕的主窗口。通常它并不直接用于显示,而是作为各种窗格的父组件。一个典型的应用窗口由下几种窗格组成:-状态窗格-主窗格-控制窗格第三十六页,共七十八页。SymbianGUI编程第三十七页,共七十八页。GUI应用程序的基本组成部分Application负责启动方面的工作Document负责永久保持的工作AppUI负责接受并处理用户的命令AppView负责图形显示的工作Model可选:负责处理数据第三十八页,共七十八页。view架构view是一个执行特定任务的一屏同一时刻,view管理系统只允许一个view处于激活状态每个view都有一个ID每个view必须到viewserver上去登记调用ActiveViewL()还能够激活其它应用程序的views在view之间能够传递消息classCMyView:publicCAknView第三十九页,共七十八页。CCoeControl框架主要内容简单控件CCoeControl概述控件的初始化控件的重绘用户输入处理(按键事件)复合控件常用控件对话框表格资源菜单软键热键第四十页,共七十八页。CCoeControl框架WINDOWSserver第四十一页,共七十八页。CCoeControl框架WINDOWSserver第四十二页,共七十八页。CoeControl可以作为视图的基类传统的EIKON视图架构-containerdialog负责应用程序视图区域的显示工作一个应用程序的界面分为三部分标题栏软键区域应用程序视图区域(右图的黑框部分)使用CGraphicsContext进行画图在UI平台能力范围内工作(如:60系列)系统提供的常用控件有按钮编辑器文本标签列表框可以内嵌其它控件(又称定制控件,或者复合控件)第四十三页,共七十八页。CoeControl所有对屏幕的操作都是在控件上进行控件从CCoeControl继承而来控件是屏幕上的一个矩形区域控件占据窗口的全部或者部分应用程序的视图使用至少一个控件控件可以处理用户的输入事件键盘事件鼠标事件第四十四页,共七十八页。CoeControl是所有控件的基类被派生类直接调用的函数SetRect()CreateWindowL()被派生类重载的函数OfferKeyEventL()Draw()所拥有的函数可以分为以下三类初始化Drawing用户输入处理第四十五页,共七十八页。初始化classCAbcContainer:publicCCoeControl{public://ConstructorsanddestructorvoidConstructL(constTRect&aRect); ~CAbcContainer();private://FunctionsfrombaseclassesvoidSizeChanged(); voidDraw(constTRect&aRect)const; };voidCAbcContainer::ConstructL(constTRect&aRect){CreateWindowL(); SetRect(aRect);ActivateL();}第四十六页,共七十八页。初始化classCAbcContainer:publicCCoeControl{public://ConstructorsanddestructorvoidConstructL(constTRect&aRect); ~CAbcContainer();private://FunctionsfrombaseclassesvoidSizeChanged(); voidDraw(constTRect&aRect)const; };voidCAbcContainer::ConstructL(constTRect&aRect){CreateWindowL(); SetRect(aRect);ActivateL();}第四十七页,共七十八页。DrawingvirtualvoidDraw(constTRect&aRect)const;负责产生控件的图形化外观重要提示基类中的该函数为空,在派生类中如果不实现该函数的话控件将不可见该方法由应用程序框架调用,不要自己调用该函数方法是const,意味着你在Draw()中不能更改任何成员变量,或者调用任何不是const的函数。该函数不允许leave,因此你必须用TRAP封装可能leave的函数第四十八页,共七十八页。Draw()voidCAbcContainer::Draw(constTRect&aRect)const{CWindowGc&gc=SystemGc();gc.SetPenStyle(CGraphicsContext::ENullPen);gc.SetBrushColor(KRgbDarkBlue);gc.SetBrushStyle(CGraphicsContext::ESolidBrush);gc.DrawRect(aRect);//gc.Clear()}第四十九页,共七十八页。图形设备接口GDI抽象类CGraphicsContext(图形上下文)定义了一致的接口派生类CWindowGc和CFbsBitGc具体实现了这些接口可以直接使用CFbsBitGc绘图,但不推荐:第五十页,共七十八页。推荐的绘图方式建议在程序中使用CWindowGc提供的接口第五十一页,共七十八页。图形上下文 CWindowGc&SystemGc()const用来获取当前的图形上下文提供了许多有用的绘图函数画点、线、椭圆、矩形、位图等等改变画笔/画刷的颜色和风格改变字体设置裁剪区域,原点在某一时刻CWindowGc只能由一个窗口激活voidActivate(RDrawableWindow&aWindow)voidDeactivate()第五十二页,共七十八页。控件的重绘(redraw) 更新在屏幕上的显示两种类型系统发起的windowserver我们“必须”重绘控件应用程序发起的内部状态改变我们“想要”重绘控件第五十三页,共七十八页。系统发起的重绘 当windowserver检测到可能使一个区域无效的事件对话框/菜单不再需要时启动一个GUI程序时发送redraw消息给拥有窗口的应用程序应用程序通过CONE发送消息给相关的控件调用控件的Draw()函数第五十四页,共七十八页。应用发起的重绘 通常是某个内部状态改变的结果实现方法有以下几种:Invalidate控件窗口的某部分,让windowserver发送一个redraw消息请求CONE立即重绘整个控件立即重绘控件的某个部分所有的实现方法最终都是调用Draw()函数第五十五页,共七十八页。redraw的类型 立即重绘整个控件CCoeControl::DrawNow()在程序初始化时采用一旦有机会就重绘整个窗口:voidCCoeControl::DrawDeferred()const部分窗口:voidRWindow::Invalidate(constTRect&)立即重绘已知无效的部分voidCSemView::DrawSunNow()const{Window().Invalidate(iSunArea);ActivateGc();Window().BeginRedraw(iSunArea);DrawSun();Window().EndRedraw();DeactivateGc();}第五十六页,共七十八页。更多Draw()的信息参数aRect指定重绘的区域相对于控件的原点(左上角)对于简单控件,通常重绘整个控件对于复合控件,只重绘部分控件防止屏幕闪烁只重绘位于无效区域的部分不要短时间内多次重绘某个区域尽量避免大面积的重绘第五十七页,共七十八页。处理按键事件控件能够检测并处理按键事件按键事件的处理是独立于资源文件定义的热键处理之外的UI框架已经实现了大部分的按键处理典型应用导航键选择键第五十八页,共七十八页。CONE控件堆栈按键事件由系统通告给对其感兴趣的控件在一个特殊的数据结构(CONE控件堆栈)中登记感兴趣的控件系统给控件发送OfferKeyEventL事件CONE控件堆栈中的控件被一一通告事件的发生,直至某个控件宣称接收了该事件控件按优先级被通告事件的发生控件必须告知系统是否接收了该事件如果没有任何控件宣称接收一个事件,则最后将由AppUi在它的CMyAppUi::HandleKeyEventL()中处理该事件第五十九页,共七十八页。AppUi对按键事件的处理在CONE控件堆栈中登记控件voidCtestAppUi::ConstructL(){BaseConstructL();iAppContainer=new(ELeave)CtestContainer;iAppContainer->SetMopParent(this);iAppContainer->ConstructL(ClientRect());AddToStackL(iAppContainer);iAppContainer2=new(ELeave)CtestContainer2;iAppContainer2->SetMopParent(this);iAppContainer2->ConstructL(ClientRect());AddToStackL(iAppContainer2);}在析构的时候将控件从CONE控件堆栈中注销CtestAppUi::~CtestAppUi(){if(iAppContainer){RemoveFromStack(iAppContainer);deleteiAppContainer;}}第六十页,共七十八页。CCoeControl对按键事件的处理TKeyResponseOfferKeyEventL(constTKeyEvent&aEvent,TEventCodeaType)TKeyResponseCMyGameView::OfferKeyEventL(constTKeyEvent&aKeyEvent,TEventCodeaType){switch(aType){caseEEventKey:if(aKeyEvent.iScanCode==EStdKeyNkp5||aKeyEvent.iScanCode==EStdKeyDevice3){ iMyGameEngine->Fire();returnEKeyWasConsumed;}break;caseEEventKeyDown:…caseEEventKeyUp:…}returnEKeyWasNotConsumed;}第六十一页,共七十八页。点击事件的处理60系列并不支持笔写输入但模拟器支持笔的点击voidHandlePointerEventL(constTPointerEvent&)第六十二页,共七十八页。复合控件compoundcontrol包含其它控件的控件有时也称container,容器为什么要用复合控件共享主控件的现有窗口重用控件系统控件(CEikLabel)自己的控件(CMyInfoControl)可以选择性地重绘子控件第六十三页,共七十八页。容器(主控件)的责任创建窗口只为主控件创建窗口子控件重用该窗口创建和删除子控件在主控件中定义成员变量在析构函数中删除子控件摆放子控件设置自己的大小摆放子控件第六十四页,共七十八页。CCoeControl&Windows创建一个新窗口CreateWindowL()为主控件所拥有为子控件所共享重用现有的窗口SetContainerWindowL(constCCoeControl&aContainer)子控件调用该函数减少与windowserver的c/s交互}第六十五页,共七十八页。创建子控件在容器的第二阶段构造函数中创建子控件,并让它们重用容器的窗口voidCtestContainer::ConstructL(constTRect&aRect){CreateWindowL();//创建主窗口iLabel=new(ELeave)CEikLabel;iLabel->SetContainerWindowL(*this);iLabel->SetTextL(_L("ExampleView"));iToDoLabel=new(ELeave)CEikLabel;iToDoLabel->SetContainerWindowL(*this);iToDoLabel->SetTextL(_L("AddYourcontrols\nhere"));SetRect(aRect);ActivateL();}第六十六页,共七十八页。通告给CONE相应的信息告诉CONE拥有的子控件的数目TIntCtestContainer::CountComponentControls()const缺省的实现返回0返回子控件的指针CCoeControl*CtestContainer::ComponentControl(TIntaIndex)const用来依次对所有的子控件执行操作第一个控件的index为0,顺序通常不是很重要如果忘记重载上述两个函数,则子控件依然存在,但无法显示,因为CONE不知道我们的容器有几个子控件第六十七页,共七十八页。复合控件的绘图重绘容器时也重绘了子控件首先调用容器的Draw()然后调用子控件的Draw()CONE利用CountComponentControls()和ComponentControl(TIntaIndex)依次调用自控件的Draw()防止闪烁如果子控件覆盖了整个容器的区域,则无须为容器提供Draw(),否则会重绘两次同一区域,产生闪烁只重绘没有被子控件覆盖的区域设置裁剪区域voidSetClippingRect(constTRect&aRect)TintSetClippingRegion(constTRegion&aClippingRegion)TRegionFix<10>clippingRegion;clippingRegion.Clear();clippingRegion.AddRect(Rect());clippingRegion.SubRect(iSubControl1);//裁剪掉该子控件占用的区域clippingRegion.SubRect(iSubControl2);第六十八页,共七十八页。转发按键事件只有容器被压入CONE控件堆栈由AppUi来将其压栈必须转发按键事件给子控件具体实现TKeyResponseCMainControl::OfferKeyEvent(..){ if(aType!=EEventKey)return; returniSubContro

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论