<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog336280.html" frameborder="0" width="336" scrolling="no" height="280"></iframe>
Author:孙东风 2007-04-08
①MVC架构
我们知道,在软件编写过程中一直提倡"数据"和"界面"的高度分离,Symbian中也是这么做的。
首先,基于"传统EIKON框架"的应用程序会产生App、Document、AppUi、Container四个类,其中App是应用程序的"启动类",Document基础上没什么用处,而Symbian中大量的处理工作都放在了AppUi和Container类中。AppUi就象是一个交通枢纽负责南来北往的数据,一般来说,在Symbian的程序中都会新建一个Engine的"引擎类"来负责程序的逻辑处理,而AppUi就是负责把"引擎类"中数据的处理结果、数据的变化及时更新到Container中。
下面是我写的一个Symbian游戏引擎中AppUi二阶段构造函数中的代码:
void CMegajoyAppUi::ConstructL() { BaseConstructL(); iAppContainer = new (ELeave) CMegajoyContainer; iAppContainer->SetMopParent( this ); iAppContainer->ConstructL( ClientRect() ); AddToStackL( iAppContainer ); iMainEngine = new (ELeave) CMegajoyMain(this); iLancher = CIdle::NewL( CActive::EPriorityIdle ); iLancher->Start(TCallBack(Start,this)); }
|
从中可以看到,上面AppUi的二阶段构造函数中同时产生了iAppContainer和iMainEngine实例,并且我们把一个AppUi的this指针传递给了"引擎类"。我们知道,做为一种GUI程序,无非就是用户界面的交互(包括键盘、鼠标等)和引擎处理数据。而Symbian中提供给用户界面交互接口的正是AppUi类,它里面的HandleCommandL()负责处理用户的菜单操作,HandleKeyEventL()负责处理用户的键盘操作,DoExit()负责用户的退出操作等。那么,一切数据的处理和界面的显示都经过AppUi这个中枢就显得很有必要了!
试想一下,用户按下某个键,这个键从传递到AppUi的HandleKeyEventL()函数里(当然也有可能是其上某个控件的消息响应函数中,这里忽略控件栈的讨论),而AppUi调用iMainEngine来处理这个按键数据,从而进行必要的逻辑转变,比如从一个界面跳转到另一个界面,那么iMainEngine里就会把一个全局的界面ID从一种状态转换到另一种状态,但是这种状态的切换会伴随着界面的变化,界面上也需要体现出这种变化,而界面的绘制是在iAppContainer中完成的,iAppContainer又是在AppUi中构造并初始化的。
就是说我们的iAppContainer和iMainEngine需要一种类似通信的机制,让iAppContainer能及时的知道iMainEngine中某个全局变量状态的变化并及时做出界面上的更新。
问题到了这里已经很明显,iAppContainer和iMainEngine都在AppUi类里,而这两个实例对象之间需要一种类似通信的机制。
解决这种两个对象实例之间通信问题的非我们的"Observer模式"莫属!下面我们就来看看Symbian中的"Observer模式"。
②Observer模式
Observer模式提供一种类与类之间传递消息的机制,当某个事件发生或状态改变时,拥有观察者的类可以向另一个类发送某个消息,这样另一个类可以根据变化做出相应的处理。呵呵,是不是觉得简直是为了我们Symbian量身定做的一个模式?
在我们的Symbian架构中iMainEngine中会有事件发生(因为AppUi类把事件传递给它了)或状态改变(例如全局界面ID的变化),那么我们的iMainEngine中就需要有一个"观察者"的实例以便向iAppContainer发送消息,iAppContainer可以根据变化做出相应的处理。
这样我们就可以定义一个消息接口的类,这个类是抽象的,内部的函数也都是纯虚函数(只提供接口),下面是我写的Symbian游戏引擎中观察者接口(或者说消息接口)的定义:
class MMegajoyAction{ public: // Graphic functions virtual void FlipBackBuffer(void)=0; virtual void BitBlt(TInt iBltType, CExtendedBitmap &iBitmap, const TPoint &aPosition)=0; virtual void DoExit(void)=0; virtual TBool ReadIniFile(TUid iInfo, void *ptr, TUint &size)=0; virtual TBool CheckIniFile(TUid iInfo)=0; virtual void WriteIniFile(TUid iInfo, void *ptr, TUint size)=0; virtual void RemoveIniData(TUid iInfo)=0; }; |
因为iMainEngine和iAppContainer都在AppUi中,那么AppUi就成为它们之间消息中转的最佳选择了,让AppUi类实现这个接口MMegajoyAction,并传递AppUi的this指针到iMainEngine,而iMainEngine中也有个MMegajoyAction的实例对象MMegajoyAction *Actions;从而当iMainEngine中有事件发生(因为AppUi类把事件传递给它了)或状态改变(例如全局界面ID的变化)时直接调用Actions传递消息到AppUi,AppUi中通过实现的具体接口再调用iAppContainer中的方法,实现了iMainEngine和iAppContainer之间的通信机制。
如下是我写的Symbian游戏引擎中AppUi对观察者接口的实现
void CMegajoyAppUi::FlipBackBuffer(void){ iAppContainer->FlipBackBuffer(); } void CMegajoyAppUi::BitBlt(TInt iBltType, CExtendedBitmap &iBitmap, const TPoint &aPosition){ switch(iBltType){ case BLTTYPE_NORMAL: iAppContainer->BlitToBackBuffer(iBitmap, aPosition); break; case BLTTYPE_MASKED: iAppContainer->BlitToBackBufferMasked(iBitmap, aPosition); break; } } void CMegajoyAppUi::DoExit(void){ Exit(); } TBool CMegajoyAppUi::ReadIniFile(TUid iInfo, void *ptr, TUint &size){ TInt r; TBool result = EFalse; RFs fs; fs.Connect(); CleanupClosePushL( fs ); RDictionaryReadStream rdsIniFile; CDictionaryStore *cdIniFile = Application()->OpenIniFileLC(fs); if (cdIniFile->IsPresentL(iInfo)){ rdsIniFile.OpenLC(*cdIniFile, iInfo); TPtr8 buf((TUint8*)ptr, size); TRAP(r, rdsIniFile.ReadL(buf)); CleanupStack::PopAndDestroy(); // rdsIniFile result = ETrue; } CleanupStack::PopAndDestroy( 2 ); // fs, cdIniFile return result; } TBool CMegajoyAppUi::CheckIniFile(TUid iInfo){ TBool result = EFalse; RFs fs; fs.Connect(); CleanupClosePushL( fs ); RDictionaryReadStream rdsIniFile; CDictionaryStore *cdIniFile = Application()->OpenIniFileLC(fs); result = cdIniFile->IsPresentL(iInfo); CleanupStack::PopAndDestroy( 2 ); // fs, cdIniFile return result; } void CMegajoyAppUi::WriteIniFile(TUid iInfo, void *ptr, TUint size){ TInt r; RFs fs; fs.Connect(); CleanupClosePushL( fs ); RDictionaryWriteStream rdsIniFile; CDictionaryStore *cdIniFile = Application()->OpenIniFileLC(fs); rdsIniFile.AssignLC(*cdIniFile, iInfo); TPtr8 buf((TUint8*)ptr, size, size); TRAP(r, rdsIniFile.WriteL(buf)); rdsIniFile.CommitL(); CleanupStack::PopAndDestroy(); cdIniFile->CommitL(); CleanupStack::PopAndDestroy( 2 ); } void CMegajoyAppUi::RemoveIniData(TUid iInfo){ RFs fs; fs.Connect(); CleanupClosePushL( fs ); RDictionaryWriteStream rdsIniFile; CDictionaryStore *cdIniFile = Application()->OpenIniFileLC(fs); cdIniFile->Remove(iInfo); cdIniFile->CommitL(); CleanupStack::PopAndDestroy( 2 ); } |
可见,接口的实现也分为两部分
virtual void FlipBackBuffer(void)=0;
virtual void BitBlt(TInt iBltType, CExtendedBitmap &iBitmap, const TPoint &aPosition)=0;
这两个接口属于界面的更新,AppUi直接调用iAppContainer中的函数进行消息的传递,而其它几个数据保存、读取、删除的操作都是在AppUi本地完成。
而下面的用户接口消息(按键、菜单等操作)则直接传递消息给iMainEngine进行处理:
TKeyResponse CMegajoyAppUi::HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) { if(iMainEngine) return iMainEngine->DoKeyEvent(aKeyEvent, aType); return EKeyWasNotConsumed; } void CMegajoyAppUi::HandleCommandL(TInt aCommand) { switch ( aCommand ) { case EAknSoftkeyOk: iMainEngine->ExternalEvent(EVT_SELECT); break; case EAknSoftkeyBack: iMainEngine->ExternalEvent(EVT_ESCAPE); break; case EEikCmdExit: iMainEngine->ForceQuit(); Exit(); break; default: break; } } |
相关推荐
Symbian中的游戏编程;Symbian中的游戏编程Symbian中的游戏编程Symbian中的游戏编程
Symbian塞班软件破解入门资料,新手值得一看~
Symbian S60 V3软件Symbian S60 V3软件Symbian S60 V3软件Symbian S60 V3软件Symbian S60 V3软件Symbian S60 V3软件Symbian S60 V3软件Symbian S60 V3软件打包下载 我佛痴悲 石祖江Symbian S60 V3软件打包下载 我佛...
Symbian S60 V3软件打包下载Symbian S60 V3软件打包下载Symbian S60 V3软件打包下载Symbian S60 V3软件打包下载Symbian S60 V3软件打包下载Symbian S60 V3软件打包下载Symbian S60 V3软件打包下载Symbian S60 V3软件...
s60v3 热门软件合集。S60 V3塞班软件合集软件.rar。包括QQ微信浏览器等等,想要的可以下载。
全书共分为21章,分别介绍了Symbian OS中的类命名约定、异常退出、清除栈、两段构造、描述符、良好的描述符风格、动态的数组与缓冲区、使用活动对象的事件驱动多任务、活动对象、Symbian OS的线程与进程、客户/...
须安装py平台,想提取源代码可以用sis编辑器解包。。
SYMBIAN OS C++ 高效编程教程
推荐-symbian塞班软件开发工程师培训班实施方案 精品.pdf
塞班手机万用加密软件 ET私密锁是一款强力软件私密加密工具,软件使用前加密,不管是你的名片夹,通讯记录,短信,照片,音乐,多媒体资料,文件管理,程序管理,记事本,备忘录,包括第三方软件,游戏,充分做到物...
Symbian OS:线程编程中文版,值得保留哦.
诺基亚塞班智能手机可用SISX软件和JAVA软件等三十多个打包。
可以随意的对塞班s60v3以上的软件进行签名,去签名。操作简单。绿色免安装
诺基亚非智能手机,只能使用jar软件,但是在导入手机证书后就可以使用签名软件(软件设置里--“总是允许”可以选择),使用这时先安装JAVA环境,然后用JAR处理器对jar软件进行处理(不处理,可能会无法生成JAD文件)...
手机软件塞班的
我们塞班也有跑分软件了,jar格式的,结果仅供参考啊!
symbian塞班软件开发工程师培训班实施方案.doc
塞班s60v1和v2软件游戏sis解压工具,电脑端,解压后复制到塞班一代或二代手机内存卡对应的文件夹里,即可完美运行软件和游戏
《Symbian OS C++ 高效编程》 源码 《Symbian OS Explained》 源码
Symbian系统平台实时核心编程,Symbian系统平台实时核心编程