Author:孙东风 2007-04-06
最近总有同行问我Symbian全屏显示的问题,说是参考了网上的方法也无法设置成全屏。其实,归根结底还是不明白Symbian框架的调用机制。这篇文章里我就来彻底研究一下Symbian全屏的机制。
首先,我们可以利用Carbide.vs向导建一个项目,名字就叫"TestScreen",选择基于Eikon的传统控件架构。
那么在CTestScreenAppUi的二阶构造函数里就有如下代码:
void CTestScreenAppUi::ConstructL() iAppContainer = new (ELeave) CTestScreenContainer; AddToStackL(iAppContainer); } |
这里面有很关键的一句,就是我用红色显示的那段代码。它把当前UI的ClientRect()传递给Container类,我们都知道Container类是控件类,负责整个程序的界面显示,那么UI传递给Container的这个ClientRect()到底是什么东东呢?我们看看SDK HELP:
|
|
从Description我们可以看到:ClientRect()获得应用程序绘制的有效屏幕区域,但是这个区域不包括那些总是显示的非应用程序区域,比如:应用程序状态面板(application status pane)、按钮(button group)、应用程序的菜单bar、标题、工具条。
而且更重要的是从下面一行可以看出,这个ClientRect()所获得区域的top-left坐标是(0,45)。
通过上面的分析我们知道,UI在构造我们的Container时传递一个所谓的"客户矩形区域",这个"客户矩形区域"的top-left坐标是(0,45),从而也就知道如果要让我们的程序全屏显示,那么我们需要改变的是构造Container的时候传递的矩形大小。
那么就有如下几种方法:
①如果我们知道屏幕尺寸,那么就可以把iAppContainer->ConstructL( );里面的参数改为TRect (0,0,176,208)。
②上面的程序不具有适配性,因为我们把屏幕的宽度和高度写死了。
我们来看Symbian给我们提供的一个方法
|
|
Description写的很明显了,我就不翻译了。这个方法可以获得屏幕的整个尺寸,我们把程序可以改为:
iAppContainer->ConstructL( ApplicationRect() );从而实现程序的全屏显示。
③第三中方法是最笨的方法了,那就是不改变UI所传递的"客户矩形区域"的大小,传递的仍然是ClientRect()。但是到了Container后再采用"亡羊补牢"的做法!把status pane、menu bar等隐藏起来。
而且这种方法也容易出错误,下面是一个同行犯的错误,他在Container类里写入下面代码:
void CTestScreenContainer::ConstructL(const TRect& aRect)
{
CreateWindowL();
iLabel = new (ELeave) CEikLabel;
iLabel->SetContainerWindowL( *this );
iLabel->SetTextL( _L("Example View") );
iToDoLabel = new (ELeave) CEikLabel;
iToDoLabel->SetContainerWindowL( *this );
iToDoLabel->SetTextL( _L("Add Your controls\n here") );
SetRect(aRect);
CEikStatusPane* statusp = iEikonEnv->AppUiFactory()->StatusPane();
if(statusp)
statusp->MakeVisible(EFalse);
iEikonEnv->AppUiFactory()->Cba()->MakeVisible(EFalse);
ActivateL();
}
为了使用CEikStatusPane类要加入头文件#include <eikspane.h>
为了使用CEikButtonGroupContainer类要加入头文件#include <eikbtgpc.h>
其中iEikonEnv->AppUiFactory()是在Symbian中获取UI实例常用的方法,这和MFC是一样,你千万不能new一个CTestScreenAppUi出来,因为他们是由框架调用的,我们并不知道何时调用。
但是因为他是在Container类里调用这两个方法,也就是说ClientRect()获取"矩形区域"之后程序才设置status pane、Cba为不可见!所以当然也没什么用,程序仍然无法全屏显示。
所以说即使你在UI类里写下面的代码,但因为代码是在获取"矩形区域"之后才设置status pane、Cba为不可见,程序仍然无法全屏显示!
void CTestScreenAppUi::ConstructL() //在获取"矩形区域"后设置status pane、Cba为不见 CEikStatusPane* statusp = StatusPane(); Cba()->MakeVisible(EFalse); AddToStackL( iAppContainer ); |
所以千万记住:如果要通过设置status pane、Cba为不可见的方法获得全屏,千万要在获取"矩形区域"之前设置!
④上面集中方法都是通过在UI类设置"矩形区域"的大小,或者通过设置status pane、Cba不可见隐式改变"矩形区域"的大小实现全屏的。
这里我们介绍一种在Container类里,在UI设置完"矩形区域"后再改变屏幕为全屏显示的方法。
void CTestScreenContainer::ConstructL(const TRect& aRect) iLabel = new (ELeave) CEikLabel; iToDoLabel = new (ELeave) CEikLabel; SetRect(aRect); ActivateL(); |
但是要千万记得:SetExtentToWholeScreen()一定要在SetRect(aRect)之后调用才有效果。这点很容易理解,因为如果SetExtentToWholeScreen()改变屏幕为全屏后,再调用SetRect(aRect)又把屏幕尺寸设置为UI里传递的"矩形区域"的大小了。