小糊涂学symbian日记(一)作者:huwell发表日期:2003年8月30日阅读次数:589术语:AvkonSeries60extensionsandmodificationstoSymbian'sUikonandotherpartsoftheSymbianOSApplicationFrameworkSymbian中的应用程序通常分为两个部分,engine和UI,如此的划分增加了可维护性和灵活性,engine就好象是程序的核心,它主要处理运算和数据,而UI(应该是UserInterface)主要处理数据的显示和所有行为(操作行为应该是)。engine不谈,它是程序起作用的灵魂,这个是因程序而异的,我们来看应用程序外观,它可以分为三种体系结构:一、传统的symbianOS控制体系结构二、基于对话框的体系结构三、视图体系结构看看好象跟MFC搞的似的,也有个View和Dialog,不过也是Symbian就是用C++写的,面向对象特性非常好。运用什么样的界面取决于程序和界面布局的需要,就不多说了。只是不管你使用哪种,都是从一个基类继承而来的,就好象是CView一样。[传统SymbianOS应用程序的体系结构]传统意义上,SymbianOS应用程序是在CCoeControl类的基础上派生出我们自己的viewcontrols,这些都存放在应用程序的controlstack中,也就是我们应用程序的视图。这些controls会根据应用程序的需要来创建释放或显示隐藏,以产生相应的操作。[Dialog体系结构]如果主体应用是对话框,那我们更应该使用这样的体系结构,使用dialogs的好处是我们光可以靠改变resource文件来修改内容和布局,而不需要重新编译那c++代码。注意,如果不小心规划,那嵌套的对话框将耗去大量的堆栈空间。另外,如果dialog体系结构被用于主要视图,那建议讲其设计为非模态对话框。(它不垄断用户的输入,用户打开非模态对话框后,仍然可以与其它界面进行交互。)如果你要生成一个主界面对话框,要求是满屏,并提供多页设计,那应该包括如下features:RESOURCEDIALOGr_dlgapp_main_dialog{flags=EEikDialogFlagNoDrag|EEikDialogFlagNoTitleBar|EEikDialogFlagFillAppClientRect|EEikDialogFlagCbaButtons|EEikDialogFlagModelss;buttons=r_dlgapp_softkeys_options_home;pages=r_dlgapp_main_pages;}如果要创建一个对话框应该如下:voidCDlgappAppUi::ConstructL(){BaseConstructL();iAppView=new(ELeave)CDlgAppMainView;iAppView-ExecuteLD(R_DLGAPP_MAIN_DIALOG);AddToStackL(iAppView);}ExecuteLD()在调用后立即返回,并且对话框必须要加到controlstack中——使用AddToStack函数,因为非模态对话框不会自己处理这些。[View体系结构]使用view的应用程序每次只能有一个活动的view,当另一个view要激活时,当前的view就要被释放。当一个view被释放后,所以的菜单,对话框以及包含的应用都将被关闭。每个view都被当作一个应用UI对待,它必须提供一个Id()函数以便为系统所标识,它也要重载DoActivateL(),DoDeactivate(),HandleForegroundEventL(),HandlCommandL()和HandleStatusPaneSizeChange()函数以处理各种事件。下面一个个的看DoActivateL()当客户端要求你的view激活时,它就要被调用。client可能发送消息参数给你的view,如果你的view已经是激活了,那只有当client明确要求再次激活时才被调用,所以你的DoActivateL()实现得应付这种情况,ie已经激活了view。如果你不打算显示view或者你的view不想处理任何消息,那一个简单的检查和return即可。DoDeactive()这个函数当你的view被注销时调用,view被注销时通常有两种情况:一是你的应用程序要退出了,二是相同程序里另一个view要被激活。这个函数很重要,咱们可不能忘记了:)HandleForegroundEventL()这个函数主要是在你的view被激活时调用(即在DoActivateL()和DoDeactivate()之间被调用)。当你的view在前台时,它将是HanleForegroundEvent(ETrue),当你的view移出前台时,它将为HandleForegroundEvent(EFalse),只有当前台状态确实改变时这个函数才会被调用。HandleCommandL()当view菜单产生一个命令后本函数将被调用。HandleStatusPaneSizeChange()当client的尺寸由于statuspane而改变时,本函数被调用了就。下面是一个view在接受事件的典型调用顺序1.DoActivateL()2.HandleForegroundEventL(ETrue)3.HandleForegroundEventL(EFalse)4.DoDeactivate()其中一对HandleForegrounEventL在view被激活的过程中会发生多次调用。而DoActivateL()在DoDeactivate()被调用前可能会被多次调用。ViewResources如果你要使用view来显示pages,那唯一的途径是创建出自己的AVKON_VIEW资源,里面有自己的CBA和菜单,把这个资源的id传递给view的BaseContructL()函数即可。RESOURCEAVKON_VIEWr_viewapp_view1{hotkeys=r_viewapp_hotkeys;menubar=r_viewapp_view1_menubar;cba=R_AVKON_SOFTKEYS_OPTIONS_BACK;}注意如果没有给定的menubar资源,那就会使用确省的系统menubarConstruction下面这个例程是用的AppUIobject'sConstructL来构造出view的,使用了AddView来登记,最后把第一个创建的view做为缺省的view了:voidCMyViewArchAppUi::ConstructL(){BaseConstructL();CMyViewArchAppView1*view1=new(ELeave)CMyViewArchAppView1;CleanupStack::PushL(view1);view1-ConstructL();AddViewL(view1);//Addview1toCAknAppUi;transfersownershipCleanupStack::Pop();CMyViewArchAppView2*view2=new(ELeave)CMyViewArchAppView2;AddViewL(View2);//transferownershiptoCAknAppUiCleanupStack::Pop();CMyViewArchAppView3*view3=new(ELeave)CMyViewArchAppView3;AddViewL(View2);//transferownershiptoCAknAppUiCleanupStack::Pop();SetDefaultViewL(*view1);.......(morecode)要让view发挥作用(注意,一个view自身是没有绘图能力的),它必须拥有得到一个从CCoeControl派生的containers,譬如classCMyViewArchAppView1Container:publicCCoeControl,MCoeControlObserver下面这个例程将展现编程者自己的CAknView派生类classCMyViewArchAppView1:publicCAknVIew{.....private:CMyViewArchAppView1Container*iVIew;}大家可以看出App里产生了View,View类中有我们必须的Container.当前激活的view在HandleCommandL()处理命令,这些是自定义功能键和菜单所生成的命令。voidCMyAppView1::HandleCommandL(TIntaCommand){switch(aCommand){caseEMyAppCmdSwitchView:AppUi()-ActivateLocalViewL(KView2Id);break;caseEAknSoftKeyOk:{......break;}caseEAknSoftKeyBack:{((MEikCommandObserver*)AppUi())-ProcessCommandL(EEikCmdExit);break;}default:AppUi()-HandleCommandL(aCommand);break;}}LocalViewSwitching如果你要切换view,你得提供view的UID//Nowswitchtheviewtoview2iAvkonViewAppUi-ActivateLocalViewL(TUid::Uid(2));事实上,每个view都有自己的菜单系统,如果你要使用它,应当在AVKON_VIEW资源结构中设置,前面已经讲过了。而且不管怎么说,如果要使用系统菜单,它的内容在切换之前是一定要更新一次的。//SwitchtoanewmenusystemforthenewviewiEikonEnv-AppUiFactory()-MenuBar()-SetMenuTitleResourceId(R_MY_VIEW_ARCH_APP_VIEW2_MENU);//Nowswtichtheviewtoview2如果要进行远程的视图切换,那就要调用CCoeAppUi::ActivateViewL()函数,并传递了一个包含目标应用程序UID和目标视图UID的TVwsViewIdLeaverecoveryAvkon视图体系结构在DoActivateL()退出时会有个自动的回复机制。系统会调用DoDeactivate()在当前view离去时,回复前一个view,并把用户带到之前他们所在的地方。如果程序并没有前一个view的存在,那它就会退出,如果程序前个view就是当前的view(也就是说他们是重激活的),则应用程序会试图恢复缺省的view.说了这么多,那我们在什么情况下采用合适的体系结构那?下面的内容将会有所帮助。使用传统的SymbianOS体系结构,你要花费大量的时间研究代码是怎么工作的,但大部分交互和错误处理的引擎代码都是现成,可以降低你的开发难度。Doyouhaveanacyclicgraphshapednavigationstructure?如果你视图程序中的navigation能够asanacyclicgragh,那最好使用dialog体系结构。Arealltheapplicationscreensdialoglike?如果你的应用程序想使用对话框,那建议你使用dialog体系结构,注意如果要有一个选择列表,那最好写成包含在dialog中的选择列表。Doestheapplicationhavemultipleviewsormodes,whichdealwithdifferentsortsofdataatthetoplevel?如果是这样,那最好使用传统或view体系结构。Doexternalappli