【转】symbian s60 3rd 横屏竖屏切换、旋转屏幕,全屏

来源:互联网 发布:新三板交易软件下载 编辑:程序博客网 时间:2024/06/05 17:24

symbian s60 3rd 横屏竖屏切换

 

原文:http://blog.sina.com.cn/s/blog_491e04500100dg85.html

 

设备, 软件 版本:

S60 3rd Edition

S60 3rd Edition, FP1

S60 3rd Edition, FP2

详细描述:

缺省情况下,程序是根据手机屏幕的当前方向开始启动的。如果要强制程序以横屏或竖屏的模式启动,那我们在CAknAppUi::ConstructL()方法中调用BaseConstructL()时就要传递相应的flag值:

定义如下:

       EAknEnableSkin = EAknEnableSkinFlag,
       EAppOrientationPortrait    = EAppOrientationSpecifiedFlag,
       EAppOrientationLandscape   = EAppOrientationSpecifiedFlag
                                     | EAppOrientationLandscapeFlag,
       EAppOrientationAutomatic   = EAppOrientationSpecifiedFlag
                                     | EAppOrientationAutomaticFlag,
       // Since 3.0
       EAknDisableHighlightAnimation =EAknDisableHighlightAnimationFlag,

使用方式:

void CMyAppUi::ConstructL()

{

BaseConstructL( EAknEnableSkin | EAppOrientationLandscape ); // start in landscape mode

...

}

如果要在程序运行期间改变方向,则需要调用:
void CAknAppUiBase::SetOrientationL( TAppUiOrientation aOrientation );
例:在HandleCommandL(TInt aCommand)函数中:

       case ES60ExCmdRotate:
        {
        iForcedRotateState = ETrue;
     
      if( !ScreenState() )
           {
           SetOrientationL(CAknViewAppUi::EAppUiOrientationPortrait); //竖屏         
           }
         else
           {        
           SetOrientationL(CAknViewAppUi::EAppUiOrientationLandscape); //横屏    
           }         
        break;
           }
这里的参数为EAppUiOrientationLandscape和EAppUiOrientationPortrait,注意这种情况下的调用就不要再向BaseConstructL()中传递相同的参数了。

注意

  • 横屏(landscape),前者是横幅,一般多用在风景照,所以叫"landscape"。
  • 竖屏(portrait),后者是直幅,一般多用在肖像上,所以叫"portrait"。

实例代码:S60_Platform_Custom_UI_and_Screen_Rotation_Example_v1_0_en.zip

 

测试机型:nokia 5320 xpressmusic

不过在3rd mr模拟器上测试屏幕旋转没效果,这个模拟器不支持旋转,只能手动设置屏幕大小。屏幕旋转需要真机测试。

 

旋转屏幕
2.8,3.0 SDK支持屏幕旋转,程序里面可以捕获该消息,然而使UI自定义的改变位置
继承的函数为:Container::HandleResourceChange,原先的SizeChange这个函数不会响应
 
在该函数内不要使用AppUi->ClientRect函数来获取工作区范围,数据会有偏差(这个问题郁闷了好久),可以使用
TRect rect;
AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane,rect );
来获取RECT

 

彻底解决Symbian全屏显示问题

原文:http://blog.csdn.net/Max__Payne/archive/2009/02/18/3906734.aspx

 

最近总有同行问我Symbian全屏显示的问题,说是参考了网上的方法也无法设置成全屏。其实,归根结底还是不明白Symbian框架的调用机制。这篇文章里我就来彻底研究一下Symbian全屏的机制。

首先,我们可以利用Carbide.vs向导建一个项目,名字就叫"TestScreen",选择基于Eikon的传统控件架构。

那么在CTestScreenAppUi的二阶构造函数里就有如下代码:

void CTestScreenAppUi::ConstructL()

{

BaseConstructL();

iAppContainer = new (ELeave) CTestScreenContainer;

iAppContainer->SetMopParent( this );

iAppContainer->ConstructL( ClientRect() );

AddToStackL(iAppContainer);

}

这里面有很关键的一句,就是我用红色显示的那段代码。它把当前UI的ClientRect()传递给Container类,我们都知道Container类是控件类,负责整个程序的界面显示,那么UI传递给Container的这个ClientRect()到底是什么东东呢?我们看看SDK HELP:

ClientRect()

TRect ClientRect() const;

Description

Gets the area of thescreen available to the application for drawing, not including thespace that is available for any of the following, where required:non-application areas which should always be displayed, an applicationstatus pane, an application button group, an application menu bar, anapplication title band and an application tool bar.

Importantly, theco-ordinates of the rectangle are relative to the whole screen area so,for example, the co-ordinate for the top, left point of the areaavailable for drawing may be (0, 45).

Return value

TRect The area of the screen available to the application for drawing.

从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给我们提供的一个方法

ApplicationRect()

TRect ApplicationRect() const;

Description

Gets the total areaof the screen available to the application. This includes the spacethat is available for a toolbar, toolband or title band, if theapplication requires them.

Return value

TRect The total area of the screen available to the application.

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

为了使用CEikButtonGroupContainer类要加入头文件#include

其中iEikonEnv->AppUiFactory()是在Symbian中获取UI实例常用的方法,这和MFC是一样,你千万不能new一个CTestScreenAppUi出来,因为他们是由框架调用的,我们并不知道何时调用。

但是因为他是在Container类里调用这两个方法,也就是说ClientRect()获取"矩形区域"之后程序才设置status pane、Cba为不可见!所以当然也没什么用,程序仍然无法全屏显示。

所以说即使你在UI类里写下面的代码,但因为代码是在获取"矩形区域"之后才设置status pane、Cba为不可见,程序仍然无法全屏显示!

void CTestScreenAppUi::ConstructL()

{

BaseConstructL();

iAppContainer = new (ELeave) CTestScreenContainer;

iAppContainer->SetMopParent( this );

iAppContainer->ConstructL( ClientRect() );

//在获取"矩形区域"后设置status pane、Cba为不见

CEikStatusPane* statusp = StatusPane();

if(statusp)

statusp->MakeVisible(EFalse);

Cba()->MakeVisible(EFalse);

AddToStackL( iAppContainer );

}

所以千万记住:如果要通过设置status pane、Cba为不可见的方法获得全屏,千万要在获取"矩形区域"之前设置!

④上面集中方法都是通过在UI类设置"矩形区域"的大小,或者通过设置status pane、Cba不可见隐式改变"矩形区域"的大小实现全屏的。

这里我们介绍一种在Container类里,在UI设置完"矩形区域"后再改变屏幕为全屏显示的方法。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);

SetExtentToWholeScreen();

ActivateL();

}

但是要千万记得:SetExtentToWholeScreen()一定要在SetRect(aRect)之后调用才有效果。这点很容易理解,因为如果SetExtentToWholeScreen()改变屏幕为全屏后,再调用SetRect(aRect)又把屏幕尺寸设置为UI里传递的"矩形区域"的大小了。

 

Dialog全屏实现:

RESOURCE DIALOG r_dialog_waitingbox0
{
    flags = EEikDialogFlagWait
            |EEikDialogFlagFillAppClientRect //client screen
            |EEikDialogFlagNoShadow
            |EEikDialogFlagNoBorder
            |EEikDialogFlagCbaButtons
            |EEikDialogFlagNotifyEsc  //OkToExitL will catch "exit" event
            |EEikDialogFlagNoDrag;
    buttons = R_AVKON_SOFTKEYS_CANCEL;
}
void CUbWaitingBox::PostLayoutDynInitL()
{
#if 1 //dialog 全屏的实现
    // hide cba buttons
    CEikButtonGroupContainer* cba = CEikButtonGroupContainer::Current();
    cba->MakeVisible(EFalse);
    // hide status pane
    CEikStatusPaneBase* statusPane = CEikStatusPane::Current();
    statusPane->MakeVisible(EFalse);
    SetExtentToWholeScreen();
#endif
    CAknDialog::PostLayoutDynInitL();
}

 

屏幕相关事件:

void CAknAppUi::HandleResourceChangeL( TInt aType );

void CAknAppUi::HandleScreenDeviceChangedL();

void CAknAppUi::HandleForegroundEventL(TBool aForeground);

例如捕捉转屏事件:

在appui的HandleResourceChangeL处理
HandleResourceChangeL( TInt aType )
{
CAknAppUi::HandleResourceChangeL( aType );
if ( aType==KEikDynamicLayoutVariantSwitch ){
//TODO: handle screen switch
}
}

void CUbiLiveGC_SymbianAppUi::HandleForegroundEventL(TBool aForeground)
{
    TAppUiOrientation aOrientation = Orientation();
    if(aOrientation==EAppUiOrientationLandscape){
       
    }
}
void CUbiLiveGC_SymbianAppUi::HandleScreenDeviceChangedL()
{
    TAppUiOrientation aOrientation = Orientation();
    if(aOrientation==EAppUiOrientationLandscape){
       
    }
}

原创粉丝点击