Nokia论坛技术资料Symbian解决方案-中文版(7)-转载

启动正确的viewer应用程序

细描述:
如果某文件(内容)类型被系统支持,那它的viewer可以通过CDocumentHandler作为一个内嵌应用程序来显示。

Code:
#include <DocumentHandler.h>    // link against commonui.lib    #include <apmstd.h>             // link against apmime.lib    void TTestEmbedApp::EmbedLaunchFileL( const TDesC& aFile )      {      // iDocHandler is a pointer to CDocumentHandler       if( !iDocHandler )           {           // On S60 3rd Edition, CDocumentHandler constructor no longer requires           // a CEikProcess pointer as a parameter    #ifdef __SERIES60_3X__           iDocHandler = CDocumentHandler::NewL();    #else           iDocHandler = CDocumentHandler::NewL( iEikonEnv->Process() );    #endif           }      TDataType empty;      iDocHandler->OpenFileEmbeddedL( aFile, empty );      }

上面这个示例将启动正确的程序来显示该特殊文件。因为使用了一个空白的数据类型(MIME),这样document handler会试图将文件传递到system recognizers以解决文件类型的问题。例如,如果文件(aFile)是一个.txt文件,那记事本程序将被启动,如果文件是.jpg图片,那多媒体程序将被启动,以用来打开该文件。

在S60设备上调用getHeaderField("Location")返回nll的问题

详细描述:
为了获得URL转向,你需要通过getHeaderField方法获得http头中有关location的内容。但这个方法有时无法返回任何值。
这个问题在S60第三版向后不会再发生了。
因此建议如果需要location,在1st/2nd中可用socket来直接操作获取。

如何更换当前主题

详细描述:
S60第三版SDK并未提供给第三方程序一个方法来更换主题。
但我们可以在

Extensions plug-in package for S60 3rd Edition SDK
http://www.forum.nokia.com/info/sw.n...Pack1.zip.html
获取到我们需要的API.


解决方案
如何更换主题:
1、连接Skin Server

Code:
    #include <AknSSrvClient.h> // link against aknskinsrv.lib        RAknsSrvSession skinsSession;        User::LeaveIfError( skinsSession.Connect( this ) );        CleanupClosePushL( skinsSession );


2、获取当前skin的package ID

Code:
 #include <centralrepository.h> // link against centralrepository.lib     #include <AknSkinsInternalCRKeys.h>            void CMyThemeManager::StoreCurrentSkinIdL()          {            TAknsPkgIDBuf pidBuf;                        CRepository* repository = CRepository::NewL(KCRUidPersonalisation );                                TInt retVal = repository->Get( KPslnActiveSkinUid, pidBuf );            delete repository;            repository = NULL;            iOriginalSkinPid.SetFromDesL( pidBuf ); // iOriginalSkinPid is of type TAknsPkgID            }


3、获得已安装skin packages列表

Code:
CArrayPtr<CAknsSrvSkinInformationPkg>* skinInfoArray =                     skinsSession.EnumerateSkinPackagesL();    CleanupStack::PushL( skinInfoArray );


4、查询已安装的主题,确认第一个有效新主题

Code:
TInt retValue( KErrNone );        if ( skinInfoArray->Count() > 0 )            {            for ( TInt i = 0; i < skinInfoArray->Count(); i++ )                {                TAknsPkgID pkgId = skinInfoArray->At( i )->PID();                if ( pkgId != iOriginalSkinPid )                    {                    // Activates a complete skin package                    retValue = skinsSession.SetAllDefinitionSets( pkgId );                    if ( retValue == KErrNone )                        {                        SetNewSkinIdL( pkgId );                        }                    break;                                        }                }                        }

5、在Central Repository中存储新主题id

Code:
    void CMyThemeManager::SetNewSkinIdL( TAknsPkgID aPkgId )            {            TAknsPkgIDBuf pidBuf;                        aPkgId.CopyToDes( pidBuf );            CRepository* repository = CRepository::NewL( KCRUidPersonalisation );                                TInt retVal = repository->Set( KPslnActiveSkinUid, pidBuf );                    // KPslnActiveSkinLocation value needs to be updated            // if the new skin resides on memory card and the             // previous one resided in phone memory (and vice versa)                    delete repository;            repository = NULL;            }

如何获取功能键上的文字
 详细描述:

==描述==
下列代码演示了如何获取当前control pane(CBA)上左、中、右功能键的文字。

我们可以通过CCoeControl::ComponentControl()获取每个功能键的label(CEikLabel),它是功能键上第一个控件。


解决方案

Code:
    CEikButtonGroupContainer* cba = CEikButtonGroupContainer::Current();             if( cba )             {             MEikButtonGroup* buttonGroup = cba->ButtonGroup();            for( TInt pos = 0; pos < 3; pos++ )                {                TInt cmdId = buttonGroup->CommandId( pos );                CCoeControl* button = buttonGroup->GroupControlById( cmdId );                                    if( button && buttonGroup->IsCommandVisible( cmdId ))                    {                    CEikLabel* label = static_cast<CEikLabel*>( button->ComponentControl(0) );                    const TDesC* txt = label->Text();                         }                }            }


==注意==
1、上述代码总是返回完整的lable text,即使显示在屏幕上的label是缩短过文字的。

2、CEikCommandButton类中提供了Label()方法以完成该项功能,但目前CBA的实现并没支持该类。CEikButtonGroupContainer::CommandButtonOrNull()总是会返回NULL。

如何在S60第三版设备上设置麦克风无声或取消无声

详细描述:
现在我们可以通过Phone Client Extension API(其为S60第三版扩展插件包的一部分)来控制手机麦克风无声或取消无声。

Extensions plug-in package for S60 3rd Edition SDK for Symbian OS, for C++, MR
http://www.forum.nokia.com/info/sw.n...Pack1.zip.html


Extensions plug-in package for S60 3rd Edition SDK for Symbian OS, for C++, supporting FP1
http://www.forum.nokia.com/info/sw.n...g-In_Pack.html


解决方案:
下列代码显示了通过加载PhoneClientExt这个Dll,来构造一个command handler(CPhCltCommandHandler)以设置无声或取消无声。

需要功能:WriteDeviceData

Code:
/*** Header file ***/        #include <RPhCltServer.h>   // link against PhoneClient.lib        #include <PhCltExt.h>       // link against PhoneClientExt.lib        ...                RPhCltServer iPhoneClientServer;        RLibrary iLibrary;        CPhCltCommandHandler* iPhCommandHandler;        /*** Source file ***/        _LIT(KPhoneCltExDllName, "PhoneClientExt.dll");        User::LeaveIfError( iPhoneClientServer.Connect() );        User::LeaveIfError( iLibrary.Load(KPhoneCltExDllName) );        TInt res = iLibrary.Lookup(1)();        CPhCltExtFactory* phCltExtFactory = reinterpret_cast<CPhCltExtFactory*>( res );        iPhCommandHandler = phCltExtFactory->CPhCltCommandHandlerLD();        User::LeaveIfError( iPhCommandHandler->Open( iPhoneClientServer ) );        // Mute the microphone. This should be done inside an active object        // (a class derived from CActive)        iPhCommandHandler->MuteMicrophone( iStatus, ETrue );        SetActive();
无法在S60第三版FP1设备上使用OCR引擎
详细描述
如果你试图在S60 3rd Edition, Feature Pack 1设备上用如下语句来初始化OCR(Optical Character Recognition)引擎,将会得到-5 (KErrNotSupported) 错误

Code:
    static MOCREngineInterface* CreateOCREngineL(             MOCREngineObserver& aObserver,             const TOcrEngineEnv aEngineEnv,             TEngineType aEngineType );

如何演示该问题
我们可以通过编译S60 3rd Edition, Feature Pack 1 SDK中的OCR example application (S60Ex/ORCExample),来演示这个问题。
这个程序可以运行在模拟器上,但在真机运行时就会报告"Initializing OCR Engine Failed: -5"错误。

解决方案
目前暂未有解决方案。尽管S60第三版FP1的SDK文档上已有记载。但第三版FP1设备还尚未支持它。

如何防止editor中出现遮行的现象

详细描述
如果editor的高度不能满足多行文本显示的高度,那最下面一行可能只能显示部分内容,出现遮行的现象。根据实际内容动态的计算editor高度并不一定可行。
例如,插入图片或改变字体大小时,可能上述方法就无效了。这时我们可以通过调用RestrictScrollToTopsOfLines()来解决这个问题(加入EFalse参数):

Code:
iEditor->TextLayout()->RestrictScrollToTopsOfLines( EFalse );

注意:
RestrictScrollToTopsOfLines()使用时要小心,在某些情况下鼠标可能会出现在屏幕外面。

如何隐藏status和control panes

详细描述:
描述
我们可以通过隐藏status和control panes来生成一个全屏效果的应用程序。

解决方案
将程序切换为全屏最简单的方法,就是:

Code:
SetExtentToWholeScreen();

在(CCoeControl-derived)window-owning控件中,这个方法可以将窗口尺寸调整到整个屏幕大小,程序绘制时即可覆盖status和control panes了。

我们也可准确指名对panes的隐藏的操作。


如何隐藏status pane:

Code:
    CEikStatusPane* statusPane =             CEikonEnv::Static()->AppUiFactory()->StatusPane();                statusPane->MakeVisible(EFalse);


还有一种可选的方法是在程序资源文件中将status pane设置为empty layout.

Code:
    RESOURCE EIK_APP_INFO             {            ...            status_pane = R_AVKON_STATUS_PANE_LAYOUT_EMPTY;            ...            }


如何隐藏control pane:

Code:
    CEikButtonGroupContainer* cba = CEikButtonGroupContainer::Current();        cba->MakeVisible( EFalse );
如何获取S60第三版上图片缩略图
详细描述:
描述
在S60第二版上,我们可以通过CAPAlbImageUtil类提供的GetThumbnailL()方法获取存放在多媒体文件夹中的图片的缩略图,但在第三版中,Photo Album API已经被新的Media Gallery API取代了,而它并没有提供直接方法来获取图片的缩略图。


解决方案
一般说来,我们可以通过扫描存放图片的文件夹来获取缩略图。
存放缩略图的文件目录一般格式如下:
Code:
<DRIVE>:\ Data \ Images \ _PAlbTN \
在Nokia N系列手机中,目录存放格式不同于其他手机:
Code:
<DRIVE>:\ Data \ Images \ <YearMonth> \ _PAlbTN \ <R1XR2> \

其中R1和R2是设备指定的,这样同个缩略图可能有多个版本呢。

注意,_PAlbTN目录一般为隐藏。

要在S60第三版上完成这些工作,找出图片缩略图,需要采用递归搜索的方式来处理这些图片目录。

一般来说,缩略图和主图片的名称是一致的,不过有个不一样的后缀,例如,某图片名称为some_picture.jpg,那其缩略图的名字就可能为some_picture.jpg_170x128.


下列这个实例简要的说明图片/缩略图的递归搜索方式:
Code:
RFs fs;            User::LeaveIfError(fs.Connect());            CleanupClosePushL(fs);                          // assumes phone memory is used for storing images            _LIT( KImagesPath, "C:\\Data\\Images\\" );                    // to list known image file(s) and thumbnail(s), use imagename.ext*            // to list thumbnail(s) only for a known image, use imagename.ext_*            // to list all available images and thumbnails, use *.*                    _LIT(KImageName,"some_picture.jpg*");                     CDirScan* scan = CDirScan::NewLC( fs );                    scan->SetScanDataL( KImagesPath,                                 KEntryAttNormal|KEntryAttHidden,                                 ESortNone,                                 CDirScan::EScanDownTree );                FOREVER                {                CDir* dirlis = 0;                TRAPD(error, scan->NextL(dirlis));                if (error || !dirlis)                    {                                break;                    }                delete dirlis;                FindFile( fs, scan->FullPath(), KImageName );                };                        CleanupStack::PopAndDestroy(2); // scan, fs                void FindFile( RFs& aFs, const TDesC& aDir, const TDesC& aImageWild )            {            CDir* dirList;            TFindFile FindObj( aFs );            TInt j = FindObj.FindWildByDir( aImageWild, aDir, dirList );                            if( j == KErrNone )                {                for ( TInt i = 0; i < dirList->Count() ; i++ )                    {                    TFileName fullname(aDir);                                 fullname.Append((*dirList)[i].iName);                                    // fullname now contains path and name of image/thumbnail                               }                }            }

怎么通过程序锁定键盘

我们可以通过RAknKeyLock类来锁定键盘

Code:
    #include <aknkeylock.h>     // link against avkon.lib        RAknKeyLock keyLock;         if( keyLock.Connect() == KErrNone )      {             keyLock.EnableKeyLock();            keyLock.Close();        }

如何检测拨出电话的类型和状态

详细描述:

我们可以使用Publish & Subscribe keys来检测拨出电话的类型和状态。有三个PS keys可用来获取相关属性值。

Code:
    const TUid    KPSUidTelephonyCallHandling = { 0x101f8787 };        const TUint32 KTelephonyCallState         = 0x00000004;        const TUint32 KTelephonyCallType          = 0x00000005;


获取电话类型:
[code cpp]
RProperty iProperty;

iProperty.Get(KPSUidTelephonyCallHandling, KTelephonyCallType, calltype);
[/code]


电话呼叫的类型(TPSTelephonyCallType)值:

Code:
            EPSTelephonyCallTypeUninitialized = 0,                EPSTelephonyCallTypeNone,                EPSTelephonyCallTypeCSVoice,                EPSTelephonyCallTypeFax,                EPSTelephonyCallTypeData,                EPSTelephonyCallTypeHSCSD,                EPSTelephonyCallTypeH324Multimedia,                EPSTelephonyCallTypeVoIP


如何获得呼叫状态信息:

Code:
    iProperty.Get(KPSUidTelephonyCallHandling, KTelephonyCallState , callstate);

电话呼叫的状态(TPSTelephonyCallState)值:

EPSTelephonyCallStateUninitialized = 0,

EPSTelephonyCallStateNone,

EPSTelephonyCallStateAlerting,

EPSTelephonyCallStateRinging,

EPSTelephonyCallStateDialling,

EPSTelephonyCallStateAnswering,

EPSTelephonyCallStateDisconnecting,

EPSTelephonyCallStateConnected,

EPSTelephonyCallStateHold

PS Keys for Call Status & Indicators API 并非官方S60 SDK的一部分,但可以通过
Extensions plug-in package for S60 3rd Edition SDK for Symbian OS, for C++, MR
http://www.forum.nokia.com/info/sw.n...Pack1.zip.html
获得

注意,Nokia没有承诺这些API在各平台或平台内可以二进制兼容。

如何在S60中动态改变功能键并置之为无效

详细描述:
可以通过如下方法来动态改变功能键:

在.rss文件中定义一个新的CBA资源

Code:
RESOURCE CBA r_custom_cba1        {             buttons =              {              CBA_BUTTON { id = ECba1Button1; txt = "Button1"; },              CBA_BUTTON { id = ECba1Button2; txt = "Button2"; }              };          }

在.hrh文件中定义一个新的command ID

Code:
    enum TMyMenuCmdIDs          {            // ...            ECba1Button1,            ECba1Button2            };


在代码中调用SetCommandSetL():

Code:
#include <eikbtgpc.h>     CEikButtonGroupContainer* cba = CEikButtonGroupContainer::Current();    cba->SetCommandSetL(R_CUSTOM_CBA1);    cba->DrawNow();


如果要将CBA改变为Options/Cancel,可以参考avkon.rsg中的预先定义:

Code:
cba->SetCommandSetL(R_AVKON_SOFTKEYS_OPTIONS_CANCEL);

如果要置之无效的话,可以使用预先定义的资源名R_AVKON_SOFTKEYS_EMPTY

如何在列表框项中响应动作

详细描述:
描述
下面的代码示例演示了如何响应用户选定的列表框项。

这里介绍一下如何生成一个简单列表框 [[How to create a simple listbox]]

我们可以捕捉任何键盘事件借以产生各种响应(如弹出一个对话框),我们可以通过OfferKeyEventL()方法来处理

解决方案

Code:
TKeyResponse CMyExampleAppView::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)  {            if(aType != EEventKey)              {                return EKeyWasNotConsumed;                }            switch(aKeyEvent.iCode)                {                case EKeyUpArrow:                case EKeyDownArrow:                    {                    // Forward up and down key press events to the list box                    return iListBox->OfferKeyEventL( aKeyEvent, aType );                    }                case EKeyOK: // display an information note when item is selected                    {                    _LIT(KFormatMessage, "Selected item: %d");                    TInt idx = iListBox->CurrentItemIndex();                    TBuf<32> message;                    message.Format(KFormatMessage, idx);                    CAknInformationNote* Note = new (ELeave) CAknInformationNote;                    Note->ExecuteLD(message);                     return EKeyWasConsumed;                    }                default:                    break;                }                            return EKeyWasNotConsumed;            }


注意要加上这行代码:

Code:
    AddToStackL( iAppView );
在AppUi的构造函数ConstructL()中,要将该view/container添加到control stack中以便接收OfferKeyEventL()调用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值