symbian 雜談,小技巧
如何枚舉出正在運(yùn)行的App
結(jié)合RApaLsSession和TApaTaskList應(yīng)該可以做到.
RApaLsSession:
GetAppIcon()
GetAppInfo()
TApaTaskList:
FindApp()
從收件箱讀取彩信圖片
mmslist實(shí)現(xiàn)了首先以listbox列表的形式列出了收件箱中的所以彩信,選擇某一條彩信后可以顯示出它的發(fā)送端號(hào)碼和彩信的文本信息;現(xiàn)在我想讓它顯示發(fā)送端號(hào)碼和彩信圖片(假設(shè)我的彩信都是圖片格式);請(qǐng)教兩位應(yīng)該怎么才能實(shí)現(xiàn)讀彩信圖片并顯示的功能。
下面是讀彩信文本信息的代碼,你們參考一下:
void CMmslController::GetMessageL( const TDesC& aItem,
TDes& aMessageText ) const
{
//Read the message Uid from aItem
TUint32 id = 0;
TLex lexer( aItem );
lexer.SkipSpace();
TChar ch( lexer.Get() );
while ( ( ch != ‘\t’ ) && ( ch != 0 ) ) // Finding end of 1.st line
{
ch = lexer.Get();
}
lexer.SkipSpace();
lexer.Val( id, EHex );
if( iCurEntries->Find( id ) == KErrNotFound )
{
return;
}
CMsvEntry* msvEntry = iSession->GetEntryL( id );
CleanupStack::PushL( msvEntry );
const TMsvEntry& msgEntry = msvEntry->Entry();
CBaseMtm* clientMtm = iMtmReg->NewMtmL( msgEntry.iMtm );
CleanupStack::PushL( clientMtm );
clientMtm->SwitchCurrentEntryL( msvEntry->EntryId() );
// An instance of the TDesOverflow derived class used to suppress
// the panic that would be generated if buffer length was exceeded
// in calls to AppendFormat
TOverrideOverFlow noOflo;
// Text is located in iDescription field.
aMessageText.AppendFormat( msgEntry.iDescription, &noOflo );
//aMessageText.AppendFormat( msgEntry.iDetails );
CleanupStack::PopAndDestroy( 2 ); // clientMtm, msvEntry
}
如何讓程序在安裝后自動(dòng)運(yùn)行
如何讓一個(gè)程序(或是一個(gè)server)在安裝后自動(dòng)運(yùn)行于手機(jī)中,這是非常容易的,只需在你的PKG文件中,在包含你的app或exe文件的那行末尾加上“FR,RI”。
“FR”表示“File Run”,而“RI”則表示“Run during Installation”。請(qǐng)注意,務(wù)必要先開始rsc,aif,mbm文件的安裝,然后才能是APP等(也就是在pkg文件的末尾進(jìn)行app的安裝)
舉例:
“\Symbian.1\Series60\Epoc32\release\thumb\urel\MyApp.rsc” -
“!:\system\apps\MyApp\MyApp.rsc”
“\Symbian.1\Series60\Epoc32\release\thumb\urel\MyApp_caption.rsc” -
“!:\system\apps\MyApp\MyApp_caption.rsc”
“\Symbian.1\Series60\Epoc32\release\thumb\urel\MyApp.aif” -
“!:\system\apps\MyApp\MyApp.aif”
“\Symbian.1\Series60\Epoc32\release\thumb\urel\MyApp.app” -
“!:\system\apps\MyApp\MyApp.app”,FR,RI
文件類型和從屬關(guān)系
下圖顯示了在一個(gè)典型的Symbian程序中各文件的從屬關(guān)系。
.hrh文件中包含所有要在.rss、.h和.cpp中使用的枚舉類型。它們主要使用在應(yīng)用程序的菜單、工具欄等地方,下面展示了一個(gè)典型的例子:
//MyApp.hrh
//
enum{
EMyAppCmdOpenFile = 0×6000,
EMyAppCmdEdit,
};
按照慣例這些命令I(lǐng)D值的范圍應(yīng)該從0×6000開始向上。
.rss文件中是資源文件,這些文件包括所有靜態(tài)字符串、按鈕、菜單和列表等的定義,都使用在應(yīng)用程序UI中。此外,Nokia Series 60向?qū)н€可能生成一個(gè).loc文件,這個(gè)文件同.rss文件很相似但只用于描述你程序中的靜態(tài)字符串,利用它你可以很容易的將程序變成多語(yǔ)言版本。
.rsg是生成的資源文件。它們是在編譯時(shí)刻由資源編譯器產(chǎn)生的,.cpp文件將包含它們以便處理資源。
.mbm是symbian位圖文件,它里面可以存儲(chǔ)幾個(gè)位圖。
.mbg是在創(chuàng)建.mbm時(shí)生成的。這些文件一般包含在那些使用位圖的RSS文件中,一個(gè)mbg文件包括在.mbm中各位圖的ID。
網(wǎng)絡(luò)通訊中正確顯示中文
1。經(jīng)過(guò)對(duì)照GB2312/GBK編碼表,在程序中定義_LIT8(KTest, “中文測(cè)試”);是GB2312/GBK編碼
2。直接從輸入框取出的字符串,經(jīng)過(guò)按照byte分析并比較中文和unicode對(duì)照表,發(fā)現(xiàn)是UTF-16LE(Sixteen-bit UCS Transformation Format, little-endian byte order)編碼
3,中文對(duì)服務(wù)器的傳輸建議統(tǒng)一處理成UTF8編碼進(jìn)行,從對(duì)話框獲得的也一樣處理,服務(wù)器需要對(duì)應(yīng)識(shí)別過(guò)來(lái)的字符串并做處理。
如何動(dòng)態(tài)更改CEikLabel 的text
CEikLabel* iLabelStatus;
…..
iLabelStatus = new (ELeave) CEikLabel;
iLabelStatus->SetContainerWindowL( *this );
iLabelStatus->SetTextL( this->iStatusStr );
….
//動(dòng)態(tài)在這里更改
iLabelStatus->SetTextL(iStatusStr);
iLabelStatus->DrawNow();
如果初始化時(shí)就無(wú)法顯示,請(qǐng)對(duì)照helloworld代碼檢查自己label是否設(shè)置正確;如果是進(jìn)度進(jìn)行中無(wú)法顯示,請(qǐng)檢查cactive是否正確執(zhí)行,單步DrawNow是否被正確調(diào)用。
在listbox中怎么處理所選項(xiàng)的事件
觸發(fā)事件并不是很復(fù)雜的事情,
TKeyResponse CXXContainer::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
{
TInt code = aKeyEvent.iCode;
switch(code)
{
// is navigator button pressed
case EKeyOK:
{
// pass the key press event to view,
// then view will pass it to ui class’s handler
iXXView->ProcessListEvent(iListBox->CurrentItemIndex()) ;
}
return (EKeyWasConsumed);
case EKeyLeftArrow :
case EKeyRightArrow :
return (EKeyWasConsumed);
default:
// Let Listbox take care of its key handling
return iListBox->OfferKeyEventL(aKeyEvent, aType) ;
}
}
這個(gè)iXXView的ProcessListEvent()函數(shù)就是傳入當(dāng)前用戶選擇的那個(gè)list item的index。
pkg文件中指定多個(gè)操作系統(tǒng)版本
pkg file定義了安裝文件(sis)的內(nèi)容,它包括應(yīng)用程序的UID,一個(gè)支持的語(yǔ)言列表,目標(biāo)產(chǎn)品的UID和打包在sis的一組文件:
; MyGame.pkg
; Specifies an installation file for MyGame
;Languages
&EN
;Header
#,(0×1000ABCD),1,0,0
; Required line for Series 60 devices. Defines the target product
; UID.
(0×101F6F88), 0, 0, 0,
“\epoc32\release\thumb\urel\MyGame.app”-“!:\system\apps\MyGame\MyGame.app”
“\epoc32\release\thumb\urel\MyGame.rsc”-“!:\system\apps\MyGame\MyGame.rsc”
“\epoc32\release\thumb\urel\MyGame.mbm”-“!:\system\apps\MyGame\MyGame.mbm”
“\epoc32\release\thumb\urel\MyGame.aif”-“!:\system\apps\MyGame\MyGame.aif”
“..\MyGame\MyGameSample.wav”-“!:\system\apps\MyGame\MyGameSample.wav”
Product UID定義了應(yīng)用程序的目標(biāo)環(huán)境,大部分的s60版本是向下兼容的。
參見(jiàn)下表:
Nokia 7650 0×101F6F87
Nokia 3650 0×101F7962
Nokia 9210/9290 0×10005E33
Nokia N-gage 0×101F8A64
Siemens SX1 0×101F9071
Series 60 Platform v0.9 0×101F6F88
Series 60 Platform v1.0 0×101F795F
Series 60 Platform v1.1 0×101F8201
Series 60 Platform v1.2 0×101F8202
Series 60 Platform v2.0 0×101F7960
如果程序需要依據(jù)各不同的平臺(tái)來(lái)進(jìn)行安裝,那就可以使用條件語(yǔ)句塊來(lái)處理,這時(shí)pkg里的語(yǔ)句如下:
;
; Files to install
;
IF MachineUID=0×101fb3dd
; Nokia 6600 specific files
“..\MyFiles\FileFor6600.dat”-“!:\system\apps\MyGame\MyData.dat”
ELSEIF MachineUID=0×101f466a
; Nokia 3650 specific files
“..\MyFiles\FileFor3650.dat”-“!:\system\apps\MyGame\MyData.dat”
ELSE
; Files for other devices
“..\MyFiles\FileForOthers.dat”-“!:\system\apps\MyGame\MyData.dat”
ENDIF
就可以生成一個(gè)支持多平臺(tái)的安裝文件,除了機(jī)器UID外,還有很多屬性,如內(nèi)存和CPU的標(biāo)識(shí):
注意,機(jī)器UID和Product UID是不同的,見(jiàn)下:
Nokia 7650 0×101F4FC3
Nokia 3650 0×101F466A
Nokia 6600 0×101FB3DD
Nokia 9210/9290 0×10005E33
Nokia N-Gage 0×101F8C19
Win32 Emulator 0×10005F62
可以使用如下的代碼來(lái)找出該設(shè)備的機(jī)器UID:
#include //and link with hal.lib
TInt machineUid = 0;
HAL::Get(HALData::EmachineUid, machineUid);
如何按字節(jié)讀取文件
1.RFile::Read()
TInt Read(TDes8& aDes,TInt aLength) const;
Description
Reads specified number of bytes of binary data from file — synchronous overload.
2.Typedef TText8
typedef unsigned char TText8;
如何取出Symbian手機(jī)中的信
方法有兩個(gè):
1 確定出他們的路徑,用文件的方式讀;
2 用系統(tǒng)給這兩個(gè)部分提供的API
通訊錄方面的(別人的代碼網(wǎng)上找的):
_LIT(KNameLabel,”Name”);
_LIT(KMobileLabel,”Mobile”);
_LIT(KName,”Steve”);
_LIT(KMobile,”+8613900000000″);
// Open the default contacts database:
CContactDatabase* contactsDb = CContactDatabase::OpenL();
CleanupStack::PushL(contactsDb);
// Create a contact card and add some fields:
CContactItem* contact = CContactCard::NewLC();
CContactItemField* field = CContactItemField::NewLC(KStorageTypeText, KUidContactFieldFamilyName);
field->SetMapping(KUidContactFieldVCardMapUnusedN);
field->SetLabelL(KNameLabel);
field->TextStorage()->SetTextL(KName);
contact->AddFieldL(*field);
CleanupStack::Pop();
field = CContactItemField::NewLC(KStorageTypeText, KUidContactFieldPhoneNumber);
field->SetMapping(KUidContactFieldVCardMapTEL);
field->SetLabelL(KMobileLabel);
field->TextStorage()->SetTextL(KMobile);
contact->AddFieldL(*field);
CleanupStack::Pop();
// Add the new contact to the database and set it as the own card:
contactsDb->AddNewContactL(*contact);
contactsDb->SetOwnCardL(*contact);
CleanupStack::PopAndDestroy(2); // contact contactsDb
短信的:
CMsvEntry或 CMsvServerEntry
怎么使用BUTTON 類創(chuàng)建一個(gè) BUTTON
S60里面好像沒(méi)有BUTTON的類吧
1.好像沒(méi)有必要做BUTTON,觸發(fā)事件使用MENU就可以了
2.如果非要做的話,可以嘗試的下面的簡(jiǎn)單方法
2.1 使用一個(gè)LABEL(設(shè)置一下邊框?qū)傩钥梢允惯@個(gè)LABEL像一個(gè)所謂的BUTTON)
2.2 可以在該LABEL的所處CONTAINER的
OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
處理KEY事件(判斷該LABEL擁有FOCUS)
圖標(biāo)資源的讀取與儲(chǔ)存結(jié)構(gòu)
可以在AknView類中定義如下的圖標(biāo)數(shù)組進(jìn)行儲(chǔ)存圖標(biāo)數(shù)據(jù)結(jié)構(gòu),這種結(jié)構(gòu)有圖表位圖和蒙板(mask)
CArrayPtr* iIconArray;
具體實(shí)現(xiàn)方法:
iIconArray->AppendL(CEikonEnv::Static()->CreateIconL(iMbmFile, EMbmFile1, EMbmFile1_mask));
在需要貼圖標(biāo)的地方用這個(gè)數(shù)組句柄引用即可
一段左軟鍵菜單的控制代碼
要求:1點(diǎn)了左軟鍵之后,就相當(dāng)與點(diǎn)了ok鍵。
2 :把左軟鍵菜單的地方由option改為select
// My.rss
RESOURCE EIK_APP_INFO
{
menubar = r_bmpmanip_menubar;
// cba = R_AVKON_SOFTKEYS_OPTIONS_EXIT;
cba = R_AVKON_SOFTKEYS_SELECT_BACK; // see “epoc32\include\avkon.rsg”
}
// MyAppUi.cpp
void CMyAppUi::HandleCommandL(TInt aCommand)
{
switch(aCommand)
{
case EAknSoftkeySelect: // see “epoc32\include\avkon.hrh”
{
// left softkey is pressed…
}
…
}
}
}
如何在CAknGrid上繪制背景圖
從CAknGrid派生自己的子類,然后自己draw,如:
void CYourGrid:raw(const TRect& aRect) const
{
CWindowGc& gc = SystemGc();
gc.DrawBitmap(aRect, aYourBitmap);
CAknGrid:raw(aRect);
}
兩種從資源文件中讀取常量的方法
第一種 是老的方法了 要先 #include 才可以用
TBuf<64> buf;
CEikonEnv::Static()->ReadResource(buf,R_APP_LABEL);
R_APP_LABEL 就是我們?cè)谫Y源文件中定義的常量
第二種 新方法 要先 #include
HBufC* buf;
buf=StringLoader::LoadLC(R_APP_LABEL);
在此之前要求先把資源文件給加進(jìn)來(lái)噢, 格式 #include < 項(xiàng)目名.rsg>
如何取得imei
#ifndef __WINS__
TPlpVariantMachineId imei;
PlpVariant::GetMachineIdL(imei);
aImei.Copy(imei);
#else
如何在Series 60窗體上繪制標(biāo)簽
這是一種在Series 60窗體上顯示標(biāo)簽的方法。你可以在電量圖標(biāo)或信號(hào)圖標(biāo)旁邊顯示一個(gè)標(biāo)簽,為此需要用程序?qū)崿F(xiàn)。我使用了從CCoeControl繼承的CIndicatorIcon 這個(gè)類。你需要象這樣創(chuàng)建ConstructL():
void CIndicatorIcon::ConstructL()
{
iMyWindowGroup = RWindowGroup(iCoeEnv->WsSession());
User::LeaveIfError(iMyWindowGroup.Construct((TUint32)&iMyWindowGroup));
iMyWindowGroup.SetOrdinalPosition(0, ECoeWinPriorityAlwaysAtFront);
iMyWindowGroup.EnableReceiptOfFocus(EFalse);
CreateWindowL(&iMyWindowGroup);
// 默認(rèn)設(shè)置指示標(biāo)簽靜止
SetIndicatorIconL(EIndicatorIconAppActive);
ActivateL();
}
在ConstructL()中,我調(diào)用了另一個(gè)函數(shù) SetIndicatorIconL()設(shè)置標(biāo)簽:
void CIndicatorIcon::SetIndicatorIconL(TIndicatorIcon aIndicatorIconType, TBool aRedraw)
{
switch(aIndicatorIconType)
{
case EIndicatorIconEmpty:
iIndicator = CEikonEnv::Static()->CreateBitmapL(KSysIconFile, EMbmAvkonQgn_prop_empty);
iIndicatorMask = CEikonEnv::Static()->CreateBitmapL(KSysIconFile, EMbmAvkonQgn_prop_empty_mask);
break;
case EIndicatorIconAppActive:
iIndicator = CEikonEnv::Static()->CreateBitmapL(KSysIconFile, EMbmAvkonQgn_bt_connect_on);
iIndicatorMask = CEikonEnv::Static()->CreateBitmapL(KSysIconFile, EMbmAvkonQgn_bt_connect_on_mask);
break;
case EIndicatorIconAppInactive:
iIndicator = CEikonEnv::Static()->CreateBitmapL(KSysIconFile, EMbmAvkonQgn_prop_bt_audio);
iIndicatorMask = CEikonEnv::Static()->CreateBitmapL(KSysIconFile, EMbmAvkonQgn_prop_bt_audio_mask);
break;
default:
break;
}
SetRect(TRect(TPoint(KIndicatorPosX, KIndicatorPosY),iIndicator->SizeInPixels()));
// 如果 aRedraw == ETrue 從新繪制畫布
if(aRedraw)
{
DrawNow();
}
}
你需要跳過(guò)CCoeControl的Draw()函數(shù)代碼如下 :
void CIndicatorIcon::Draw(const TRect& aRect) const
{
CWindowGc& gc = SystemGc();
gc.Clear();
gc.SetBrushStyle(CGraphicsContext::ENullBrush);
gc.BitBltMasked(TPoint(aRect.iTl.iX, aRect.iTl.iY),
iIndicator,
TRect(TPoint(0, 0), iIndicator->SizeInPixels()),
iIndicatorMask,
ETrue);
}
現(xiàn)在把這些行加入到程序AppUi類的ConstructL()中:
iIndicatorIcon = CIndicatorIcon::NewL();
// 下一行將畫標(biāo)簽并繪制到屏幕上
iIndicatorIcon->SetIndicatorIconL(CIndicatorIcon::EIndicatorIconAppInactive, ETrue);
判斷E盤是否可用
TDriveInfo driveInfo;
TInt error = fs.Drive(driveInfo, EDriveE);
User::LeaveIfError(error);
if (driveInfo.iDriveAtt == KDriveAbsent)
{
// drive E is absent
}
Reference: “How to retrieve drive and volume information”
http://www.symbian.com/developer ... eExample.guide.html
讀取symbian上文件的例子
RFile igpFile;
RFs fs;
TInt aSeek = 0;
TInt aFileSize;
TBuf16 igpName16;
TParse parse ;
parse.Set(CEikonEnv::Static()->EikAppUi()->Application()->AppFullName(), NULL, NULL);
TBuf16<128> igpFullName ;
igpFullName.Copy (parse.DriveAndPath()) ;
igpFullName.Append (_L(”dice1.igp”));
fs.Connect();
// Write to file for later usage
igpFile.Open( fs,
igpFullName,
EFileRead | EFileStream );
igpFile.Seek( ESeekEnd, aSeek );
aFileSize = aSeek;
aSeek = 0;
igpFile.Seek( ESeekStart, aSeek );
aFileBuffer = HBufC8::NewL( aFileSize );
igpFile.Read( aFileBuffer->Des (), aFileSize );
igpFile.Close();
fs.Close();
正確響應(yīng)FORM的OK和BACK事件
TBool CMyForm::OkToExitL ( TInt aButtonId )
{
if (aButtonId == EAknSoftkeyOk )
{
…..
}
else if( aButtonId == EAknSoftkeyBack )
{
……
}
}
流讀取windows編寫的txt文件
// Open file1
_LIT(KMyFile,”c:\\documents\\file1″);
RFile myFile;
User::LeaveIfError(myFile.Open(fs,KMyFile,EFileShareExclusive|EFileWrite
));
// Write to current file position: start of file
_LIT8(KWriteBuf,”write data”);
myFile.Write(KWriteBuf);
// Read from position 0: start of file
TBuf8<6> readBuf1;
myFile.Read(0,readBuf1); // readBuf1 is now “write ”
// Read from current position
TBuf8<4> readBuf2;
myFile.Read(readBuf2); // readBuf2 is now “data”
得到CEikEdwin輸入的數(shù)據(jù)
TBuf<128> buf;
CEikEdwin* edwin = STATIC_CAST(CEikEdwin*, Control);
edwin->GetText(buf);
Symbian生成隨機(jī)數(shù)的方法
無(wú)論開發(fā)什么程序,尤其是類似紙牌類游戲和拼圖類,以及俄羅斯方塊之類的游戲,
隨機(jī)數(shù)發(fā)生器是必不可少的。標(biāo)準(zhǔn)c語(yǔ)言里面有seed()和rand()用來(lái)生成種子和數(shù)值
在symbian平臺(tái)下面,用什么方法呢?下面就是一個(gè)例子
TTime theTime( KAknExNoteInitializeTime );
theTime.UniversalTime();
TInt64 randSeed( theTime.Int64() ); // 采用時(shí)間初始化隨機(jī)數(shù)種子
TInt number( Math::Rand( randSeed ) % KAknExNoteRandomNumberRange ); // 這里就是調(diào)用了
生成的結(jié)果放在number中。
Symbian中把字符串變成數(shù)字的方法
我們知道C語(yǔ)言中又很方便的函數(shù),很多種方法可以把字符串變成數(shù)字,
比如
char * p = “100″ ;
int a;
a = atoi(p) ; // 此時(shí)a的值就是100了。
或者用這種辦法也可以,就是慢點(diǎn):
sscanf(p, “%d”, &a) ; 這樣也可以達(dá)到同樣的效果。
但是symbian開發(fā)環(huán)境中遇到這種情況,我們?cè)撛趺醋瞿兀?br />
我們可以考慮采用TLex類,來(lái)實(shí)現(xiàn)同樣的功能。
TBufC buffer = _L(”124″) ;
TLex8 lex;
TInt value;
lex.Assign((const unsigned char*) buffer.Ptr());
if(lex.Val(value) == KErrNone) {
// 證明轉(zhuǎn)換沒(méi)有問(wèn)題,你可以在value中使用buffer里面的字符串格式的數(shù)據(jù)了。
}
Symbian應(yīng)用程序中如何備份和載入
在S60 3rd中,默認(rèn)情況下將不被支持。支持備份將使你的應(yīng)用程序用戶界面更加友好,做備份的用戶(或者只有一小部分)期望自己的所有應(yīng)用程序可以被備份。讓我們來(lái)滿足這些用戶的需求,大多數(shù)情況下,這是非常容易的……
使應(yīng)用程序可以備份文件的另一個(gè)原因是Symbian Signed。它不是一個(gè)強(qiáng)制的,但是,你的應(yīng)用程序沒(méi)有意識(shí)到備份的問(wèn)題,你必須通知Test House 或者他們可能認(rèn)為你的備份功能失敗。再說(shuō)一次,大多數(shù)情況下,備份是非常簡(jiǎn)單的。
程序備份基礎(chǔ)
如果你想使應(yīng)用程序具備備份功能,以下是最起碼要做到的(也就是說(shuō),只能執(zhí)行和相應(yīng)的資源文件,沒(méi)有數(shù)據(jù)可以被支持):
1. 寫一個(gè)backup_registration.xml文件,內(nèi)容如下:
CODE:
2. 添加它到你的PKG文件
CODE:
“backup_registration.xml”-”!:\private\\backup_registration.xml”
添加私有數(shù)據(jù)到你的備份文件
另外一個(gè)常見(jiàn)的需求就是保存數(shù)據(jù)內(nèi)容到你的私有文件夾(位置在\private\)。添加以下申明到你的backup_registration.xml 文件中(使用標(biāo)簽):
CODE:
你也可以保存所有內(nèi)容到”nobackup” 私有目錄:
CODE:
你也可以指定些文件代替文件夾:
CODE:
添加公共文件到備份文件中
在前面的內(nèi)容中,“\”目錄被指定為應(yīng)用程序的私有目錄。如何保存那些在私有數(shù)據(jù)以外的數(shù)據(jù)呢?這個(gè)也很簡(jiǎn)單,你可以使用另外的一個(gè)XML標(biāo)簽??梢杂?br />
標(biāo)簽來(lái)替換
,路徑相對(duì)于你手機(jī)的根目錄(不需要指定驅(qū)動(dòng)器):
CODE:
所知到的Bug
不幸的是,包含一些bug會(huì)影響備份和重新載入特性:
1. 位于C:\System 的數(shù)據(jù)不被支持:非工作區(qū),除非指定數(shù)據(jù)到其他位置……
2. 使用開發(fā)證書(developer certificate),應(yīng)用程序的備份和載入會(huì)失敗。這一點(diǎn)是很可怕的:你測(cè)應(yīng)用程序的試備份恢復(fù)僅僅只能在你注冊(cè)了自產(chǎn)生證書(self- generated certificate)的時(shí)候。如果你使用開發(fā)證書(developer certificate)是不行的,你的應(yīng)用程序?qū)⒛軌騻浞?,但是恢?fù)的時(shí)候會(huì)失敗。
作者不能計(jì)算在第二點(diǎn)上到底花費(fèi)了多少時(shí)間,作者說(shuō)至少花費(fèi)了一個(gè)下午的時(shí)間去嘗試用開發(fā)證書(developer certificate)測(cè)試它。
Symbian程序中的觀察者模式
Symbian程序中的觀察者模式
在這個(gè)站點(diǎn)上有很多關(guān)于Symbian程序外表的文章,很少有關(guān)于架構(gòu)設(shè)計(jì)的觀點(diǎn)。在以下的文中中,我介紹一下在Symbian應(yīng)用程序中的觀察者模式,我會(huì)用一些有意義的類名來(lái)代表整個(gè)Symbian程序的設(shè)計(jì)流程。在這個(gè)應(yīng)用程序中,將告訴你在一個(gè)Symbian程序中如何使用 Engine和前臺(tái),UI接口,和用戶直接的交互。在文章中,我已經(jīng)給了一種解決的方案。在接下來(lái)的文章種,我將介紹另外一種方法,通過(guò)內(nèi)嵌類。讓我們開始應(yīng)用程序的引擎類和它的觀察者,我們創(chuàng)建了一個(gè)觀察者接口 MObserver,定義如下:
CODE:
class MObserver
{
public:
virtual void CallbackFunction1() = 0;
};
接口,它有一個(gè)純虛函數(shù),它必須被一個(gè)創(chuàng)建類實(shí)現(xiàn)。在我們的例子中,Engine(引擎類)將實(shí)現(xiàn)它:
CODE:
class Engine : public MObserver
{
public: Engine(CAppUi& aAppUi);
void CallbackFunction1();//From MObserver
void DoSomething();
Subject& GetSubject();
private: Subject* iSubject;
CAppUi& iAppUi;
};
從名字可以清晰的看出,Engine類有一個(gè)Subject類,他是實(shí)際上在后臺(tái)工作的類;CAppUi 類是核心與視圖的用戶接口。引擎創(chuàng)建一個(gè)Subject類,通常在Symbian程序中,CAppUi 類是通過(guò)veiw類表現(xiàn)數(shù)據(jù)到用戶接口的(UI)。
Subject類申明如下:
CODE:
class Subject
{
public:
Subject(MObserver& aObserver);
void DoSomething();
private:
MObserver& iObserver;
};
很明顯,Subject類鏈接了它的觀察者iObserver。Symbian程序在一般情況下,在后臺(tái)通過(guò)一些異步函數(shù),Subject類將繼承至 CActive類而工作。這里有一個(gè) DoSomething()將調(diào)用一些異步函數(shù),這個(gè)函數(shù)也將調(diào)用MObserver中的CallbackFunction1()。 CallbackFunction1 函數(shù)將更新AppUi 應(yīng)用程序或引擎和UI中相關(guān)的表現(xiàn)形式。因此讓我們來(lái)看看CAppUi類的申明:
CODE:
class CAppUi
{
public:
CAppUi();
Engine& GetEngine();
void PrintToUI(char* msg);
virtual ~CAppUi();
private:
Engine* iEngine;
};
AppUi類的作用是,創(chuàng)建應(yīng)用程序的引擎。記住,應(yīng)用程序和Engine已經(jīng)循環(huán)的引用,整個(gè)的流程如下:
AppUi將創(chuàng)建引擎;
Engine創(chuàng)建Subject;
AppUi通過(guò)一些菜單命令調(diào)用Engine中的DoSometing函數(shù);
Engine將委派一些任務(wù)通過(guò)Subject類的DoSometing函數(shù);
Subject的DoSometing函數(shù)將通知通過(guò)CallbackFunction1創(chuàng)建Observer;
Subject的DoSometing函數(shù)看上去如下:
CODE:
void Subject::DoSomething()
{ //Call the Asynchronous function
//Now Notify the Observer regarding this.
iObserver.CallbackFunction1();
}
Observer中的這個(gè)回調(diào)函數(shù)將打印AppUi中消息通過(guò)函數(shù)PrintToUi。這個(gè)函數(shù)將呈現(xiàn)從Engine得到的消息到Veiw中。
希望這篇文章能講清楚一些Symbian入門者對(duì)于如何使用UI的疑惑。
IMPORT_C關(guān)鍵字釋義
在Symbian程序中我們經(jīng)常會(huì)看到IMPORT_C這個(gè)關(guān)鍵字,它是C:\Symbian\8.0a\S60_2nd_FP2_SC\epoc32\include下e32def.h文件里面定義的一個(gè)宏.
原定義如下:
#define IMPORT_C __declspec(dllexport)
那么__declspec(dllexport)又是什么東東呢?
先看代碼:
以下是在dev-c++里建立自已的dll時(shí)的dll.h里面的代碼,這里面有一個(gè)_declspec(dllexport)
#ifndef _DLL_H_
#define _DLL_H_ //防重復(fù)定義
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */
DLLIMPORT void HelloWorld (void);
#endif /* _DLL_H_ */
上面代碼里面的_delcspce(dllexport)被定義為宏,這樣可以提高程序的可讀性!這個(gè)的作用是將函數(shù)定義為導(dǎo)出函數(shù),也就是說(shuō)這個(gè)函數(shù)要被包含這個(gè)函數(shù)的程序之外的程序調(diào)用!本語(yǔ)句中就是:void Helloword(void)
摘自msdn:在 32 位編譯器版本中,可以使用 __declspec(dllexport) 關(guān)鍵字從 DLL 導(dǎo)出數(shù)據(jù)、函數(shù)、類或類成員函數(shù)。__declspec(dllexport) 將導(dǎo)出指令添加到對(duì)象文件
若要導(dǎo)出函數(shù),__declspec(dllexport) 關(guān)鍵字必須出現(xiàn)在調(diào)用約定關(guān)鍵字的左邊(如果指定了關(guān)鍵字)。例如:
__declspec(dllexport) void __cdecl Function1(void);
若要導(dǎo)出類中的所有公共數(shù)據(jù)成員和成員函數(shù),關(guān)鍵字必須出現(xiàn)在類名的左邊,如下所示:
class __declspec(dllexport) CExampleExport : public CObject{ … class definition … };
生成 DLL 時(shí),通常創(chuàng)建一個(gè)包含正在導(dǎo)出的函數(shù)原型和/或類的頭文件,并將 __declspec(dllexport) 添加到頭文件中的聲明。若要提高代碼的可讀性,請(qǐng)為 __declspec(dllexport) 定義一個(gè)宏并對(duì)正在導(dǎo)出的每個(gè)符號(hào)使用該宏:
#define DllExport __declspec( dllexport )
__declspec(dllexport) 將函數(shù)名存儲(chǔ)在 DLL 的導(dǎo)出表中。
如何讓程序支持皮膚功能
標(biāo)題: Form UI component要支持皮膚
設(shè)備, 軟件 版本: S60 2nd Edition, FP3, Nokia N70, Nokia N90 S60 3rd Edition
說(shuō)明:
在S60第二版,F(xiàn)P3設(shè)備上使用CAknForm UI component時(shí),如果程序不支持皮膚,則該控件將無(wú)法正確繪制。
詳細(xì)描述:
如果一個(gè)運(yùn)行在S60第二版,F(xiàn)P3設(shè)備上的程序,使用了form(CAknForm),那它必須要支持皮膚,否則程序?qū)o(wú)法繪制該表單。
我們?cè)诔绦騏I類(從CAknAppUi中繼承)的構(gòu)造函數(shù)ConstructL()中通過(guò)傳遞EAknEnableSkin參數(shù)來(lái)讓程序支持皮膚功能。
void CMyAppUi::ConstructL()
{
BaseConstructL(EAknEnableSkin);
…
}
這個(gè)form布局的問(wèn)題在S60第二版FP3模擬器上不會(huì)出現(xiàn)。
情景重現(xiàn):
比較一下設(shè)置及不設(shè)置EAknEnableSkin情況下我們使用CAknForm的情況。
這個(gè)我們可以通過(guò)使用CAknForm類的SDK示例程序(如Form, Popupfield example)來(lái)具體。
在S60第二版,FP2設(shè)備上獲取電量狀態(tài)
標(biāo)題: 在S60第二版,FP2設(shè)備上獲取電量狀態(tài)
設(shè)備, 軟件 版本: S60 2nd Edition, FP2
說(shuō)明:
直到S60第二版,F(xiàn)P2,電量值都是通過(guò)RSystemAgent中如systAgent.GetState(KUidBatteryStrength)獲得的,但現(xiàn)在方法返回錯(cuò)誤代碼-19。那在S60第二版,F(xiàn)P2設(shè)備上是否有其他方法可供使用呢?
解決方案:
這些值在新版中確實(shí)有所改變,而公開文檔中卻并未寫上。
你可以通過(guò)使用下列值來(lái)查詢電量狀態(tài)。
Code:
// The current battery status information
const TInt KUidBatteryCStatusValue = 0×100052D8;
const TUid KUidBatteryCStatus = {KUidBatteryCStatusValue};
enum TSABatteryCStatus
{
ESACBatteryOk,
ESACBatteryLow,
ESACBatteryEmpty,
ESACPowerOff
};
// The amount of battery bars
const TInt KUidBatteryBarsValue = 0×100052D3;
const TUid KUidBatteryBars ={KUidBatteryBarsValue};
enum TSABatteryBars
{
ESABBars_0,
ESABBars_1,
ESABBars_2,
ESABBars_3,
ESABBars_4,
ESABBars_5,
ESABBars_6,
ESABBars_7
};
檢查離線模式
在S60第三版中,我們通過(guò)讀取Centrol Repository中的電話設(shè)置來(lái)檢查離線模式是否啟動(dòng)。
要獲得情景模式的設(shè)置,只有對(duì)Central Repository進(jìn)行調(diào)用才行:
Code:
#include
#include
CRepository* cr = CRepository::NewLC( KCRUidProfileEngine );
TInt value;
// Get ID of current profile
User::LeaveIfError( cr->Get( KProEngActiveProfile, value ) );
// Check value to determine the active profile
if ( value == 5 )
{
// current profile is the offline profile
}
// …
要了解更多關(guān)于Profile Engine的信息,可閱讀SDK的幫助文檔和“Profiles Engine Active Profile Settings API.”
第三版中的ETel庫(kù)
受爭(zhēng)議的ETel庫(kù)在第三版中已經(jīng)去掉了,去掉的庫(kù)包括ETel Core和ETel MM(etel.h和etelmm.h),在第三版中之后一個(gè)公共的電話API將被提供那就是CTelephony API(etel3rdparty.h和etel3rdparty.lib)
安全共享數(shù)據(jù)及數(shù)據(jù)庫(kù)加密
從Symbian OS v9.x后就不再提供數(shù)據(jù)庫(kù)加密機(jī)制了,保護(hù)你數(shù)據(jù)庫(kù)不被其他程序訪問(wèn)的唯一方法就是將數(shù)據(jù)庫(kù)文件存儲(chǔ)在你的私人數(shù)據(jù)空間。不過(guò)這樣其他程序也就沒(méi)法訪問(wèn)到它了。
Symbian OS v9.x中所介紹的安全共享數(shù)據(jù)庫(kù)的方法為,通過(guò)data caging機(jī)制保護(hù)并共享數(shù)據(jù)。
數(shù)據(jù)庫(kù)是通過(guò)DBMS client-serve API來(lái)生成并被訪問(wèn)的。數(shù)據(jù)庫(kù)文件被存儲(chǔ)在DBMS server的data cage文件夾中。DBMS server根據(jù)與此數(shù)據(jù)庫(kù)預(yù)先關(guān)聯(lián)的安全法則允許其他客戶端程序去訪問(wèn)它。這種安全法則可以規(guī)定客戶端只能具有ReadDeviceData能力。為了向數(shù)據(jù)庫(kù)寫入東西,客戶端得具有WriteDeviceData能力,和一個(gè)給定的Secure ID(SID)
不幸的是,安全法則目前只能存放在Z盤中。這意味著第三方開發(fā)者無(wú)法定義或安裝他們自己的安全法則。同樣,當(dāng)?shù)谌匠绦蛐枰褂靡粋€(gè)好的方法來(lái)同享數(shù)據(jù)庫(kù)時(shí),也沒(méi)有能使用的預(yù)先配置的法則。
如果你的程序需要訪問(wèn)一個(gè)共享數(shù)據(jù)庫(kù),那下列選項(xiàng)是可以考慮的:
將數(shù)據(jù)庫(kù)存放在一個(gè)共同目錄下(如果不需要考慮安全性問(wèn)題)
為你的服務(wù)提供一個(gè)API以訪問(wèn)存儲(chǔ)在自己
If for your applications require access to a shared database, the options available are
- share a database stored in a public folder (if there are no security concerns)
- write your own server that provides an API to access a database stored in its own data cage folder.
If data encryption needs to be used, you must provide your own encryption mechanism in both cases.
S60第三版中對(duì)messaging components(MTM)的性能需求
S60第三版上,因?yàn)槠脚_(tái)安全性的考慮,對(duì)公共DLL有很多要求。
這會(huì)在下列方面影響messaging component(MTM)的開發(fā)使用:
所有public-size MTM component都需要“ALL-TCB”屬性,因?yàn)樗麄円黄渌鹥ublic-side application所加載(這些程序擁有設(shè)置其的能力)
Public-side MTM component主要為:Client MTM, UI MTM, 以及UI Data MTM.
而private-side MTM component既Server MTM,要和加載進(jìn)程擁有一樣的能力。你的server-side MTM component應(yīng)該擁有下列能力:
ReadDeviceData, WriteDeviceData, ProtServ, NetworkControl, NetworkServices, LocalServices, ReadUserData.
Given these heavy capability requirements any MTM implementation has to go through the Symbian Signed process and will need to assign all needed UIDs from the protected UID range (0×00000000 - 0×7FFFFFFF).
實(shí)現(xiàn)Tab頁(yè)
carbide.c++編程非常考驗(yàn)人的是所有的資源必須自己定義,然后在程序中引用這些自定義的資源。這讓習(xí)慣了windows可視化編程的程序員非常的頭痛。不過(guò)也好,這樣更能讓我們清楚地了解到symbian資源文件的結(jié)構(gòu)和調(diào)用方法。
實(shí)現(xiàn)Tab頁(yè),首先要在.rss文件中定義Tab頁(yè)所需要的資源,其中包括Tab頁(yè)的數(shù)量,Tab頁(yè)的Title。然后在***AppUI.cpp 文件的construct函數(shù)中生成該Tab頁(yè)。其次,還要在***container.cpp文件的按鍵處理事件中編寫相關(guān)的代碼,以實(shí)現(xiàn)Tab頁(yè)的切換。
帶完整鍵盤的S60第三版設(shè)備上的按鍵映射
設(shè)備, 軟件 版本: S60 3rd Edition
說(shuō)明:
在一些S60第三版手機(jī)上有完整的鍵盤,其中一些鍵值只有通過(guò)FEP模式下編輯框才能獲得
詳細(xì)描述:
在Nokia E61以及E70等帶全鍵盤的機(jī)器上運(yùn)行的程序時(shí),如果要捕捉CCoeControl派生類下的按鍵事件時(shí),在FEP模式下的編輯框中是無(wú)法獲取同樣鍵值的(通過(guò)TKeyEvent::iCode)。
這是因?yàn)镼WERTY鍵盤的映射是依賴于當(dāng)前的語(yǔ)言和輸入模式的。例如,在Nokia E61上,CCoeControl派生類在數(shù)字鍵盤被按下時(shí)總是獲得1,2,3。。。。而只有在FEP模式下的編輯框中(如CEikEdwin)它才能獲取字母鍵”r”,”t”,。。。等。
注意scan codes(TKeyEvent::iScanCode)是不會(huì)受當(dāng)前語(yǔ)言或輸入模式影響的。
解決方案:
應(yīng)用程序在處理文本輸入時(shí),應(yīng)該使用表示準(zhǔn)的Avkon編輯框控件。
S60第三版SDK中MMF框架API的問(wèn)題
詳細(xì)描述:
S60第三版SDK中缺少M(fèi)MF Controller Framework頭文件和庫(kù),這樣的話,我們將不會(huì)搜索到關(guān)于MMF的信息和媒體格式插件,這將導(dǎo)致一些MMF的相關(guān)引用。如 CVideoRecorderUtility在構(gòu)造時(shí)就需要Controller和格式UIDs。
解決方案:
MMF Controller Framework的支持將有望在s60第三版后面加入
SymExpat 面向OS 9.x的端口
起初我認(rèn)為把SyEpxpat應(yīng)用于OS 9.x的端口將會(huì)引起一系列的變化。然而,結(jié)果卻并非如此。 最簡(jiǎn)單的修訂是針對(duì)xmlparse.c的. 看起來(lái)expat 開發(fā)人員把返回代碼枚舉和錯(cuò)誤代碼枚舉混為一談,因此對(duì)于主要expat 源編碼來(lái)說(shuō)更改它就足夠了。
一個(gè)稍微有點(diǎn)欺騙性的問(wèn)題是由GCCE帶來(lái)的??雌饋?lái)其似乎對(duì)XMLCALL進(jìn)行了一些定義。似乎 GCCE認(rèn)為它支持微軟擴(kuò)展,但實(shí)際上只在有些情況下可行。
我認(rèn)為這一問(wèn)題的根源是_MSC_EXTENSIONS。因此為了修訂它,首先,我們需要確定expat-config.h 是在源文件中expat.h文件之前定義的,之后便是定義XML調(diào)用并且停止運(yùn)行expat-external.h使之恢復(fù)默認(rèn)設(shè)定。
唯一的改變是讓SyExpat.cpp 文件在包含expat.h 之前包含expat-config 文件,因?yàn)樗O(shè)立了一套定義,并具體說(shuō)明了功能是怎樣輸出的,同時(shí)由此選出那些并沒(méi)有被正確處理的輸出申明。
因此,我們僅定義了空的XML調(diào)用并將其補(bǔ)充進(jìn)入編譯器主題。更多信息請(qǐng)查看expat_config.h。
現(xiàn)在便可為OS9.x充分的建立SyExpat, 并且仍舊保留其向后的兼容性。不幸的是我遇到一個(gè)關(guān)于Carbide.vs 和標(biāo)準(zhǔn)C庫(kù)的糟糕問(wèn)題,詳細(xì)情況如下:
http://discussion.forum.nokia.com/forum/showthread.php?t=75575 因此,即使項(xiàng)目在維護(hù)期,目前看起來(lái)需要解決的重要問(wèn)題首先是對(duì)OS9相關(guān)主題進(jìn)行修訂。
由HelloWorld想到的
對(duì)于一個(gè)symbian GUI應(yīng)用程序,必須實(shí)現(xiàn)四個(gè)類:
(1)應(yīng)用程序類(HelloWorldApp.cpp)
該類用于定義應(yīng)用程序的屬性,還用于生成新的空白文檔,以及傳遞UID信息。
(2)文檔類(HelloWorldDocument.cpp)
該類表示應(yīng)用程序的數(shù)據(jù)模式,負(fù)責(zé)保存和恢復(fù)應(yīng)用程序的數(shù)據(jù),以及創(chuàng)建應(yīng)用程序的用戶UI接口。
(3)應(yīng)用程序UI接口類(HelloWorldAppUi.cpp)
該類是完全不可見(jiàn)的,它創(chuàng)建一個(gè)應(yīng)用程序視圖,并且處理菜單等32位命令的相應(yīng)手段。
(4)應(yīng)用程序視圖類(HelloWorldContainer.cpp)
這是一個(gè)具體的控件類,它的目的是在屏幕上顯示應(yīng)用程序數(shù)據(jù),并允許用戶交互。
通過(guò)這幾個(gè)類的作用,可以得出一個(gè)程序的啟動(dòng)過(guò)程如下:
HelloWorldApp.cpp—–>HelloWorldDocument.cpp——>HelloWorldAppUi.cpp——>HelloWorldContainer.cpp
周期類: Cperiodic
CPeriodic* iPeriodicTimer;
iPeriodicTimer = CPeriodic::NewL( CActive::EPriorityStandard );//這條語(yǔ)句一般在ConstructL()中
void CGraphicsAppView::StartTimer()//開始啟動(dòng)時(shí)鐘
{
if ( !iPeriodicTimer->IsActive() )
{iPeriodicTimer->Start( 1, 1,
TCallBack( CGraphicsAppView::Period, this ) );//TcallBack是一個(gè)方法回調(diào)函數(shù),從使用來(lái)看,他只能回調(diào)類中的靜態(tài)方法。
}
}
TInt CGraphicsAppView::Period( TAny* aPtr )//周期啟動(dòng)函數(shù),注意,這是個(gè)靜態(tài)函數(shù),但static只在頭文件中才做了申明。
{
( static_cast( aPtr ) )->DoPeriodTask();
return ETrue;
}
void CGraphicsAppView::DoPeriodTask()//周期真正在做的事情
{
// Update the screen
CWindowGc& gc = SystemGc();
gc.Activate( *DrawableWindow() );
UpdateDisplay();///////////////////這個(gè)函數(shù)是關(guān)鍵的關(guān)鍵
gc.Deactivate();
}
void CGraphicsAppView::StopTiem()//停止時(shí)鐘
{
if ( iPeriodicTimer->IsActive() )
{
iPeriodicTimer->Cancel();
字符串類:
HBufC* textResource;
//兩種字符串附值方法
textResource = StringLoader::LoadLC( R_HEWP_TIME_FORMAT_ERROR );
textResource =iEikonEnv->AllocReadResourceL(R_EXAMPLE_TEXT_HELLO);
TBuf<32> timeAsText;
timeAsText = *textResource;
編譯命令
1. bldmake bldfiles
2. abld build wins udeb
3. abld makefile vc6
4. epoc
5. abld reallyclean
有了以上的基礎(chǔ),我們就可以編譯sis文件了. 一共分為2步:
1. 進(jìn)入到/group目錄下, 輸入bldmake bldfiles, 和以前講過(guò)的作用一樣, 然后: abld build thumb urel, “abld build”是編譯命令, “thumb urel”是編譯目標(biāo), 一般手機(jī)的格式都是thumb, 用命令行為windows編譯的話,就可以用 abld build wins udeb (urel). “udeb” 代表debug build, “urel”代表release build, 前者用于開發(fā),后者用于發(fā)行。
2. 進(jìn)入/sis, 輸入makesis Helloworldbasic.pkg, 然后Helloworldbasic.sis就被創(chuàng)建了。
怎么在一個(gè)view類中響應(yīng)按鍵消息
TKeyResponse CAknExEditorContainer9::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
{
return iListBox->OfferKeyEventL(aKeyEvent, aType);
}
Panic的含義
原意是報(bào)錯(cuò),異常,緊急狀態(tài)。
也就是程序的意外情況,symbian中用于彈出系統(tǒng)的異常對(duì)話框,并結(jié)束程序。
舉例
Most of the functions here return void because if they fail the server will panic the client.
大部分函數(shù)都返回void值,這是因?yàn)槿绻麄兂鲥e(cuò)了,那server端會(huì)通知client出了意外情況。
S60和Symbian的頭文件
#include
時(shí)會(huì)直接到系統(tǒng)包含路徑下去尋找aknappui.h
(這不同于#include “aknappui.h”,還會(huì)到用戶包含路徑中去尋找)。
系統(tǒng)包含路徑也就是在工程的.mmp文件中定義的:
SYSTEMINCLUDE \epoc32\include,
其真實(shí)的路徑也就是:
%EPOCROOT%\epoc32\include,
在你的機(jī)器上如果系統(tǒng)變量EPOCROOT=\Symbian\9.1\S60_3rd\,那么它就是\Symbian\9.1\S60_3rd \Epoc32\include,也就是說(shuō)本來(lái)是應(yīng)該能找到的,但是依據(jù)你的錯(cuò)誤,此時(shí)你的EPOCROOT=\Symbian\Symbian8.1b \bin\bak\,你可以試試把EPOCROOT設(shè)置成\Symbian\9.1\S60_3rd\。
另外工程文件夾最好放在%EPOCROOT%\Series60Ex下。
通過(guò)Uid來(lái)獲取應(yīng)用程序的路徑
TFileName f = EikAppUi( ).Application( )->AppFullName( );//得到當(dāng)前應(yīng)用的全路徑名
TParse parse;
parse.Set( f,NULL,NULL );
parse.DriveAndPath( );//得到最終的純路徑