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,C/C++混合編程
.cpp中定義的函數可以給.c使用,申明導出函數的.h文件,以及定義導出函數的.cpp文件中,函數的申明和實現必須包含在EXTERC中,如果只在.h中用了EXTERC而不在.cpp中用,那麼連接的時候,將提示找不到函數定義。例如:
//exportfunc.h
#ifndef __EXPORT_FUNC_H__
#define __EXPORT_FUNC_H__

#ifdef __cplusplus
extern "C"
{
#endif

import void func();

#ifdef __cplusplus
}
#endif

#endif



//exportfunc.cpp
#ifdef __cplusplus
extern "C"
{
#endif

void func()
{
//implement code block
}

#ifdef __cplusplus
}
#endif


5,標準C/C++格式的主函數
Symbian程序主函數有其特殊的形式,但也可以申明成標準C/C++格式的主函數,如,下面標準C/C++主函數的其中一種格式:
int main(int argc, char *argv[])
{
//Statements block

return 0;
}
但連接該程序時,需要用到庫ecrt0.lib。特別需要說明的時,在Symbian 9.2中的ecrt0.lib是有問題的,連接時,提示exit函數未定義,可以用PIPS的庫libecrt0.lib代替。


6,Posix庫的問題
Symbian 3rd開始支持部分Posix接口,支持Posix接口的庫叫PIPS。


7,基本數據類型的轉換(待續...)
TBuf
TDesC
char

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

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

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

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

12, 怎樣給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)

13,在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;
}
}
}
}


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

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

16, 改變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);


17, 將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"));


18, 手機按鍵聲音
#include <aknsoundsystem.h>
#include <avkon.rsg>

a) Disable Key Sound
//load key sound map from resources and push it to the context stack
KeySounds()->->PushContextL( R_AVKON_SILENT_SKEY_LIST );

//tell server to use this context stack for processing sounds
KeySounds()->BringToForeground();
//lock this context to the foreground, other BringToForeground() calls
//will be ignored until ReleaseContext() is called
KeySounds()->LockContext();

b) Enable Key Sound
//release the locked context
KeySounds()->ReleaseContext();

//pop the pushed context from the context stack
KeySounds()->PopContext();

19, Load png
For OS 6.1 (SDK 1.X), see CMdaImageFileToBitmapUtility class;
For OS 7.0/8.0 (SDK 2.x) see CImageDecoder class.

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

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

22, 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時,或在調用異步函數時。

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

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

25, 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

26, 在S60 3rd之前,庫中不能有static型的數據,但是在dll中可以用Dll類實現與static數據類似的功能。
EXPORT_LIB int Open(...)
{
XXX_HANDLE * h = new XXX;
Dll::SetTsl(h); //Set the pointer to thread local storage, h is pointer to an allocated area to be used as thread local storeage.
}

EXPORT_LIB int Handle(...)
{
XXX_HANDLE * h;
h = Dll::Tsl();
h->YYYY(....);
}

EXPORT_LIB void Close(...)
{
Dll::SetTsl(NULL);
}


27, BaflUtils, 是RFs有用的工具集, 如判斷file、directory是否存在,將路徑名分割成目錄名、文件名、盤符等。


28, System changes and network changes
1) RChangeNotifier is system change notifier, you will be notified the is system status changes, such as power supply, memory, time etc. all types of changes are defined in TChanges.

2) Network changes notifier is implemented as RConnection::AllInterfaceNotifier. When the connection goes up or down, that type of notifier wil be obtained. When the notifier is obtained, you can use RConnection::EnumerateConnections to get the number of current connections, if the number is 0, we can get the connection goes down; otherwise, the connection goes up.


29, Handle key event in view
Events framework of symbian are:

Window server send key or pointer events or some other special events to Symbian application, it calls one of a number of functions, according to the type of event. The application handles key event by calling CAknAppUi::HandleWsEventL,

For key events, CAknAppUi::HandleWsEventL calls CCoeControl::OfferKeyEventL() for each control on the control stack, beginning with the control at the top (position 0) until a control consumes it. If no control on the stack consumes the key event, the app UI's HandleKeyEventL() is called. Note that CCoeControl::OfferKeyEventL() is not called for controls whose ECoeStackFlagRefusesAllKeys flag is set.


1) Override member functions HandleKeyEventL and InputCapabilities in CAknAppUi/CAknViewAppUi derived class1
TCoeInputCapabilities CMyAppUi::InputCapabilities() const
{
return (TCoeInputCapabilities::EAllText | TCoeInputCapabilities::ENavigation);
}

TKeyResponse CMyAppUi::HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) {
TInt retVal = EKeyWasNotConsumed;
if (iView) //iViews is member of CAknView
{
CMyiew *pView = static_cast<CMyView *>(iView)
retVal = pView->HandleKeyEventL(aKeyEvent, aType); // HandleKeyEventL is member function of CMyiew which is derived from CAknView, but it is not member of CAknView
}

return retVal;
}


2) Handle key event in view
class CMyView : public CAknView
{

..........

TKeyResponse HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
{
TInt retVal = EKeyWasNotConsumed;

if (aType != EKeyEventDown)
{
return retVal
}

switch(aKeyEvent.iCode)
{
case:
..............
}

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