Symbian学习笔记(3)——应用程序框架
2008-10-30 02:47
239 查看
开发symbian的GUI应用是有模板的,用Carbide C++的工程向导可以自动生成程序的基本框架。不过可能与安装的SDK版本有关,我现在只能生成一个AppUi一个Container的常规模板(以前用2nd FP3时还可以生成多个view多个container的视图模板)。
不管是哪一种模板,它们共同的部分是入口函数、Application和Document。即以下三个文件是所有工程都具有的:
1)有一个与工程同名的cpp文件,它只提供了两个全局函数,是程序执行的入口,负责创造Application。这个文件我们不用管它。
2)有一个以工程名+Application命名的类,派生于CAknApplication,它负责创建文档类并提供应用的UID。一般情况下它也不需要我们操心,但是因为它提供了一个函数OpenIniFileLC,如果我们需要在启动程序时加载ini文件中的配置,可以重载它。
3)有一个以工程名+Document命名的类,派生于CAknDocument,它负责创建Ui类,同样一般情况我们不管它,但是它也提供了一个函数OpenFileL,如果需要加载普通文件,也可以重载它。
下面来看看两种模板的不同点吧。
一. 基于CCoeControl的常规模式
这种模式的特点是一个AppUi类并且对应一个Container类。
它在上述三个文件以外,还有下面两个文件:
4)有一个以工程名+AppUi命名的类,派生于CAknAppUi,它主要的工作是负责用户接口(所谓的UI)并且创建Container类,所以它是我们关注的重点之一。
它最重要的成员函数是HandleCommandL,这个函数来自于CEikAppUi类,负责处理各种命名/事件。
有两个函数DynInitMenuBarL和DynInitMenuPaneL,如果需要动态更改菜单的项目,可以重载它们。
HandleKeyEventL函数则可以在需要自己处理键盘事件时重载一下。
此外,这个AppUi还提供一些比较常用的函数,比如:
Document() 可以获取Document对象指针。
Application() 可以获取Application对象指针。
StatusPane() 可以获取状态栏的指针。
Cba() 可以获取控制栏的指针。
5)有一个以工程名+Container命名的类,派生于CCoeControl,它负责内容的展示,也是我们关注的重点。
如果需要在界面上增加控件类类的东西,都是在这个类中实现,总的来说,它负责所有与界面展示相关的东西。
它有一个Draw函数,但是如果我们是通过控件来展示信息,则这个函数里的代码似乎与我们关系不大,除非我们的界面完全是靠画出来的。
另两个函数ComponentControl和CountComponentControls分别获取控件与获取控件个数,在依赖于控件展示的GUI应用中则更为重要。
因为它实现了接口MCoeControlObserver,所以函数HandleControlEventL也需要实现一下。
利用它的成员iCoeEnv可以取到AppUi类的指针,不过需要强制转型一下,如:STATIC_CAST(CiMusicAppUi*,iCoeEnv->AppUi())->...
二. 基于CAknView的MVC模式
这种模式的特点是在AppUi类与Container类之间增加一个AppView的类,即一个AppUi对象,N个AppView和N个Container。
除了公共的三个文件以外,它包括的文件有:
4) 有一个以工程名+AppUi命名的类,派生于CAknViewAppUi类,其实也是间接派生于CAknAppUi类,它的工作职责与常规模式中的AppUi类也基本相同。
唯一的区别在于它不是直接创建Container类,而是创建AppView类,并且是创建多个AppView类。同时它还需要负责将创建的view加入视图栈里AddViewL。
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CiMusicViewMusic* view1 = new (ELeave) CiMusicViewMusic;
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CleanupStack::PushL( view1 );
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
view1->ConstructL();
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
AddViewL( view1 ); // transfer ownership to CAknViewAppUi
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CleanupStack::Pop(); // view1
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CiMusicViewFavt* view2 = new (ELeave) CiMusicViewFavt;
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CleanupStack::PushL( view2 );
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
view2->ConstructL();
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
AddViewL( view2 ); // transfer ownership to CAknViewAppUi
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CleanupStack::Pop(); // view2
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CiMusicViewWeb* view3 = new (ELeave) CiMusicViewWeb;
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CleanupStack::PushL( view3 );
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
view3->ConstructL();
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
AddViewL( view3 ); // transfer ownership to CAknViewAppUi
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CleanupStack::Pop(); // view3
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
this->ActivateLocalViewL(KViewMusicId);
5)有多个以工程名+View命名的类,派生于CAknView类。它负责分担AppUi部分事件的处理,所以,它也有HandleCommandL函数。
此外,它的DoActivateL和DoDeactivate两个函数在当前视图激活或失活时被调用,需要重载一下。
在激活时,需要创建视图对应的Container类,并且调用Container的SetMopParent为自己,还要在上层的AppUi中将这个Container加入栈中。一般代码如下:
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
iContainer = new (ELeave) CiMusicContainerFavt;
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
iContainer->SetMopParent(this);
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
iContainer->ConstructL( AppUi()->ApplicationRect() );
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
iContainer->listType=type;
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
AppUi()->AddToStackL( *this, iContainer );
注意,它的AppUi()可以得到它的上层的AppUi对象指针。
失活时则正好相反,需要
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
if ( iContainer )
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115100645.gif)
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115101126.gif)
...{
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115101145.gif)
AppUi()->RemoveFromViewStack( *this, iContainer );
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115101480.gif)
}
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
delete iContainer;
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
iContainer = NULL;
6)有多个以工程名+Container命名的类,派生于CCoeControl并实现接口MCoeControlObserver,所以它的行为与常规模式中的Container类似。
这种模式可以有效地组织应用程序,根据应用的多个功能界面切割成数个模块(视图)。由多个AppView来分担AppUi中的事件处理,负责自己这个视图下的具体行为与显示。
各个视图之间的切换也很简单:
STATIC_CAST(CiMusicAppUi*,iCoeEnv->AppUi())->ActivateLocalViewL(KViewMusicId);
[补充]
三 比较两种模式
有些教材还提出过对话框模式,但是我觉得那似乎不太实用,也没注意过它的结构组成。
对比上述两种架构模板,很显然,第二种基于视图的模板应该更有实用性一点,除非程序实在简单。
不过,这里的“视图”很容易让人产生误解。一般我们说MVC的时候,模型-视图-控制器,但是这里的AppView其实对应的控制器,而Container对应的则是视图。
所以在新的SDK里,第一种模板中由向导生成的工程中源于CCoeControl的类名改成了AppView,对应继承于CAknAppUi控制器的类名叫AppUi。因为我没有看到多视图的工程生成的代码,如果这样的话,估计也应该对应的改一下吧。
引用自:http://www.sf.org.cn/Article/lumen/200803/20903.html
不管是哪一种模板,它们共同的部分是入口函数、Application和Document。即以下三个文件是所有工程都具有的:
1)有一个与工程同名的cpp文件,它只提供了两个全局函数,是程序执行的入口,负责创造Application。这个文件我们不用管它。
2)有一个以工程名+Application命名的类,派生于CAknApplication,它负责创建文档类并提供应用的UID。一般情况下它也不需要我们操心,但是因为它提供了一个函数OpenIniFileLC,如果我们需要在启动程序时加载ini文件中的配置,可以重载它。
3)有一个以工程名+Document命名的类,派生于CAknDocument,它负责创建Ui类,同样一般情况我们不管它,但是它也提供了一个函数OpenFileL,如果需要加载普通文件,也可以重载它。
下面来看看两种模板的不同点吧。
一. 基于CCoeControl的常规模式
这种模式的特点是一个AppUi类并且对应一个Container类。
它在上述三个文件以外,还有下面两个文件:
4)有一个以工程名+AppUi命名的类,派生于CAknAppUi,它主要的工作是负责用户接口(所谓的UI)并且创建Container类,所以它是我们关注的重点之一。
它最重要的成员函数是HandleCommandL,这个函数来自于CEikAppUi类,负责处理各种命名/事件。
有两个函数DynInitMenuBarL和DynInitMenuPaneL,如果需要动态更改菜单的项目,可以重载它们。
HandleKeyEventL函数则可以在需要自己处理键盘事件时重载一下。
此外,这个AppUi还提供一些比较常用的函数,比如:
Document() 可以获取Document对象指针。
Application() 可以获取Application对象指针。
StatusPane() 可以获取状态栏的指针。
Cba() 可以获取控制栏的指针。
5)有一个以工程名+Container命名的类,派生于CCoeControl,它负责内容的展示,也是我们关注的重点。
如果需要在界面上增加控件类类的东西,都是在这个类中实现,总的来说,它负责所有与界面展示相关的东西。
它有一个Draw函数,但是如果我们是通过控件来展示信息,则这个函数里的代码似乎与我们关系不大,除非我们的界面完全是靠画出来的。
另两个函数ComponentControl和CountComponentControls分别获取控件与获取控件个数,在依赖于控件展示的GUI应用中则更为重要。
因为它实现了接口MCoeControlObserver,所以函数HandleControlEventL也需要实现一下。
利用它的成员iCoeEnv可以取到AppUi类的指针,不过需要强制转型一下,如:STATIC_CAST(CiMusicAppUi*,iCoeEnv->AppUi())->...
二. 基于CAknView的MVC模式
这种模式的特点是在AppUi类与Container类之间增加一个AppView的类,即一个AppUi对象,N个AppView和N个Container。
除了公共的三个文件以外,它包括的文件有:
4) 有一个以工程名+AppUi命名的类,派生于CAknViewAppUi类,其实也是间接派生于CAknAppUi类,它的工作职责与常规模式中的AppUi类也基本相同。
唯一的区别在于它不是直接创建Container类,而是创建AppView类,并且是创建多个AppView类。同时它还需要负责将创建的view加入视图栈里AddViewL。
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CiMusicViewMusic* view1 = new (ELeave) CiMusicViewMusic;
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CleanupStack::PushL( view1 );
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
view1->ConstructL();
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
AddViewL( view1 ); // transfer ownership to CAknViewAppUi
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CleanupStack::Pop(); // view1
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CiMusicViewFavt* view2 = new (ELeave) CiMusicViewFavt;
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CleanupStack::PushL( view2 );
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
view2->ConstructL();
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
AddViewL( view2 ); // transfer ownership to CAknViewAppUi
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CleanupStack::Pop(); // view2
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CiMusicViewWeb* view3 = new (ELeave) CiMusicViewWeb;
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CleanupStack::PushL( view3 );
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
view3->ConstructL();
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
AddViewL( view3 ); // transfer ownership to CAknViewAppUi
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
CleanupStack::Pop(); // view3
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
this->ActivateLocalViewL(KViewMusicId);
5)有多个以工程名+View命名的类,派生于CAknView类。它负责分担AppUi部分事件的处理,所以,它也有HandleCommandL函数。
此外,它的DoActivateL和DoDeactivate两个函数在当前视图激活或失活时被调用,需要重载一下。
在激活时,需要创建视图对应的Container类,并且调用Container的SetMopParent为自己,还要在上层的AppUi中将这个Container加入栈中。一般代码如下:
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
iContainer = new (ELeave) CiMusicContainerFavt;
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
iContainer->SetMopParent(this);
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
iContainer->ConstructL( AppUi()->ApplicationRect() );
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
iContainer->listType=type;
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
AppUi()->AddToStackL( *this, iContainer );
注意,它的AppUi()可以得到它的上层的AppUi对象指针。
失活时则正好相反,需要
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
if ( iContainer )
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115100645.gif)
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115101126.gif)
...{
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115101145.gif)
AppUi()->RemoveFromViewStack( *this, iContainer );
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115101480.gif)
}
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
delete iContainer;
![](http://www.sf.org.cn/Article/UploadFiles/200803/20080315115059770.gif)
iContainer = NULL;
6)有多个以工程名+Container命名的类,派生于CCoeControl并实现接口MCoeControlObserver,所以它的行为与常规模式中的Container类似。
这种模式可以有效地组织应用程序,根据应用的多个功能界面切割成数个模块(视图)。由多个AppView来分担AppUi中的事件处理,负责自己这个视图下的具体行为与显示。
各个视图之间的切换也很简单:
STATIC_CAST(CiMusicAppUi*,iCoeEnv->AppUi())->ActivateLocalViewL(KViewMusicId);
[补充]
三 比较两种模式
有些教材还提出过对话框模式,但是我觉得那似乎不太实用,也没注意过它的结构组成。
对比上述两种架构模板,很显然,第二种基于视图的模板应该更有实用性一点,除非程序实在简单。
不过,这里的“视图”很容易让人产生误解。一般我们说MVC的时候,模型-视图-控制器,但是这里的AppView其实对应的控制器,而Container对应的则是视图。
所以在新的SDK里,第一种模板中由向导生成的工程中源于CCoeControl的类名改成了AppView,对应继承于CAknAppUi控制器的类名叫AppUi。因为我没有看到多视图的工程生成的代码,如果这样的话,估计也应该对应的改一下吧。
引用自:http://www.sf.org.cn/Article/lumen/200803/20903.html
相关文章推荐
- Symbian学习笔记(3):应用程序框架
- Symbian学习笔记(3)——应用程序框架
- MFC学习笔记——应用程序框架分析(CWinApp)
- 孙鑫VC学习笔记:第三讲 MFC应用程序框架
- IOS开发学习笔记(五)——多视图应用程序之框架分析
- ASP.NET 2.0高级编程学习笔记-第3章 应用程序和页面框架
- 逐梦旅程学习笔记 DirectX开发入门01:应用程序基本框架
- V4L2应用程序框架学习笔记
- android开发学习笔记(6)android应用程序框架
- GTK+图形化应用程序开发学习笔记(十七)—框架构件、比例框架构件
- GTK+图形化应用程序开发学习笔记(十七)—框架构件、比例框架构件
- Silverlight商业应用程序开发--学习笔记(1) 导航框架 navigationFramework
- 孙鑫VC学习笔记:第三讲 MFC应用程序框架
- 深度学习笔记——深度学习框架TensorFlow(十)[Creating Estimators in tf.contrib.learn]
- 学习笔记_毕向东 Java_集合框架_LinkedList 2014.7.22
- Symbian上往UI框架应用程序发送消息
- Echo 框架学习笔记 1
- SilverLight商业应用程序开发---学习笔记(8)
- bootstrap框架学习笔记
- (五) 畸变矫正—让世界不在扭曲 【计算机视觉学习笔记--双目视觉几何框架系列】