symbian開發札記

 1, 棧問題
棧空間不足或者棧被破壞,不僅能導致程序崩潰,還能造成系統自動重啓.解決方案
1) 在.mmp中用 EPROCSTACKSIZE 增大棧空間。但是需注意,EPROCSTACKSIZE的有效範圍是8k到80k,默認值8k,如果申明的棧空間超過這個範圍,應用程序是無法運行的,連main函數就進不了。
2) 正確使用棧,特別是CleanupStack. 比如如下錯誤就可能導致系統自動重啓:
RSocketSrv socket.
socket.Connect();
CleanupClosePushL(socket);

....

CleanupStack::PopAndDestroy(2, &socket);

2,堆問題
如果應用程序new/malloc失敗,多半都是堆空間不足造成的。解決方案是在.mmp中用 EPROCHEAPSIZE 申明堆空間大小(設定最小和最大值),默認大小是:最小4k,最大1M


3,Console問題
Symbian程序在設備上運行時,可以將調試信息輸出到Console,只需要調用CConsole::Printf或者C的printf即可。實現該輸出功能的程序,需要連接estlib.lib和euser.lib,但不能連接elibc.lib,否則,Console將無法顯示。

 

4, 清除棧
清除棧不能濫用。一般來說,若當前函數異常返回後,已分配的內存無法被釋放,這樣的內存地址才需要加入清除棧,如在函數內部分配,釋放的指針。
以LC結尾的系統函數,在返回前,它將返回值加入了清除棧,所以要記得將其從清除棧中彈出。
在非主線程以外的其他線程中使用清除棧,需要先用CtrapCleanup::NewL初始化清除棧,並在線程退出前釋放。

5, 重載CAknDialog/CEikDialog的PreLayoutDynInitL時,需要首先調用ActivateL(), 否則,會造成系統崩潰。

6, 獲得CAknAppUi/CEikAppUi的指針
在CAknView子類中直接用AppUi();
在CCoeContro子類中,用iEikonEnv->EikAppUi();

7, 可以同過重載Dialog的PreLayoutDynInitL或PostLayoutDynInitL實現動態創建控件/設置控件的內容,但通常都在函數PostLayoutDynInitL中實現,因爲若在PreLayoutDynInitL實現的話,會導致Dialog在彈出時出現閃爍的現象。

 

8, 怎樣給Dialog中的CEikEdwin添加Vertical Scrollbar
1) 在資源文件中,將CEikEdwinInclusiveSizeFixed添加到EDWIN的flags中,以便ScrollBar顯示在CEidEdwin的內部;否則,顯示在CEikEdwin外部,可能落在可視區域之外而在屏幕上無法看見。
2) 在Dialog中的PreLayoutDynInitL用static_cast(CEikEdwin*)(ControlOrNull(edwin_id)獲取CEikEdwin的句柄,然後調用CreateScrollBarFrameL()(注: 創建ScrollBar)和ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::Eon)(注:顯示ScrollBar)

9,在Dialog中顯示Listbox
RESOURCE DIALOG r_tmp_dialog
{
    buttons = R_AVKON_SOFTKEYS_OK_CANCEL;
    flags = EEikDialogFlagWait | EEikDialogFillAppClientRect;
    items =
    {
       DLG_LINE
       {
          type = EAknCtSingleGraphicListBox;
          id = ETmpListBox;  //The id of listbox
          control = LISTBOX
          {
             flags = EAknListBoxMenuList;
          }
       }
    }
}


10, 在View中創建Container時,一定要將對Container調用SetMopParent, 將其MopParent 設置成該View, 否則,container中的control可能會顯示不正確,比如listbox的scrollbar, 在設備上可能顯示不出來。

11, Listbox 在添加了item之後一定要調用HandleItemAdditionL, 刪除文件之後一定要調用HandleItemRemovalL, 否則,listbox可能顯示不正常,比如scrollbar顯示不出來或無法隱藏等。

12, 改變CEikEditor的text顏色
CCharFormatLayer* formatLayer = CEikonEnv::NewDefaultCharFormatLayerL();

TFontSpec fontspec = LatinBold16()->FontSpecInTwips();
TCharFormat charFormat( fontspec.iTypeface.iName, fontspec.iHeight );
TCharFormatMask charFormatMask;
 
charFormat.iFontPresentation.iTextColor = KRgbBlack;
charFormatMask.SetAttrib(EAttColor);

charFormatMask.SetAttrib(EAttFontTypeface);
charFormatMask.SetAttrib(EAttFontHeight);

formatLayer->Sense(charFormat, charFormatMask);
formatLayer->SetL(charFormat, charFormatMask);
iEdwin->SetCharFormatLayer(formatLayer);



13, 將TTime以系統定義的格式輸出
TBuf<64> string;
TTime time;
time.HomeTime();
time.FormatL(string, _L("%/0%1%/1%2%/2%3%/3 %-B%:0%J%:1%T%:2%S%:3%+B"));


14, 在Draw函數之外使用CWindowGc, 必須先調用ActivateGc(), 使用完畢後,調用DeactivateGc(), eg:
ActivateGc();
CWindowGc & gc = SystemGc();
gc.SetBrushStyle( CGraphicsContext::ENullBrush );
gc.Clear( Rect() );
DeactivateGc();

15, 修改窗口中控件的顏色
比如:文字顏色,背景色,Label邊框色、文字顏色、背景色等。
CCoeControl::OverrideColor(EColorxxx, KRgbBlack);

16, CTrapClean & CScheduler
1) 默認情況下,系統會爲.app和.exe建立cleanup stack。 但是,如果是子進程,或者線程,需要自己建立,並在退出前釋放:如下:
CTrapCleanup *trapHandler = NULL;
if (User::TrapHandler() == NULL)
{
    trapHandler = CTrapCleanup::New();
}
//Others codes
delete trapHandler;
如果cleanup stack已經存在,就不要再建立,否則,可能會出問題。
2)默認情況下,系統會爲GUI程序建立Active Scheduler。 但是對於其他程序,如命令行程序, 線程,則需要自己建立,並在退出前釋放:
ActiveScheduler *scheduler = NULL;
if (CActiveScheduler::Current() == NULL)
{
    scheduler = new CActiveScheduler;
    if (scheduler != NULL)
    {
       CActiveScheduler::Install(scheduler);
    }
}

//Other codes;

if (scheduler)
{
    ActiveScheduler::Install(NULL);
    delete scheduler;
    scheduler = NULL;
}

如果系統沒有建立Active Scheduler, 且程序中又使用到了Active Object, 並不是一定會出問題。 但是若出問題,一般在在跟異步函數或活動對象相關的地方,比如在調用WaitForRequest時,或在調用異步函數時。

17,RChunk
多進程可以使用RChunk共享數據(注意用Semophore或Mutex等保護共享數據區)。S60 2nd不能有static型數據,也可以藉助RChunk代替static數據。

18, 可以在TRAP中是用返回值
TRAPD(errCode, retVal = FunctionL());
但是,只有當errCode是KErrNone時,retVal纔有意義。但是,不要對LC函數是用返回值,否則可能會出問題:
TRAP(errCode, retVal = FunctionLC()); //Will lead out some problems
但是可以用:
TRAP(errCode, FunctionLC()); //OK

19, Client-Server間可以傳遞指針,但是隻能是描述符(descriptor)的指針,不能是普通的、自定義數據類型的指針。如果需要傳遞非描述符指針,需要用TPckg打包成描述符指針。
class TTmpDataType
{
......
};

typedef TPckg<TTmpDataType> TTmpDataPckg;
TTmpDataType iDataSend;
TTmpDataPckg iPckgSend(iDataSend);

//Client end;
Tany *p[KMaxMessageArguments];
p[0] = &iPckgSend;
SendReceive(iStatus, p);

//Server end;
TTmpDataType iDataRecv;
TTmpDataPckg iPckgRecv(iDataRecv);
iMessage.ReadL(iMessage.Ptr0(), &iPckgRecv); //iMessage is received message of RMessage

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章