Symbian学习笔记(2)转载

开发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。

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    CiMusicViewMusic* view1 = new (ELeave) CiMusicViewMusic;   

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    CleanupStack::PushL( view1 );

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    view1->ConstructL();

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    AddViewL( view1 );      // transfer ownership to CAknViewAppUi

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    CleanupStack::Pop();    // view1

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客   

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    CiMusicViewFavt* view2 = new (ELeave) CiMusicViewFavt;   

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    CleanupStack::PushL( view2 );

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    view2->ConstructL();

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    AddViewL( view2 );      // transfer ownership to CAknViewAppUi

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    CleanupStack::Pop();    // view2

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客   

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    CiMusicViewWeb* view3 = new (ELeave) CiMusicViewWeb;   

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    CleanupStack::PushL( view3 );

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    view3->ConstructL();

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    AddViewL( view3 );      // transfer ownership to CAknViewAppUi

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    CleanupStack::Pop();    // view3

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客   

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    this->ActivateLocalViewL(KViewMusicId);

5)有多个以工程名+View命名的类,派生于CAknView类。它负责分担AppUi部分事件的处理,所以,它也有HandleCommandL函数。

此外,它的DoActivateL和DoDeactivate两个函数在当前视图激活或失活时被调用,需要重载一下。

在激活时,需要创建视图对应的Container类,并且调用Container的SetMopParent为自己,还要在上层的AppUi中将这个Container加入栈中。一般代码如下:

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    iContainer = new (ELeave) CiMusicContainerFavt;

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    iContainer->SetMopParent(this);       

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    iContainer->ConstructL( AppUi()->ApplicationRect() );

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    iContainer->listType=type;

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    AppUi()->AddToStackL( *this, iContainer );

注意,它的AppUi()可以得到它的上层的AppUi对象指针。

失活时则正好相反,需要

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客if ( iContainer )

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客Symbian学习笔记(2)转载 - jianhai1229 - 水木博客...{

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客AppUi()->RemoveFromViewStack( *this, iContainer );

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客}

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客delete iContainer;

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客iContainer = NULL;

6)有多个以工程名+Container命名的类,派生于CCoeControl并实现接口MCoeControlObserver,所以它的行为与常规模式中的Container类似。

这种模式可以有效地组织应用程序,根据应用的多个功能界面切割成数个模块(视图)。由多个AppView来分担AppUi中的事件处理,负责自己这个视图下的具体行为与显示。

各个视图之间的切换也很简单:

STATIC_CAST(CiMusicAppUi*,iCoeEnv->AppUi())->ActivateLocalViewL(KViewMusicId);

[补充]

三 比较两种模式

有些教材还提出过对话框模式,但是我觉得那似乎不太实用,也没注意过它的结构组成。

对比上述两种架构模板,很显然,第二种基于视图的模板应该更有实用性一点,除非程序实在简单。

不过,这里的“视图”很容易让人产生误解。一般我们说MVC的时候,模型-视图-控制器,但是这里的AppView其实对应的控制器,而Container对应的则是视图。

所以在新的SDK里,第一种模板中由向导生成的工程中源于CCoeControl的类名改成了AppView,对应继承于CAknAppUi控制器的类名叫AppUi。因为我没有看到多视图的工程生成的代码,如果这样的话,估计也应该对应的改一下吧。与2nd.不同的是,3rd.支持svg格式的可缩放图标(最大好处在于一个图标搞定,以前用bmp时为了应用程序的菜单图标得要做四个小图标)。而且,现在有了一种新的图像打包格式mif(这名字咋跟BREW中那个MIF一样啊)。虽然还支持以前的MBM方式但是不建议使用了。

要在应用程序中增加图像图标资源,过程如下:

第一步,先将要加入的图像放在工程的/gfx目录下,如:

qgn_menu_DemoUI.svg

splash2.bmp

前面一个就是应用程序图标(可以修改它)。

第二步,修改/group目录下的Icons_scalable_dc.mk文件,不知道为什么,工程向导生成的这个文件相当不完整,郁闷

TARGETDIR=$(ZDIR)\resource\apps

ICONTARGETFILENAME=$(TARGETDIR)\DemoUI_0xE8656D58.mif

HEADERDIR=C:\Symbian\workspace\DemoUI\inc

HEADERFILENAME=$(HEADERDIR)\DemoUI.mbg

上面的targetdir是原有的,下面的headerdir是我加上的,因为我需要一个mbg文件(以前旧方式也有这个头文件)。

RESOURCE :   

    mifconv $(ICONTARGETFILENAME) /h$(HEADERFILENAME) \

        /c32,8 $(ICONDIR)\qgn_menu_DemoUI.svg \

        /c24 $(ICONDIR)\splash2.bmp

       

RELEASABLES :

    @echo $(HEADERFILENAME)&& \

    @echo $(ICONTARGETFILENAME)

主要是那个mifconv的参数,加上/h生成mbg头文件,注意这里的/c32,8 表示我们只提供一个svg文件但是将它的8bit图像作为它的mask,比

原来的方式简单多了,当然你也可以新做一个图像作为mask。

[补充@2008-03-14]

昨天这个例子只在模拟器上成功了,真机失败,无法加载bmp图像。

后来出编译时的控制台输出发现,它只把svg图片放在mif文件中,而bmp图片仍会放入一个同名的mbm文件中。所以我们还得修改pkg文件,让mbm也打包进sisx中:

"$(EPOCROOT)Epoc32\data\z\resource\apps\DemoUI_0xE8656D58.mif" -"!:\resource\apps\DemoUI_0xE8656D58.mif"

"$(EPOCROOT)Epoc32\data\z\resource\apps\DemoUI_0xE8656D58.mbm" -"!:\resource\apps\DemoUI_0xE8656D58.mbm"

代码中则无所谓了,因为AknIconUtils::CreateIconL()会自动判断是去mif还是mbm中读取图像资源。

第三步,先把上面的改完后,编译一下,就能得到mif文件和mbg文件了。

下面在container中显示这个图像splash2.bmp,先修改.h文件,增加两个CFbsBitmap。

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客private:

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客        CFbsBitmap*     iBkImage;

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客        CFbsBitmap*     iBkImageMask;

修改cpp文件,如此加载和显示:

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客_LIT(KMbmFileName,"\resource\apps\DemoUI_0xE8656D58.mif");

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客const TInt KMyIconMaxWidth(100);

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客const TInt KMyIconMaxHeight(100);

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客...

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客void CDemoUIAppView::ConstructL( const TRect& aRect )

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客Symbian学习笔记(2)转载 - jianhai1229 - 水木博客...{

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客...

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客TFileName fullname(KMbmFileName);

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客CompleteWithAppPath(fullname);

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客   

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客iBkImage=AknIconUtils::CreateIconL(fullname,EMbmDemouiSplash);

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客...

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客}

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客...

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客void CDemoUIAppView::Draw( const TRect& aRect ) const

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客Symbian学习笔记(2)转载 - jianhai1229 - 水木博客...{

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    CWindowGc& gc = SystemGc();

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    TRect drawRect( Rect());

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    gc.Clear( drawRect );

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客   

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客    gc.BitBlt(TPoint(0,0),iBkImage);

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客...

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客}

其实这里与旧方式差不多了,但是原来的那个iBkImage->Load()方法已经不管用了,只能用AknIconUtils提供的这个方法CreateIconL。

另外,如果是加载SVG呢,其实也一样的,如果同时加载mask呢?也一样。例如:

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客AknIconUtils::CreateIconL(iBkImage, iBkImageMask, fullname, EMbmDemouiQgn_app_demoui, EMbmDemouiQgn_menu_demoui_mask);

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客AknIconUtils::SetSize(iBkImage, TSize(KMyIconMaxWidth, KMyIconMaxHeight));

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客AknIconUtils::SetSize(iBkImageMask, TSize(KMyIconMaxWidth, KMyIconMaxHeight));

显示时就这样:

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客TPoint point = TPoint(aRect.Center().iX - (KMyIconMaxWidth/2),aRect.Center().iY - (KMyIconMaxHeight/2));

Symbian学习笔记(2)转载 - jianhai1229 - 水木博客gc.BitBltMasked(point, iBkImage, aRect, iBkImageMask, EFalse);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值