Symbian开发——Symbian开发知识(转)
生活随笔
收集整理的這篇文章主要介紹了
Symbian开发——Symbian开发知识(转)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
調(diào)研時(shí)發(fā)現(xiàn)這邊文章,有很多寶貴經(jīng)驗(yàn),也收藏一下。
轉(zhuǎn)自另一個(gè)CSDN博客:http://blog.csdn.net/andy205214/archive/2008/04/11/2282675.aspx
?
General Hints / 一般提示學(xué)習(xí)S2,我的方法無非是:
·每天coding,多少小時(shí)你自己掌握,看你有多少時(shí)間了。
·coding的同時(shí),打開SDK Help,查里面的函數(shù)庫。
·資源管理器的“搜索”功能不能少,你可以在你的安裝目錄/series60ex里面找到Series60的范例代碼,/example這里找到Symbian的范例代碼
·范例代碼我是使用UltraEdit來察看并卻穇閱的,不要畏懼Nokia長長的example,他只是為了在一個(gè)例子里面展示能牽扯到的所有的功能,你所需要的可能只是一個(gè)類的幾行使用方法,找到那一段,把它c(diǎn)opy出來,用在你的.cpp里面理解就可以了。
前面是網(wǎng)下的,下面說說網(wǎng)上的。
·每天來這里看看首頁更新,有document就下載下來,是你所需要的就馬上看。
·看看DiscussionBoard,這里,Chinese Application Development > Symbian ,有別人的問題,你可以記住并且以后參考。
·自己遇到的問題,就在這里用AdvancedSearch找一下。
·NewLC www.newlc.com 是一個(gè)好網(wǎng)站,我發(fā)現(xiàn)的除了Forum Nokia之外唯一的S2站點(diǎn)。它里面的Tutior教學(xué)部分真的有很多好東西,我建議都給他離線瀏覽下載下來,我就是這么做的。不過它里面的論壇,我還 沒有看,主要是外國人太多,好像也都是提問的,真正解決問題的沒有這里那么好吧。
其它的,也沒有什么了,你要是想看市場,還有www.symbian.com和www.series60.com 。
中文問題
在模擬器或者真機(jī)上面顯示中文,這是一個(gè)不難的問題。
先 說說模擬器。因?yàn)槲液芫煤芫脹]有用過0.9中文版的模擬器了,所以對(duì)其情況也忘記的差不多了。我想如果是0.9中文版的模擬器,顯示中文應(yīng)該沒有什么大問 題了,不過SDK V0.9中不全的header&lib,這個(gè)會(huì)對(duì)你開發(fā)程序造成影響吧,所以我還是不建議現(xiàn)在仍然在使用SDK V0.9。
那 么使用英文版模擬器要如何顯示中文呢?其實(shí)是不可以顯示中文的。英文版的SDK中主要是說他的模擬器沒有制作成中文版,所以如果你在菜單中寫了中文,他是 無法顯示的。但是有一個(gè)例外,就是如果你在程序中實(shí)現(xiàn)Draw函數(shù)的時(shí)候使用了DrawText或者DrawTextVertical,并且事先把中文版 模擬器中的中文字體復(fù)制到了模擬器中,那么模擬器是可以顯示中文的。注意這其實(shí)是等同于“用字體在屏幕上面‘劃*’字”,其中的實(shí)現(xiàn)機(jī)理我想我還沒有什么 研究,扯遠(yuǎn)了肯定會(huì)出錯(cuò),所以大家如果有需要的話,在英文版模擬器上面Draw中文,可以復(fù)制一下中文版中的字體文件到英文版SDK的
epoc32/release/wins/udeb/z/system/fonts(大概是這里,我現(xiàn)在手邊沒有SDK來參考)
然后在DrawText之前調(diào)用一下字體就可以了。
*因?yàn)檎搲形南到y(tǒng)的訽因,我無法輸入那個(gè)關(guān)鍵的“籣”字,一橫一個(gè)田下面一個(gè)半包圍,所以暫時(shí)用這個(gè)錯(cuò)別字代替了,我目的就是說明它是Draw上去的。
在真機(jī)上面,大家顯示中文無非就是按照上面那篇文檔說的,一步一步來就可以了。
大體上,在程序中顯示中文分為固定的用戶界面中文字符串和程序運(yùn)行時(shí)生成字符串。第一類使用較多,而且也基本上可以代替第二類,所以我還是主張大家不要在你的.cpp里面寫中文字符串,雖然它是可以實(shí)現(xiàn)的。
用 戶界面中的字符串,Symbian系統(tǒng)是使用資源文件來保存并管理的。我們所需要知道的便是:在你的Project文件夾的data目錄下面,編糭你 的.RSS文件。這個(gè)文件中,你可以通過定義TBUF資源對(duì)象,來定義字符串。你定義的字符串,最好還是寫成一個(gè)假名,比如
RESOURCE TBUF r_myprj_str_somestring
? ? ? ? {
? ? ? ? buf=qtn_myprj_str_somestring;
? ? ? ? }
而這個(gè)qtn_myprj_str_somestring,你最好寫在myprj.loc里面,這樣:
#define qtn_myprj_str_somestring "Some String"
他的一個(gè)好處就是,你便于將你的程序作本地化/國際化處理。如果你的程序要做成很多語言的版本,那么你可以把你的用戶界面字符串寫成
myprj.en.loc
myprj.cn.loc
myprj.fr.loc
然后在編譯的時(shí)候,只需要在你的rss文件中include不同的loc就可以了。這個(gè)就是他系統(tǒng)實(shí)現(xiàn)機(jī)制的考慮所在。
準(zhǔn)備好了.RSS文件和.LOC文件并不是萬事大吉了,很多朋友在這里沒有試驗(yàn)成功的一個(gè)訽因就是在.RSS文件的頭部,忘了加上
注意在RSS文件重要加入
CHARACTER_SET UTF8
或者是忘記了把.LOC文件給轉(zhuǎn)換成UTF-8的格式。
我目前使用的是Windows NotePad來轉(zhuǎn)換UTF-8格式的,需要注意是如果你使用的是英文版的Windows,那么它會(huì)在LOC文件的頭部添加3個(gè)前導(dǎo)標(biāo)示字符,你需要再用UltraEdit[非UTF-8自動(dòng)辨認(rèn)模式]來刪除他們。
Descriptor/String 字符串相關(guān)
我們寫程序,幾乎很少不跟字符串打交道的,所以字符串這一塊兒自然成了一個(gè)平臺(tái)的很重要一塊兒。
因 為Symbian系統(tǒng)是面向移動(dòng)設(shè)備,用設(shè)計(jì)者的話說就是:資源受限的智能設(shè)備,另外它是基于ROM和RAM操作的,所以他們對(duì)于字符串的處理也是采用了 一套自己獨(dú)創(chuàng)的方式來進(jìn)行。這樣的機(jī)制,初學(xué)者乍看起來會(huì)很不習(xí)慣,摸不到頭腦,不知道他為什么要這么做。不過可以這樣說,跟她的內(nèi)存資源處理機(jī)制相比, 字符串方面Symbian所作的改動(dòng)還只是相當(dāng)于換了一個(gè)名稱而已,對(duì)于ISV級(jí)的開發(fā)者來說,它是在眾多Symbian系統(tǒng)中眾多獨(dú)有特性中最好掌握的 幾種之一。
在Symbian系統(tǒng)中,字符串被稱為Descriptor,你不用知道為什么,就把它當(dāng)作你熟悉的string也就好了。因 為要對(duì)字符串進(jìn)行操作,所以高級(jí)一些的平臺(tái),都把字符串寫成了一個(gè)獨(dú)立的類,當(dāng)作對(duì)象來對(duì)他們處理,而不像是C中,字符串是char[],然后有一批函數(shù) 來處理它。又考慮到 Symbian系統(tǒng)所處理的字符串有在RAM中的也有在ROM中的,而RAM又是十分寶貴的,Symbian處理字符串提供了不止一個(gè)類,就在這里有了一 點(diǎn)點(diǎn)不是那么直接的地方。
下面開始具體講解一下我的理解,
在Symbian中,字符串的抽象類是TDes,它可以是TDes16 業(yè)可以是TDes8,取決于你的程序是否處理Unicode。我們可以這樣理解, TDes就是char[],不過它不以'/0'結(jié)尾,而是把長度信息保存在了頭部,并且含有一個(gè)內(nèi)存地址來表示他的位置。正如前面所述當(dāng)今高級(jí)的平臺(tái)構(gòu) 架,都會(huì)把字符串給分裝成一個(gè)類,我們是把字符串當(dāng)作一個(gè)對(duì)象來處理的,所以抽象類我們是不能直接定義一個(gè)實(shí)例來使用的,抽象類的作用,在于傳遞函數(shù)的參 數(shù),在這個(gè)時(shí)候我們可以把函數(shù)傳遞的參數(shù)當(dāng)作最基本的抽象類來進(jìn)行處理。那么要直接使用一個(gè)字符串,我們?cè)撌褂檬裁茨?#xff1f;
情況分為兩種,如 果我們的字符串是比較短的,并且字符串的長度是相對(duì)已知的話,我們須要使用的是TBuf<len>,其中l(wèi)en表示長度。同樣,TBuf是一 個(gè)Unicode相關(guān)的類,他表示TBuf16或者TBuf8。定義這樣類型的一個(gè)字符串,我們使用這樣的語句
TBuf<100> buf100;
就 可以定義一個(gè)字符串了。然后,參看TBuf類在SDK文檔中的參考說明,我們就可以使用這樣的字符串了。注意,使用TBuf是事先知道他的大概長度的,使 用的時(shí)候不能溢出,否則會(huì)出現(xiàn)程序錯(cuò)誤而導(dǎo)致退出。另外,據(jù)說TBuf是被分配在了很寶貴的地方,所以盡量不要分配很長的TBuf,我想如果你的 TBuf長度超過了2000,哪怕是已知長度也最好換下面的第二種方式來分配好了。模擬器里面大家試驗(yàn)東西的時(shí)候可以分配很大很大的,沒有問題,只不過用 在真機(jī)上面的時(shí)候就要小心了。
另外一種,叫做HBufC,它是被分配在了Heap里面,可以在運(yùn)行時(shí)才決定他的大小,不過也不能過大。定義一個(gè)HBufC我們可以使用下面的語句
HBufC* heapBuf=HBufC::NewL(100);
這樣我們就定義了一個(gè)長度為100的heap字符串,需要注意的有幾點(diǎn)。
1,使用它地抽象類部分,也就是把它當(dāng)作字符串使用,需要用他的Des函數(shù)來返回他的TDes類,比如
heapBuf->Des()
,這樣來調(diào)用HBufC的字符串部分。
2, 因?yàn)镠eap字符串是一個(gè)新分配的對(duì)象,所以你必須在使用完之后立即手動(dòng)刪除它。我使用的是delete heapBuf;來刪除的,不過我覺得如果能夠使用Symbian系統(tǒng)中提供的CleanupStack庫來進(jìn)行刪除的話,可能會(huì)更好。我因?yàn)閷?duì)這一方面 還沒有什么研究,所以不敢在這里舉例子。
3,他的大小仍然是需要注意的,我的程序中分配過兩個(gè)0x8000長的Heap字符串,沒什么大問題。很 早很早年少無知的時(shí)候,曾綺在0.9SDK的模擬器中一下子分配了1MegaByte的HBufC,沒有任何問題。但是真機(jī)上面?_?_,我沒有試驗(yàn)過, 大家小心嘗試~~~~
最后還有一種叫做TPtrC這樣的東西,我們可以全當(dāng)他是一個(gè)指針,指向一個(gè)TDes,其實(shí)可以當(dāng)作是節(jié)省 heapBuf->Des()的鍵盤消耗,我們可以定義一個(gè)TPtrC pBuf;然后pBuf=heapBuf->Des(); 從此我們就可以把pBuf當(dāng)作一個(gè)TDes來處理了,我很少用TPtrC,所以也不太熟悉,不敢多說了。
需要注意的,
·在Symbian中,其實(shí)字符串都是按照Unicode編碼保存的TDes16。
·我不知道為何在有的時(shí)候,定義'/n'是管用的,可是在EDWIN中,我卻需要在TDes后面追價(jià)數(shù)值為0x2029的字符才可以換行。
· 論壇中,或者其它網(wǎng)站[比如www.newlc.com],有介紹TDes16和TDes8之間的互轉(zhuǎn),請(qǐng)注意如果他們不是中國人,pure chinese,請(qǐng)注意他們是否會(huì)忽略中文處理,僅僅是簡單的拋棄了高位為0的字節(jié)。如果是這樣方法,我們最好還是考慮一下。三思而后行。
平臺(tái)號(hào)及產(chǎn)品號(hào)-pkg打包
pkg file定義了安裝文件(sis)的內(nèi)容,它包括應(yīng)用程序的UID,一個(gè)支持的語言列表,目標(biāo)產(chǎn)品的UID和打包在sis的一組文件:
; MyGame.pkg
; Specifies an installation file for MyGame
;Languages
&EN
;Header
#,(0x1000ABCD),1,0,0
; Required line for Series 60 devices. Defines the target product
; UID.
(0x101F6F88), 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版本是向下兼容的。
參見下表:
Nokia 7650 0x101F6F87
Nokia 3650 0x101F7962
Nokia 9210/9290 0x10005E33
Nokia N-gage 0x101F8A64
Siemens SX1 0x101F9071
Series 60 Platform v0.9 0x101F6F88
Series 60 Platform v1.0 0x101F795F
Series 60 Platform v1.1 0x101F8201
Series 60 Platform v1.2 0x101F8202
Series 60 Platform v2.0 0x101F7960
如果程序需要依據(jù)各不同的平臺(tái)來進(jìn)行安裝,那就可以使用條件語句塊來處理,這時(shí)pkg里的語句如下:
;
; Files to install
;
IF MachineUID=0x101fb3dd
; Nokia 6600 specific files
“../MyFiles/FileFor6600.dat”-“!:/system/apps/MyGame/MyData.dat”
ELSEIF MachineUID=0x101f466a
; 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是不同的,見下:
Nokia 7650 0x101F4FC3
Nokia 3650 0x101F466A
Nokia 6600 0x101FB3DD
Nokia 9210/9290 0x10005E33
Nokia N-Gage 0x101F8C19
Win32 Emulator 0x10005F62
可以使用如下的代碼來找出該設(shè)備的機(jī)器UID:
#include <hal.h> //and link with hal.lib
TInt machineUid = 0;
HAL::Get(HALData::EmachineUid, machineUid);
File Manipulatating/文件操作
其 實(shí)這方面的操作相對(duì)于Symbian的某些其他部分來說還是跟其他平臺(tái)比較類似的,并無太大的不同。從最訽始的Standard C中的FILE結(jié)構(gòu)到C++中的stream,再到目前的各種各樣的流行的語言、腳本什么的,對(duì)文件的操作無非是打開一個(gè)用字符串指定文件名的文件,給出 打開方式(Binary or Text, Read or Write),然后獲得“文件對(duì)象”,你可以當(dāng)作這個(gè)文件的實(shí)例或者句柄什么的(Instance or Handle),知道意思就行了,反正就是這么一回事;p?_?_在我們目前的面向?qū)ο蟪绦蛑?#xff0c;如果要對(duì)文件進(jìn)行讀取或者寫入等操作,無非就是調(diào)用在這個(gè) 文件對(duì)象各種過程,比如寫入,讀取,Seek,之類的,等到用完了文件再用Close之類的過程關(guān)閉它以釋放資源。這個(gè)就是我們編成的時(shí)候大致的操作文件 的抽象描述。Symbian在這方面與其他平臺(tái)并無太大差別。
下面結(jié)合Code說說具體的操作:
上面說了Symbian在文件操 作方面與其他平臺(tái)差別不大,但是全無差別也是不可能的。因?yàn)镾ymbian系統(tǒng)是為資源受限設(shè)備設(shè)計(jì)的,這一點(diǎn)我相信大家都聽得耳朵起糨子了-_-,所以 他的文件資源也是由系統(tǒng)管理的,我們要通過建立FileServer來與系統(tǒng)的文件服務(wù)通信,以建立客戶端--服務(wù)器模式來訪問文件。說了那么玄,其實(shí)很 簡單地,也就是說我們?cè)诩兇獾氖褂梦募糠值臅r(shí)候,之前要Connet一下FileServer,之后要Close一下 FileServer,就這么簡單。
如:
Code:
RFs fs;
User::LeaveIfError(fs.Connect());
/*
* Your File Manipulatating Code Here...
*/
fs.Close();
我的Code其實(shí)并不好,如果是Symbian老手,我相信即使是簡單的fs.Connect();也會(huì)有隨后馬上進(jìn)行的CleanupStack類的操作,只是我目前還不熟悉,不敢妄自誤導(dǎo)大眾~~
下 面的就是文件了,我們?cè)赟ymbian中使用的比較“低級(jí)”或者說“底層”的訽始文件對(duì)象是通過RFile類來實(shí)現(xiàn)的,大家只要參考一下 DeveloperLibrary的這個(gè)部分就清楚了,位置是:(? Developer Library ? API Reference ? C++ API reference ? File Server Client Side ? RFile)
下面給兩個(gè)例子,來說明一下文件的打開,關(guān)閉,讀,寫,Seek等操作。
Code:
RFs fs;
User::LeaveIfError(fs.Connect());
RFile file
User::LeaveIfError(file.Open(fs, _L("C://file.foo"), EFileWrite));
TBuf8<256> buf;
file.Read(buf, 256);
file.Seek(ESeekStart, 911);
file.Write(_L8("Some thing you wanna write..."));
file.Close();
fs.Close();
注: 以上代碼沒有綺過測試,沒有綺過編譯檢查,但是綺過了對(duì)照SDK DeveloperLibrary的檢查,技術(shù)上應(yīng)該不會(huì)有什么問題。有兩點(diǎn)要說明的,在程序中寫死(HardCode)變量長度和位置什么東西還是最好 用MACRO代替,這可能是所有programmer的常識(shí)了,我并不是在教大家而是指名我的實(shí)例代碼中的不足;另一點(diǎn)就是_L8(), _L()這兩個(gè)MACRO是Symbian不支持大家再使用的了,大家最好用_LIT()或者_(dá)LIT8()來代替好了,此處僅僅為了方便使用了一下。
大 家可以很容易從DeveloperLibrary看出,RFile支持的讀寫只有TDes8這種類型,也就是說它只能以byte,或byte數(shù)組的形式寫 入或者讀出數(shù)據(jù)。如果大家想使用文本文件或者二進(jìn)制數(shù)據(jù)文件的話,就要借助更高級(jí)的文件類了,他們的使用方法仍然是大同小異。
TFileText 提供了文本文件的讀寫,從他的API Reference中很容易看出來,在我們建立好的TFileText對(duì)象上,只要Set一個(gè)RFile到它本身上面,我們就可以用這個(gè) TFileText對(duì)象來很容易的對(duì)文件(就是底層的RFile)來進(jìn)行文本文件的讀寫了。
與此類似,RFileReadStream對(duì)象,在構(gòu) 造的時(shí)候只需指明構(gòu)建在哪個(gè)RFile對(duì)象上,我們就可以方便的在這個(gè)RFile對(duì)象上進(jìn)行數(shù)據(jù)的操作,比如讀出一個(gè)32bit的整數(shù),讀出一個(gè)64比特 實(shí)型數(shù)。RFileWriteStream進(jìn)行的是寫入方面的操作,操作方式與讀入類相同,就不贅述了。
從上面的例子和說明我們可以看出,Symbian系統(tǒng)的文件操作幾乎與其他平臺(tái)沒什么太大的不同,也是符合所有的抽象文件操作要求的。對(duì)文件的操作只要我們看看DeveloperLibrary,記住幾個(gè)常用的過程,就沒有什么困難的了。
希望我寫的文字能給大家?guī)硇椭?#xff01;
為 kcomex 補(bǔ)充兩點(diǎn):
1、symbian的所有文件名中最好不好含有空格等特殊字符,負(fù)責(zé)編譯可能出錯(cuò),我用0.9SDK是這樣的。
2、 如果編譯的時(shí)候出現(xiàn)了你不知道的文件夾,請(qǐng)將mmp文件所在的文件夾中的.bat和.inf文件刪掉,用.mmp重新生成這兩個(gè)文件。我一般都是使用 mmpclick這個(gè)工具來生成的,因?yàn)槊钚挟吘共环奖恪jP(guān)于mmpclick的使用,在SDK附帶的工具中有詳細(xì)的說明。
如何給模擬器發(fā)短信
建議從諾基亞論壇上下載安裝"Nokia Connectivity Framework"。我不知道它是否支持在真機(jī)和仿真器之間互發(fā)短信,但我用它在兩個(gè)仿真器之間互發(fā)過短信,下面簡要說一下當(dāng)時(shí)的配置過程。
1. 安裝SDK
安裝S60 SDK 2.2和S60 SDK 2.3
安裝"Nokia Connectivity Framework 1.2"
2. 配置環(huán)境
打 開"Nokia Connectivity Framework",將左側(cè)窗口中的"Projects"->"Terminal SDKs"->"Series 60 2nd Ed. SDK for Symbian OS FP2 ...",和"Projects"->"Terminal SDKs"->"Series 60 2nd Ed. SDK for Symbian OS FP3 ..."拖到右側(cè)的窗口中,此時(shí)右側(cè)窗口中出現(xiàn)兩個(gè)仿真器的圖標(biāo),圖標(biāo)下側(cè)列出了該仿真器的藍(lán)牙地址和MMS/SMS號(hào)碼。
然后用鼠標(biāo)從其中一個(gè)圖標(biāo)向另一個(gè)圖標(biāo)引一條連線。
3. 啟動(dòng)環(huán)境
分別在兩個(gè)仿真器圖標(biāo)上單擊右鍵,然后從彈出式菜單中選擇"Start Product"啟動(dòng)仿真器。
4. 發(fā)送短消息
進(jìn)入某個(gè)仿真器的"Messages"應(yīng)用程序,編寫一條短信,其中"to:"域填寫另一個(gè)仿真器的SMS號(hào)碼,然后發(fā)送該短信。首次發(fā)送時(shí)會(huì)彈出對(duì)話框要求設(shè)置服務(wù)中心的號(hào)碼,隨便填個(gè)數(shù)(我填的1),點(diǎn)OK就行了。
5. 接收短消息
打開另一個(gè)仿真器的"Messages"應(yīng)用程序,就能看到"Inbox"收到了剛才發(fā)的短信。
symbian下面制作DLL 的流程
首先咱們假設(shè)要封裝一個(gè)叫做CMyClass的東西。先叢工程文件入手:
MyClass.mmp
-------------------
代碼:
TARGET MyClass.dll
TARGETTYPE??dll
UID 0x1000008d 0x10004268 //注意,這里換上你的UID
SOURCEPATH? ?../src
SOURCE? ?MyClass.cpp
SYSTEMINCLUDE? ?.
SYSTEMINCLUDE? ?/epoc32/include
SYSTEMINCLUDE? ?/epoc32/include/libc
LIBRARY euser.lib
#if defined(WINS)
deffile ./MyClassWINS.def
#else if defined(ARM)
deffile ./MyClassARM.def
#endif
NOSTRICTDEF
EXPORTUNFROZEN
好,一半已經(jīng)搞定了,再堅(jiān)持一下。
MyClass.h
--------------
代碼:
class CMyClass : public CBase
{
public: // 這些IMPORT_C開頭的家伙就是我們可以從別的程序中調(diào)用的函數(shù)
IMPORT_C static CMyClass* NewL();
IMPORT_C static CMyClass* NewLC();
IMPORT_C ~CMyClass();
public:
IMPORT_C void DoSomething();
private:
CMyClass();
void ConstructL();
};
很晚了,我偷個(gè)懶,上面的代碼只寫了重要的部分,那些個(gè)#include什么的麻煩看官們自己補(bǔ)齊吧。
MyClass.cpp
-----------------
代碼:
// DLL Entry Point。這是最重要的東西,別忘了哦,每個(gè)DLL都需要它。
GLDEF_C TInt E32Dll(TDllReason /*aReason*/)
{
return(KErrNone);
}
EXPORT_C void CMyClass::DoSomething()
{
??// 好,我承認(rèn),這個(gè)函數(shù)也許應(yīng)該叫做DoNothing才對(duì)。:-)
??return ETrue;
}
EXPORT_C CMyClass* CMyClass::NewL()
{
? ?CMyClass* self = NewLC();
? ?CleanupStack::Pop(self);
? ?return self;
}
...
其實(shí)大家注意到了,問題關(guān)鍵就在這對(duì)IMPORT_C...EXPORT_C上。這些函數(shù)就是你的DLL所定義的API接口!
好了,基本完成了,我們編譯它!abld build wins udeb
編譯結(jié)束后,你會(huì)在epoc32的那堆目錄下找到一個(gè)MyClass.lib以及生成的DLL! 是的,就這么簡單![/code]
應(yīng)用程序總是中斷的分析
檢查內(nèi)存泄漏的方法:
__UHEAP_MARK;
你得代碼中需要檢查的部分
__UHEAP_MARKEND;
無原因退出主要有以下幾個(gè)原因:
1、沒有處理Leave異常,也就是有沒有被Trap的Leave函數(shù)。所有的Leave函數(shù)必須在程序的某個(gè)地方被TRAP, TRAPD, 或TRAP_IGNORE涵蓋到。這是最初要的原因
2、訪問了非法的內(nèi)存區(qū)域
3、修改了非法的內(nèi)存區(qū)域?qū)е孪到y(tǒng)服務(wù)出錯(cuò)。這個(gè)問題可以在Symbian 9以后實(shí)現(xiàn)Platform Security之后解決
4、沒有找到需要的庫。缺少所需要的DLL文件等等
5、錯(cuò)誤的資源文件,RSC文件的版本和程序中調(diào)用所需的資源文件不一致
6、調(diào)用了系統(tǒng)不支持的功能。例如類似調(diào)用Camera功能的時(shí)候要考慮到不同手機(jī)產(chǎn)品相機(jī)的差別,需要安裝相應(yīng)的FP (Feature Pack)
如何運(yùn)行app和exe程序
Symbian有2種類型的本地程序:
APP是有GUI的程序,因此能夠被終端用戶使用
EXE通常是服務(wù)端或命令行程序,通常隱蔽的運(yùn)行。沒有GUI,不能直接從主菜單運(yùn)行
運(yùn)行指南
如果你是一個(gè)終端用戶想運(yùn)行APP:它會(huì)在你的電話菜單中列出如果它已經(jīng)安裝
當(dāng) 一個(gè)EXE程序在主菜單不可見時(shí)不能直接運(yùn)行EXE程序。試著從INBOX運(yùn)行它(如果你通過紅外或藍(lán)牙下載過它,它可能存儲(chǔ)在INBOX里)會(huì)導(dǎo)致一個(gè) 安全錯(cuò)誤。首先,你需要安裝一個(gè)文件管理器(比如FileMan或FExplorer),瀏覽它存儲(chǔ)的位置(在我的3650上INBOX的目錄在E:/ system/Mail/xxx),然后運(yùn)行它。
運(yùn)行程序
當(dāng)你知道運(yùn)行APP或EXE程序使用哪個(gè)API后是非常簡單的事。
運(yùn)行EXE程序:
#include
...
_LIT(KMyAppName, "c://system//Apps//MyApp//MyApp.exe");
EikDll::StartExeL(KMyAppName);
下面的代碼運(yùn)行APP比較復(fù)雜但允許執(zhí)行特定的文檔
#include
#include
...
_LIT(KMyAppName, "c://system//Apps//MyApp//MyApp.app");
_LIT(KMyDocName, "c://Documents//MyApp.dat");
CApaCommandLine * cmd=CApaCommandLine::NewL();
cmd->SetLibraryNameL(KMyAppName);
cmd->SetDocumentNameL(KMyDocName);
cmd->SetCommandL(EApaCommandRun);
EikDll::StartAppL(*cmd);
運(yùn)行瀏覽其他的NOKIA程序
如果你打算開始基于Series 60的ROM 程序,在NOKIA論壇查找關(guān)于外部程序查看文檔的問答可以給你帶來收獲
下面的代碼將開始瀏覽特定的頁:
#include // apgrfx.lib
void NNewLCUtils::StartBrowser(const TDesC& aUrl)
{
? HBufC* param = HBufC::NewLC( 256 );
? param->Des().Format( _L( "4 %S" ),&aUrl );
? // Wap Browser's constants UId
? const TInt KWmlBrowserUid = 0x10008D39;
? TUid id( TUid::Uid( KWmlBrowserUid ) );
? TApaTaskList taskList( CEikonEnv::Static()->WsSession() );
? TApaTask task = taskList.FindApp( id );
? if ( task.Exists() )
? {
??? HBufC8* param8 = HBufC8::NewLC( param->Length() );
??? param8->Des().Append( *param );
??? task.SendMessage( TUid::Uid( 0 ), *param8 ); // Uid is not used
??? CleanupStack::PopAndDestroy(); // param8
? } else{
??? RApaLsSession appArcSession;
??? User::LeaveIfError(appArcSession.Connect()); // connect to AppArc server
??? TThreadId id;
??? appArcSession.StartDocument( *param, TUid::Uid( KWmlBrowserUid ), id );
??? appArcSession.Close();
? }
? CleanupStack::PopAndDestroy(); // param
}
將你的程序帶到前臺(tái)或后臺(tái)
這篇文章將向你展示如何在你的程序得到或失去屏幕焦點(diǎn)的時(shí)候控制它們和怎樣控制它們。
在 焦點(diǎn)改變的時(shí)候開始。Series 60系列的框架將在程序得到或失去屏幕焦點(diǎn)的時(shí)候通過CAknAppUi::HandleForegroundEventL(TBool aForeground)發(fā)出通知。當(dāng)你的程序得到焦點(diǎn)的時(shí)候參數(shù)aForeground為ETrue,失去焦點(diǎn)的時(shí)候?yàn)镋False。
如果你需要做一些特定的操作,你需要重載這個(gè)函數(shù)。這有一個(gè)不失去焦點(diǎn)的例子
void CMyAppUi::HandleForegroundEventL(TBool aForeground)
{
? // Call Base class method
? CAknAppUi::HandleForegroundEventL(aForeground);
? if(aForeground) {
??? // We have gained the focus
??? ...
? } else {
??? // We have lost the focus
??? ...
? }
}
改變焦點(diǎn)。你總是能夠請(qǐng)求改變你程序的焦點(diǎn)使用命令TApaTask::SendToBackground() and TApaTask::BringToForeground()。下面代碼片段顯示怎樣從AppUi使用它們:
void CMyAppUi::BringToForeground()
{
// Construct en empty TApaTask object
// giving it a reference to the Window Server session
TApaTask task(iEikonEnv->WsSession( ));
// Initialise the object with the window group id of
// our application (so that it represent our app)
task.SetWgId(CEikonEnv::Static()->RootWin().Identifier());
// Request window server to bring our application
// to foreground
task.BringToForeground();
}
我沒有測試下面的代碼,但你可能可以使用下面的代碼控制其他的程序:
// Bring the application "theApp" to background
TApaTaskList tasklist(iCoeEnv->WsSession());
TApaTask task(tasklist.FindApp(_L("theApp")));
task.SendToBackground(); // or BringToForeground()
Symbian 程序編譯的過程
1. C++ BuilderX
Symbian 的開發(fā)環(huán)境似乎不是那么容易配置.不過Borland的C++ Builder對(duì)Symbian的支持比較好,里面還有專門針對(duì)Symbian開發(fā)的工具選項(xiàng)呢.不過由于Microsoft Visual C++我用得比較熟悉,而且,有Visual Assist這樣強(qiáng)大的工具支持,所以我覺得還是在Microsoft Visual C++上開發(fā)比較適合我.
2. 命令行的編譯
命令行的編譯應(yīng)該是SDK的文檔中有講解的.針對(duì)Symbian SDK中的Series60Ex的Graphics的例子還說吧.
a) 首先我們得用命令行到Series60Ex/Graphics/Group這個(gè)目錄.然后需要設(shè)置VC的環(huán)境變量,最好的辦法就是直接運(yùn)行/ Microsoft Visual Studio .NET 2003/Vc7/bin/vcvars.bat這個(gè)批處理文件.我的做法就是Group這個(gè)目錄建立一個(gè)command.bat文件,里面的內(nèi)容如下
PATH=%PATH%;D:/Microsoft Visual Studio .NET 2003/Vc7/bin
Cmd
然后,我只要在Windows里雙擊這個(gè)文件,就會(huì)自動(dòng)到這個(gè)目錄的命令提示符下,然后輸入vcvars32 + 回車,就設(shè)置好了VC的環(huán)境變量.
b) 輸入bldmake bldfiles.??是基于perl語言的操作,所以說一定要裝Perl才用使用SDK.
c) 如果是編譯生成模擬器運(yùn)行的,那么使用
??abld build wins udeb
? ? 如果是編譯生成機(jī)器上跑的,那么就使用
??abld build armi urel
編譯后,有兩個(gè)目錄是它給你生成的.如果你想重新生成,可以通過手動(dòng)刪除這兩個(gè)目錄.
工程編譯目錄:
/Symbian/6.1/Series60/Epoc32/BUILD/SYMBIAN/6.1/SERIES60/SERIES60EX/GRAPHICS/GROUP
保存的編譯的MAKE文件, OBJ文件等等.
程序在模擬器的目錄
/Symbian/6.1/Series60/Epoc32/Release/wins/UDEB/Z/SYSTEM/apps/graphics
保存了模擬器上運(yùn)行的App文件,只要?jiǎng)h除這個(gè)目錄,模擬器上就沒有這個(gè)程序了.
3. 全局非靜態(tài)變量引起的錯(cuò)誤
我在view的cpp的增加了一個(gè)Tint x;在模擬器上運(yùn)行沒有任何問題.當(dāng)我用armi方式編譯到目標(biāo)機(jī)器上的時(shí)候,出現(xiàn)了一個(gè)奇怪又經(jīng)典的錯(cuò)誤.
PETRAN - PE file preprocessor V01.00 (Build 183)
Copyright (c) 1996-2001 Symbian Ltd.
ERROR: Dll 'Graphics[10005BBE].APP' has initialised data.
make[1]: *** [../../../EPOC32/RELEASE/ARMI/UREL/GRAPHICSAPP] Error -2
make: *** [TARGETGRAPHICS] Error 2
make -r -f "/Symbian/6.1/Series60/EPOC32/BUILD/SYMBIAN/6.1S/SERIES60/SERIES60EX/BMPMANIP/GROUP/ARMI.make" FINAL CFG=UREL VERBOSE=-s
解決辦法: 1.把全局非靜態(tài)變量變成全局靜態(tài)變量,static
? ? 2.把全局變量編成類里面的成員變量
這樣個(gè)問題估計(jì)是Symbian的書上說的那樣,編譯成ARMI最后目標(biāo)的時(shí)候,編譯器要對(duì)代碼中的內(nèi)存使用進(jìn)行嚴(yán)格檢查所造成的.
http://discussion.forum.nokia.com/forum/showthread.php?s=&threadid=27446
從Symbian 9設(shè)備的文件管理器運(yùn)行EXE文件
Symbian 9 設(shè)備將所有的Exe文件定位與“/sys/bin”文件夾下,大多數(shù)情況下,我們不能從文件管理器來訪問它。在這里有一個(gè)很好的方式來實(shí)現(xiàn)如何從一個(gè)S60 3rd的設(shè)備上啟動(dòng)exe文件。
當(dāng) 我們初次拿到S60 3rd設(shè)備,準(zhǔn)備移植程序到這個(gè)平臺(tái)時(shí),我們多次發(fā)現(xiàn)一些問題。在PKG文件腫,會(huì)發(fā)現(xiàn)一些錯(cuò)誤,exe文件被寫入錯(cuò)誤的文件夾。在之前的版本中,exe 文件放在“/sys/bin“目錄下,使用我們的SysExplorer(Eric Bustarret開發(fā)的文件管理系統(tǒng)),我們嘗試啟動(dòng)那些可見的exe文件,我們驚奇的發(fā)現(xiàn),它啟動(dòng)了,相當(dāng)與在“/sys/bin”下。
因此,如果你真的需要啟動(dòng)exe文件:
1。拷貝“/sys/bin”下的exe文件
2。復(fù)制它到一個(gè)可見目錄
3。使用SysExplorer,到該目錄運(yùn)行它
CCoeControl類中Draw()函數(shù)的調(diào)試
自定義控件往往通過重載CCoeControl:: Draw() 方法來實(shí)現(xiàn)它的填充。然而,當(dāng)你單步調(diào)試代碼的時(shí)候,每個(gè)指令沒有立即顯示到屏幕上,因?yàn)樗峭ㄟ^window服務(wù)實(shí)現(xiàn)的。
慶幸的是,你可以改變它,你可以將每次畫圖都立即顯示到屏幕上,添加這段代碼到你的AppUi::ConstructL()中:
CODE:
#ifdef _DEBUG
iEikonEnv->WsSession().SetAutoFlush(ETrue);
#endif
這段代碼將強(qiáng)制每個(gè)圖形上下文繪制命令,立即顯示出來,這樣可以避免window服務(wù)緩沖后刷新。
這意味著,你可以看到每次畫圖代碼而產(chǎn)生的效果,到發(fā)布版中,記住去掉它,否則他將影響程序的運(yùn)行效率。
在S60 3rd的手機(jī)上顯示所有已安裝程序的Uid
一個(gè)應(yīng)用程序它可以顯示設(shè)備上所有已安裝程序的Uid。
該程序從S60 2.x 移植到 S60 3.x
S60 2.x的源代碼可以在Forum Nokia 找到,下面的代碼是S60 3.0的。
概要:
以下代碼將顯示手機(jī)上安裝的應(yīng)用程序的Uid,它使用了下面的類。
CODE:
? ?? ???RApaLsSession iLsSession;
? ?? ???MAppUidObserver& iObserver;
? ?? ???RArray<TAppInfo> iApps;
? ?? ? class TAppInfo
? ?? ???{
? ?? ?? ?? ?? ???public:
? ?? ?? ? TInt32 iAppUid;
? ?? ?? ? TApaAppCaption iAppCaption;? ?? ?? ?? ?? ?
? ?? ???};
? ?? ?? ?void CAppUidViewerEngine::AppsToUiL()
? ?? ???{
? ?? ???TApaAppInfo apaAppInfo;
? ?? ???TAppInfo appInfo;
? ?? ???iApps.Reset();
? ?? ???// Get info on all apps, then iterate through each app
? ?? ???User::LeaveIfError(iLsSession.GetAllApps());
? ?? ???while(iLsSession.GetNextApp(apaAppInfo) == KErrNone)
? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ? appInfo.iAppCaption = apaAppInfo.iCaption;
? ?? ?? ?? ?? ? appInfo.iAppUid = apaAppInfo.iUid.iUid;
? ?? ?? ?? ?? ? User::LeaveIfError(iApps.Append(appInfo));
? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?
? ?? ???//??iObserver.AppsFoundL(iApps);
? ?? ???}
以上主要代碼。
這里是源代碼文件: [attach]531[/attach]
在運(yùn)行時(shí)為S60程序提供多國語言支持
我準(zhǔn)備示范,如何使應(yīng)用程序在運(yùn)行時(shí)支持多國語言。下面的例子中,我使用了3種語言:英語、法語和德語。
修改MMP文件
第一步是修改MMP文件。在MMP文件中你可以看到這樣一行:
CODE:
LANG? ?? ?? ?? ?? ? SC
修改成:
CODE:
LANG? ?? ?? ?? ?? ? 01 02 03
創(chuàng)建3種語言文件
我們將支持3種語言,英語、法語、德語,本地文件的擴(kuò)展名分別為:l01,l02和l03。你可以在本地化使用所有的字符。
修改LOC文件
現(xiàn)在你需要修改成下面的LOC文件
CODE:
// 01 = (British) English
#ifdef LANGUAGE_01
? ?? ???#include "MultiLang.l01"
#endif
// 02 = French
#ifdef LANGUAGE_02
? ?? ???#include "MultiLang.l02"
#endif
// 03 = German
#ifdef LANGUAGE_03
? ?? ???#include "MultiLang.l03"
#endif
修改YourAppAif.rss文件
YourAppaif.rss 文件中需要像這樣本地化你的應(yīng)用程序標(biāo)題:
CODE:
RESOURCE AIF_DATA
? ? {
? ? caption_list=
? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ? CAPTION { code=01; caption="MultiLang"; }, // Eglish
? ?? ?? ?? ?? ? CAPTION { code=02; caption="MultiLang"; }, // French
? ?? ?? ?? ?? ? CAPTION { code=03; caption="MultiLang"; }??// German
? ?? ?? ?? ?? ? };
? ?? ?? ?? ?? ?
? ? app_uid=0x02a5dd83;
? ? num_icons=2;
? ? embeddability=KAppNotEmbeddable;
? ? newfile=KAppDoesNotSupportNewFile;
? ? }
修改由CAknApplication繼承來的類
重寫CEikApplication 中的 ResourceFileName() 函數(shù)到你的CYourApplicationApp 類.
CODE:
TFileName CMultiLangApp::ResourceFileName() const
? ?? ???{
? ?? ???return TFileName();
? ?? ???}
修改AppUi 類
首先,你需要為AppUi 類中的 ConstructL()函數(shù)的BaseConstructL() 中傳遞ENonStandardResourceFile 參數(shù):
CODE:
void CMultiLangAppUi::ConstructL()
? ? {
? ? BaseConstructL( ENonStandardResourceFile );
? ? //...
? ? }
接著,在你的AppUi類中創(chuàng)建下列新的函數(shù):
CODE:
void CMultiLangAppUi::ChooseLanguageL(TInt aLanguageIndex)
? ?? ???{
? ?? ???_LIT(KResourceFileName, "MultiLang.r%02d");
? ?? ???TFileName resFileName;
? ?? ???resFileName.Format(KResourceFileName, aLanguageIndex);
#if !defined(__WINS__) && !defined(__WINSCW__)
? ?? ???// Device
? ?? ???CompleteWithAppPath(resFileName);
#else
? ?? ???// Emulator
? ?? ???resFileName.Insert(0, KEmulatorPath);
#endif
? ?? ???if (iOffset) iCoeEnv->DeleteResourceFile(iOffset);
? ?? ???iOffset = iCoeEnv->AddResourceFileL(resFileName);
? ?? ???}
現(xiàn)在你可以調(diào)用 ChooseLanguageL([LanguageIndex]) 函數(shù)來實(shí)現(xiàn)語言的切換了。
修改PKG文件
添加以下幾行到你的打包文件中。
CODE:
"/Symbian/7.0s/Series60_v21/Epoc32/data/z/system/apps/MultiLang/MultiLang.r01"? ?? ?? ?-"!:/system/apps/MultiLang/MultiLang.r01"
"/Symbian/7.0s/Series60_v21/Epoc32/data/z/system/apps/MultiLang/MultiLang.r02"? ?? ?? ?-"!:/system/apps/MultiLang/MultiLang.r02"
"/Symbian/7.0s/Series60_v21/Epoc32/data/z/system/apps/MultiLang/MultiLang.r03"? ?? ?? ?-"!:/system/apps/MultiLang/MultiLang.r03"
"/Symbian/7.0s/Series60_v21/Epoc32/data/z/system/apps/MultiLang/MultiLang_caption.r01" -"!:/system/apps/MultiLang/MultiLang_caption.r01"
"/Symbian/7.0s/Series60_v21/Epoc32/data/z/system/apps/MultiLang/MultiLang_caption.r02" -"!:/system/apps/MultiLang/MultiLang_caption.r02"
"/Symbian/7.0s/Series60_v21/Epoc32/data/z/system/apps/MultiLang/MultiLang_caption.r03" -"!:/system/apps/MultiLang/MultiLang_caption.r03"
如何判斷程序是否被自動(dòng)啟動(dòng)或者被用戶啟動(dòng)
有時(shí)候能夠檢查出在系統(tǒng)啟動(dòng)的時(shí)候哪些應(yīng)用程序被“Startup List Api(只有S60 3rd可以使用)”或者用戶啟動(dòng),和通過“Symbian Signed”,管理啟動(dòng)程序的應(yīng)用是一個(gè)很通用的程序,這篇文章將告訴你如何做到。
首先,你必須修改程序注冊(cè)文件,并在APP_REGISTRATION_INFO資源中添加一些opaque_data字段,內(nèi)容和直并不是那么重要,你只需要按下面的方式指定:
CODE:
#include <appinfo.rh>
#include <uikon.rh>? ?
RESOURCE APP_REGISTRATION_INFO
{
??...
??opaque_data = r_startup_detect;
}? ?? ?
? ?
RESOURCE NUMBER_INT8 r_startup_detect
{
value = 1;
}
當(dāng)應(yīng)用程序運(yùn)行時(shí),opaque_data和其他運(yùn)行參數(shù)將被忽略。因此,判斷是否在運(yùn)行或者不允許(區(qū)分是否應(yīng)用程序被允許在啟動(dòng)的時(shí)候或者被用戶啟動(dòng))。
這樣,你可以重載AppUI中的ProcessCommandParametersL()函數(shù)
T
CODE:
Bool CMyAppUi::ProcessCommandParametersL( CApaCommandLine &aCommandLine )
{
??if(aCommandLine.OpaqueData().Length() > 0)
??{
? ?? ?// Opaque data exists, app. has been manually started from the menu
??}
??else
??{
? ?? ?// App. has been auto-started -> exit if auto-start in settings is OFF
??}
? ?return CEikAppUi::ProcessCommandParametersL( aCommandLine );
}
你也要注意,通過Symbian Signed需要你的應(yīng)用程序有一個(gè)允許禁止自動(dòng)啟動(dòng)的屬性的選項(xiàng)設(shè)置。你需要加入操作代碼來實(shí)現(xiàn)它,在 Forum Nokia Technical Library中描敘得比較好。
這篇文章僅適用于 S60 3RD,接下來的版本也將支持這個(gè)屬性
如何在SYMBIAN60中編寫DLL
Prerequisites
Knowledge of C++ and COM.
Knowledge of Symbian Programming idioms
Introduction
Writing a polymorphic DLL involves the following steps:
Design and write interfaces.
Implement the interface.
Lets explore these in more detail:
Design and write interface consisting of method declarations.
An interface is essentially an abstract class. An example would clarify it:
class ICalculator {public:virtual TInt Sum(TInt, TInt) = 0;};
Above snippet declares a class ICalculator with one method Sum which would take 2 TInt parameters and would return a TInt value. Take a look at the name given to the class. This is done to follow a convention i.e. an interface name should start with an 'I'. Now if one wishes to implement interface ICalculator, he/she has to implement the method Sum.
COM programmers would be wondering that how it can be an interface without a UUID or something like that. Yes! in Symbian too, an interface requires a UUID. While writing an interface this is how UUID is given to it.
static const TUid KCalculator_DLLUID = {0x100039CE};static const TUid KCalculator_DLLUID_Ver1 = {0x0352D96B};class ICalculator {public:virtual TInt Sum(TInt, TInt) = 0;};
Your polymorphic interface is ready. You have to write it in a .h file so that it can be implemented in other .cpp files.
Implement the interface.
Writing a polymorphic DLL is half done when interface declaration is done. Now one would require to implement it. Implementing an interface is as simple as inheriting abstract classes. You have to inherit from an interface and implement pure virtual methods of the interface.
Again an example would help us understand this:
class CImpCalculator: public ICalculator {public:EXPORT_C CImpCalculator* NewImpClass();//function would be exposed through Function tableTInt Sum(TInt num1,TInt num2);};GLDEF_C TInt E32Dll(TDllReason) {return KErrNone;}EXPORT_C CImpCalculator* CImpCalculator::NewImpClass() {return new (ELeave) CImpCalculator;}TInt CImpCalculator::Sum(TInt num1,TInt num2) {return num1 + num2;}
The example above does something more than just implementing the interface. The class CImpCalculator has a method of its own, NewImpClass. This method has a qualifier EXPORT_C. Clearly this is the method which is exposed from the implementation class. In Symbian it is not required to export or expose all the methods from an interface. Only method which needs to be exposed is which returns the object of the interface (or should I say the implementor class?). Rest of the methods can be accessed from function table. The NewImpClass method returns a pointer to the newly created object.
E32Dll method has to be written in every Polymorohic DLL as it is required by the Symbian run time. You would get linking errors in case you forget to write it. This method is responsible to allocate thread local store for the DLL instance.
Now you are ready to compile and build your own DLL. Build it and start using it.
Lastly these DLLs are called polymorphic because one can write many implementations of the same interface. Further all the Symbian GUI applications are Polymorphic DLLs. Check the GUI SDK examples, you will find E32Dll method implemented.
That's all you would require to write a DLL on Symbian!! Note that I have tested the code on NOKIA Series 60 emulator.
定義類的問題
問題:
我使用CAknView定義了一個(gè)View類,
class CCameraAppView : public CAknView.....
并且在這個(gè)類中添加了一個(gè)自定義的CCoeControl的子類成員用來繪圖等。
CCoeControl的子類定義如下:
class CCameraAppBaseContainer : public CCoeControl, MCoeControlObserver, public MAknTabObserver,MConverterController
其中MConverterController是一個(gè)自定義的純虛類,用做接口用。
開始的時(shí)候我是將MConverterController寫在了MAknTabObserver的前面,即寫成了:
class CCameraAppBaseContainer : public CCoeControl, MCoeControlObserver, public MConverterController,MAknTabObserver
這時(shí)候在使用winscw udeb方式編譯的時(shí)候不會(huì)出現(xiàn)任何錯(cuò)誤,但是當(dāng)使用gcce urel方式編譯的時(shí)候卻會(huì)出現(xiàn)如下錯(cuò)誤:
Link Error.rodata+0xf4):undefined reference to 'non-virtual thunk to CCameraAppBaseContainer::TabChangedl(int)'
當(dāng)時(shí)研究了很久也沒弄清楚是怎么回事,后來將MConverterController和MAknTabObserver的順序改過來,就沒有錯(cuò)誤了。
這個(gè)錯(cuò)誤的產(chǎn)生到底是什么原因呢?
解決:
MAknTabObserver 類只有一個(gè)公有的成員函數(shù)TabChangedL(),第一種寫法因?yàn)闆]有寫明從MAknTabObserver的繼承方法,所以是private繼承, 也就是所有的成員函數(shù)是派生類的私有函數(shù),所以外部無法訪問TabChangedL()這個(gè)私有函數(shù).聲明派生類時(shí)明確指出派生方式 (public,private,protected)是一個(gè)好習(xí)慣.
如何才能實(shí)現(xiàn)這個(gè)非同期處理
問:
我要實(shí)現(xiàn)如下3個(gè)函數(shù)處理
GetData(TInt aRequestId) //取得數(shù)據(jù),之后NotifyResult要使用這個(gè)requestID去通知處理結(jié)果
NotifyResult(TInt aRequestId) //通知取得的結(jié)果,這個(gè)requestID要和GetData的相一致
CancelRequest(TInt aRequestId)//根據(jù)requestID取消之前的某個(gè)請(qǐng)求
現(xiàn)在處理流程是這樣的,有很多的請(qǐng)求可以同時(shí)發(fā)出,那么我該如何根據(jù)不同的requestID去實(shí)現(xiàn)Cancel呢?
GetDataA
GetDataB
GetDataC
NotifyResultA
NotifyResultB
NotifyResultC
---------------------------------------------
答:
同時(shí)發(fā)出多個(gè)導(dǎo)步請(qǐng)求需要?jiǎng)?chuàng)建相應(yīng)數(shù)量的活動(dòng)對(duì)象實(shí)例,當(dāng)然也可以創(chuàng)建一個(gè)支持請(qǐng)求隊(duì)列的活動(dòng)對(duì)象來實(shí)現(xiàn)這個(gè)需求。
問:
我起初也想針對(duì)每一個(gè)請(qǐng)求創(chuàng)建一個(gè)活動(dòng)對(duì)象。
不過不清楚用什么異步請(qǐng)求去激發(fā)每個(gè)活動(dòng)對(duì)象。
初步設(shè)想是
class CMsgItem::Public CActive
CMsgItem::RunL
{deal with the request();
NotifyResult();
}
CSample::CreatMsgItem
{
a = New CMsgItem;
//★這里用什么去發(fā)出異步請(qǐng)求呢?原來想用Timer.After,但是覺得不妥。
a.SetActive();
}
后來又打算使用消息隊(duì)列去保存請(qǐng)求,然后在CIdle長線任務(wù)處理中提取msg,去處理。
不過我還是希望用第一種方法去做,
關(guān)于如何發(fā)出異步請(qǐng)求請(qǐng)指點(diǎn)一下,除了timer還能使用別的嗎?
創(chuàng)建出來了這些活動(dòng)對(duì)象,在什么時(shí)機(jī)刪除呢?能否在Runl中調(diào)用"delete this"把自己刪除?
考慮到有可能會(huì)在RunL處理中彈出選擇對(duì)話框,有問題嗎?(考慮到RunL內(nèi)部不能停留太長時(shí)間)
還有有什么需要注意的地方,也請(qǐng)賜教。
-------------------------------------------
答:
活動(dòng)對(duì)象的請(qǐng)求操作接口負(fù)責(zé)發(fā)出異步請(qǐng)并調(diào)用SetActive(),然后在RunL()中調(diào)用通知的函數(shù).這個(gè)通知函數(shù)的接口可以添加一個(gè)活動(dòng)對(duì)象本身的指針做為參數(shù),這樣就可以在接收通知的函數(shù)中區(qū)分出是哪個(gè)活動(dòng)對(duì)象發(fā)出的請(qǐng)求了,就像Listbox的觀察器一樣:
? ?Code:
class MEikListBoxObserver
{
public:
enum TListBoxEvent
{
EEventEnterKeyPressed,
EEventItemClicked,
EEventItemDoubleClicked,
EEventItemActioned, // reported by dir tree and dir contents listboxes
EEventEditingStarted,
EEventEditingStopped,
? ?? ???EEventPenDownOnItem,
? ?? ???EEventItemDraggingActioned
};
public:
virtual void HandleListBoxEventL(CEikListBox* aListBox, TListBoxEvent aEventType)=0;
};
Symbian中的線程、進(jìn)程及同步
全局內(nèi)存塊:跨越多個(gè)進(jìn)程直接訪問的內(nèi)存塊。
創(chuàng)建自己的全局內(nèi)存塊可以通過Rchunk API類
Rchunk chk;
_LIT(KChunkName,"My Globla Chunk");
TInt rc=chk.CreateGlobal(KChunkName,0x1000,0x5000);
其中CreateGlobal()方法第一個(gè)參數(shù)指定全局內(nèi)存塊的名稱。后面兩個(gè)參數(shù)為塊指定分配給它的物理RAM和為塊保留的虛擬內(nèi)存的數(shù)量。
再其他進(jìn)程中要訪問全局內(nèi)存塊可以這樣操作。
Rchunk chk;
_LIT(KChunkName,"My Globla Chunk");
TInt rc=chk.OpenGlobal(KChunkName,0);
TInt *ptr=(TInt *)chk.Base();
可以通過*ptr直接讀寫這塊內(nèi)存。
RChunk::OpenGlobal()第一個(gè)參數(shù)指定了全局內(nèi)存塊的名稱,第二個(gè)參數(shù)用于說明塊是為只讀(1)還是可寫的(0)
可以通過RChunk::Ajust(Tint newsize)方法來擴(kuò)大塊的提交內(nèi)存尺寸。
TInt rc=chk.CreateGlobal(KChunkName,0x1000,0x5000);
例如上面創(chuàng)建了一個(gè)塊,RAM提交給它0x1000字節(jié),塊的最大尺寸是0x5000
在這種情況下,只有用于讀寫的0x1000字節(jié)的物理RAM分配給了塊。但是隨后可以擴(kuò)充該塊,例如:
chk.Ajust(0x3000)
現(xiàn)在塊被分配了0x3000字節(jié)的內(nèi)存。
信號(hào)量:
全局信號(hào)量:
創(chuàng)建全局信號(hào)量
RSemphore::CreateGlobal(const TDesc &aname,TInt aCount,TOwnerType aType=EOwnerProcess);
第一個(gè)參數(shù)是信號(hào)量的名稱,第二個(gè)參數(shù)是信號(hào)量的標(biāo)記計(jì)數(shù)。
第三個(gè)參數(shù)指定句柄的所有權(quán)。
EOwnerProcess標(biāo)記該信號(hào)量句柄可以在進(jìn)程的任何位置進(jìn)行訪問。
EOwnerThread表示它只能被創(chuàng)建的線程訪問。
打開全局信號(hào)量
RSemphore::OpenGlobal(const TDesc &aname,TOwnerType aType=EOwnerProcess);或者
RSemphore::Open(const TFindSemphore& aFind,TOwnerType aType=EOwnerProcess);
第一個(gè)函數(shù)通過信號(hào)量全名打開它。
第二個(gè)函數(shù)使用TFindSemphore類,通過包含通配符字符的部分名稱打開它。
例如_LIT(KMatchName,"MySemphore*");
TFindSemphore semName(KMatchName);
RSemphore::Open(semName)
打開一個(gè)全局的信號(hào)量。
RSemphore::Signal()給信號(hào)量的標(biāo)記數(shù)加1
RSemphore::Wait()給信號(hào)量的標(biāo)記數(shù)減1
如果Wait()發(fā)現(xiàn)減后的標(biāo)記數(shù)為負(fù)值,則Wait()阻塞,直到調(diào)用Signal()增加標(biāo)記計(jì)數(shù)才返回。
(1)使用信號(hào)量可以做為一個(gè)直接信號(hào),控制不同進(jìn)程之間執(zhí)行的流程。
(2)信號(hào)量也可以用來保護(hù)共享資源。
本地信號(hào)量:
創(chuàng)建本地信號(hào)量
TInt CreateLocal(Tint aTokenCount,TOwnerType aType=EOwnerProcess);
本地信號(hào)量沒有名字,不需要打開,通過創(chuàng)建它的RSemphore,就可以簡單地訪問它。
注意,如果把a(bǔ)Type指定為EOwnerThread,但又想在另外一個(gè)線程中使用信號(hào)量,那么,就必須使用Duplicate()方法,為該線程創(chuàng)建句柄的副本。可以查看SDK文檔中的RHandleBase::Duplicate()
symbian中的幾個(gè)API
1. 定位當(dāng)前程序,并將當(dāng)前程序的優(yōu)先級(jí)調(diào)高
TInt prio = 1001; //設(shè)置一個(gè)較高的值
//將當(dāng)前程序的窗口組設(shè)計(jì)一個(gè)高的優(yōu)先級(jí),并置為同級(jí)最前
CEikonEnv::Static()->RootWin().SetOrdinalPosition(0, prio);
2.將當(dāng)前程序的窗口組設(shè)置為最前, 可與HandleForegroundEventL 配合使用,使當(dāng)前程序使終處于最前(條件是優(yōu)先級(jí)要有足夠高,否則的話還是會(huì)被優(yōu)先級(jí)更高的程序搶占)
RWsSession ws = CEikonEnv::Static()->WsSession();
TApaTaskList tlist(ws);
TApaTask task = tlist.FindApp(KUidMyApp);??//KUidMyApp 是指要調(diào)高優(yōu)先級(jí)的程序的ID
task.BringToForeground();
或者是:
TApaTaskList taskList(CCoeEnv::Static()->WsSession());
TApaTask currentTask = taskList.FindByPos(0);
TApaTask ourAppTask = taskList.FindApp(KUidNightClockApp);
if(currentTask.ThreadId() != ourAppTask.ThreadId())
??ourAppTask.BringToForeground();
3.模擬一個(gè)按鍵消息,并發(fā)向指定窗口組
RWsSession sess=CCoeEnv::Static()->WsSession();
TWsEvent event;
TInt id=sess.FindWindowGroupIdentifier( 0, _L("*Phone?") ); //取得電話程序的窗口組
event.SetType(EEventKey);
event.SetTimeNow();
event.Key()->iCode = EKeyDownArrow; //模擬一個(gè)向下的箭頭按鍵
event.Key()->iModifiers = 0;
event.Key()->iRepeats = 0;
event.Key()->iScanCode = EStdKeyNull;
sess.SendEventToWindowGroup( id, event ); 將模擬的按鍵消息發(fā)給窗口組
給pys60以不同的屏幕顯示方式
如下就可以做到,我喜歡用全屏,嘿嘿
首先記得要裝入appuifw模塊
>>>import appuifw
然后可以選擇你想要的顯示方式
>>>appuifw.app.screen='normal' #(a normal screen with title pane and softkeys)
>>>appuifw.app.screen='large' #(only softkeys visible)
>>>appuifw.app.screen='full' #(a full screen)
Symbian平臺(tái)編碼問題
自己在開發(fā)時(shí)遇到的一些問題:<!--[if !vml]-->
1.??<!--[endif]-->將Symbian應(yīng)用程序改為中文名稱
? ? ? 修改資源文件xxx_caption.rss:
? ?? ???Code:
#include “xxx.loc”
RESOURCE CAPTION_DATA
...{
? ? caption = qtn_app_caption_string;
? ? shortcaption = qtn_app_short_caption_string;
}
? ? ? 打開xxx.loc 用記事本或UltraEdit轉(zhuǎn)成UTF-8編碼
? ?? ???Code:
CHARACTER_SET UTF8? ? //必須加這行
#define qtn_app_caption_string “程序中文名”
#define qtn_app_short_caption_string “顯示名”
2.在Nokia 7610中文機(jī)上顯示Shift-JIS編碼的日文串
? ? ? Symbian平臺(tái)以Unicode編碼,可以表示、顯示所有字符,只需將本地編碼轉(zhuǎn)為Unicode即可。
? ?? 因?yàn)橹形臋C(jī)上沒有日文字庫,所以不能用類CcnvCharacterSetConverter提供的方法
? ???(但可實(shí)現(xiàn)GBK -> Unicode)
? ? Code:
CCnvCharacterSetConverter* converter = CCnvCharacterSetConverter::NewLC();
converter->PrepareToConvertToOrFromL(KCharacterSetIdentifierShiftJis, CEikonEnv::Static()->FsSession());
/***************************************************
*上一行會(huì)異常退出,因目標(biāo)平臺(tái)沒有SJIS字庫
*但可以實(shí)現(xiàn)GBK -> Unicode,只需將KcharacterSetIdentifierShiftJis
*改為KCharacterSetIdentifierGbk
***************************************************/
TInt state = CCnvCharacterSetConverter::KStateDefault;
……
TInt ctu = converter->ConvertToUnicode(bufPtr, srcPtr, state);
? 在網(wǎng)上找了一個(gè)實(shí)現(xiàn)SJIS到Unicode轉(zhuǎn)換的函數(shù)
? ? Code: #include "cp.h"
#define is_zen(c)
? ?? ???((0x81 <= ((unsigned char) (c)) && ((unsigned char) (c)) <= 0x9f)
? ?? ???|| (0xe0 <= ((unsigned char) (c)) && ((unsigned char) (c)) <= 0xfc))
#define is_han(c)
? ?? ???((0xa0 <= ((unsigned char) (c)) && ((unsigned char) (c)) <= 0xdf))
s32_t skip_bytes(char c)
{
??if(is_zen(c)) {
? ? return 2;
??} else if (is_han(c)) {
? ? return 1;
??}
??return 0;
}
s32_t jis2utf8(char **srcbuf, s32_t *srclen, char **outbuf, s32_t *outlen) {
??unsigned char *dst;
??unsigned char *src;
??unsigned short utf8code;
??int sjiscode;
??s32_t??len;
??unsigned char *to2;
??if (! (srcbuf && srclen && outbuf && outlen))
? ? return 0;
??src = (unsigned char *)*srcbuf;
??dst = to2 = (u8_t*)malloc(*outlen);
??while (*src && ((dst - to2) < (*outlen - 4))) {
? ? len = skip_bytes(*src);
? ? if ( len == 2 ) {
? ?? ?sjiscode = (int)(*src++ & 0xff);
? ?? ?sjiscode = (int)((sjiscode << 8)|(*src++ & 0xff));
? ? } else {
? ?? ?sjiscode = (int)(*src++ & 0xff);
? ? }
utf8code = cp[sjiscode];// convert sjis code to utf8 (cp[] is conversion table array)
? ? if ( utf8code <= 0x7f ) {
? ?? ?*dst++ = (char)(utf8code & 0xff);
? ? }
? ?else if ( utf8code <= 0x7ff ){
? ?? ?*dst++ = (char)( 0xc0 | ((utf8code >> 6) & 0xff));
? ?? ?*dst++ = (char)( 0x80 | ( utf8code & 0x3f ));
? ? } else {
? ?? ?*dst++ = (char)( 0xe0 | ((utf8code >> 12) & 0x0f));
? ?? ?*dst++ = (char)( 0x80 | ((utf8code >> 6)??& 0x3f));
? ?? ?*dst++ = (char)( 0x80 | (utf8code & 0x3f));
? ? }
??}
??*dst++='';
??memcpy(*outbuf,to2,*outlen);
??free(to2);
??return strlen(*outbuf);
}
<!--[endif]-->
symbian代碼編寫方面的提醒
給自己在symbian代碼編寫方面的提醒:
(1)在控件環(huán)境下進(jìn)行文件操作,建議不要連接文件服務(wù)器,而應(yīng)該直接利用 CEikonEnv::FsSession()這樣省去了連接文件服務(wù)器的開銷;
(2)常量的判斷語句,常量應(yīng)該放在==的左邊,這樣的好處是萬一程序員誤將==寫成=也可以檢查出來,因?yàn)槌A坎荒鼙毁x值的;
(3)在程序中要善于運(yùn)用條件編譯,使得同樣的一份代碼可以適應(yīng)模擬器調(diào)試和真機(jī)的運(yùn)行;
(4)提醒自己寫函數(shù)時(shí)要注意考慮函數(shù)退出的問題,含可能退出代碼的函數(shù),函數(shù)名應(yīng)以L結(jié)尾。
如何顯示s60 3rd中文菜單
sword 222??問:
1。如何在真機(jī)中顯示中文菜單啊?
我在.rss文件中,寫上CHARACTER_SET UTF8
將rls文件存儲(chǔ)成u8-dos格式。編譯GCCE過不了,說我文件有非法字符。
2.在模擬器上如何顯示中文?
我的sdk是s60 3.0 maint的。用的是vs.net2003+carbide 2.1
beover1984 答:
最好使用EditPlus把文件轉(zhuǎn)換成UTF-8編碼
sword 222??問:
我用UE轉(zhuǎn)成的就是UTF8啊。編譯不過。郁悶中。
提示非法字符如下:
..//data//HotelAd.rls(1) : *** Unknown character '? (value 0xffffffef)
..//data//HotelAd.rls(1) : *** Unknown character '? (value 0xffffffbb)
..//data//HotelAd.rls(1) : *** Unknown character '? (value 0xffffffbf)
還有其他可能不對(duì)嗎?
60 2.0版本的我用UE轉(zhuǎn)換是對(duì)的。極度郁悶中。謝謝beover1984的回復(fù)。
beover1984 答:
用UE轉(zhuǎn)換的在3.0上可能也存在問題,我換成EditPlus就好了.
sword 222??問:
用edit plus轉(zhuǎn)換成utf8編譯通過。
謝謝beover1984的回復(fù)。
我用EPlus轉(zhuǎn)換,可以編譯了,但是,真機(jī)上運(yùn)行不了,顯示系統(tǒng)錯(cuò)誤。我自簽名,只用了ReadUserData能力。在亂碼的時(shí)候,我還是可以在真機(jī)上使用的。在模擬器上可以運(yùn)行,但是依舊是亂碼。有沒有模擬器顯示中文的辦法?
beover1984 答:
執(zhí)行abld reallyclean清理一下工程,然后重新生成一下.
cdutly 答:
如 果你用UE的話,那么在"高級(jí)--配置"中將"當(dāng)保存時(shí)寫入U(xiǎn)TF-8 BOM頭到所有UTF-8文件"去掉,再去掉"自動(dòng)檢測UTF-8". 設(shè)置好以后重新打開loc文件,你會(huì)發(fā)現(xiàn)在文件頭部會(huì)有一些亂碼字符,刪掉. 但如果你的loc是中文的話,中文將會(huì)變成很奇怪的字,不要擔(dān)心,再將"自 動(dòng)檢測UTF-8"選種然后重新打開loc及可,試試看.
如何選擇編輯器中的一段文本
問題:
比如一個(gè)用來顯示聊天記錄的編輯器,通過上下鍵需要能每次選中一段文本進(jìn)行復(fù)制或其它操作,請(qǐng)問要如何實(shí)現(xiàn)呢?
解決:
CEikEdwin::SetSelectionL()
void SetSelectionL(TInt aCursorPos, TInt aAnchorPos);
Description
Sets the text selection. Highlights the selected area and makes the new cursor position visible. Any previous selection is cancelled. This function also updates the scroll bar thumbs if present.
用什么函數(shù)來獲得當(dāng)前剩余堆內(nèi)存
問題:
現(xiàn)在的問題就是要檢測系統(tǒng)的內(nèi)存容量,當(dāng)內(nèi)存的剩余量達(dá)到一個(gè)臨界值的時(shí)候做出相應(yīng)處理。可是找不到什么辦法。搜了站內(nèi)的帖子,找到一個(gè)說是Available()可以實(shí)現(xiàn)的,但是我不能通過SDK help解決問題,最好有高人給個(gè)代碼片斷。
解決:
下面的代碼可以得到可用內(nèi)存的數(shù)量。
Code:
TMemoryInfoV1Buf info;
UserHal::MemoryInfo(info);
TInt freeMemory = info().iFreeRamInBytes;
如何對(duì)描述符讀寫數(shù)值型數(shù)據(jù)
saintrui :
TInt num = 123456;
TBuf8<64> buf;
buf.AppendNum(num);
上 面的代碼把TInt型的數(shù)字num存在描述符里后,buf中就有6個(gè)字節(jié)的數(shù)據(jù)了,每個(gè)字節(jié)分別是num中的一個(gè)數(shù)字,本來TInt是占4個(gè)字節(jié)的,我想 讓描述符用4個(gè)字節(jié)存儲(chǔ)這個(gè)num,即按num的4個(gè)字節(jié)不變地儲(chǔ)存在buf的四個(gè)字節(jié)中,而不是6個(gè)字節(jié),該如何做?
上面的問題是我在寫socket通信中碰到的,還有個(gè)問題,假如pc服務(wù)器上發(fā)送過來的數(shù)據(jù)中有個(gè)數(shù)字123456,那么手機(jī)接收后存在TBuf8的描述符中,我想把這個(gè)數(shù)字從該描述符中讀到一個(gè)TInt變量里,該怎樣讀呢?
saintrui :
解決了,symbian中不提供這樣的函數(shù),只好自己轉(zhuǎn)換。太依賴symbian了,c++的類型轉(zhuǎn)換都差點(diǎn)忘了。
把a(bǔ)的二進(jìn)制值寫到描述符中:
TInt a =123456;
TUint8* ch = (TUint8*)(&a);
TBuf8<20> buf;
buf.Append(ch,4);
從描述符中讀取二進(jìn)制TInt值:
TUint8* p = &(buf[0]);
TInt* b = (TInt*)(p);
ch2000pro:
從描述符讀出來可以這樣做:
TLex iLex(iBuf);
TInt iNum2;
iLex.Val(iNum2);
SymbianLn:
樓住的最初的做法
AppendNum就是把數(shù)字轉(zhuǎn)換成字符串存儲(chǔ),所以就變成了6個(gè)字符。
讓描述符直接指向存儲(chǔ)地址,就可以了。
因?yàn)橹羔樏枋龇饶苤赶蜃址?#xff0c;也能指向內(nèi)存地址。
可以使用TPtr8等等。
在程序啟動(dòng)后先彈出確定使用文字頁面,然后確定后繼續(xù)運(yùn)行
windnoway? 問:
---------------------------------------------------------------
我們的程序做好了
但是我想在程序剛啟動(dòng)的時(shí)候
彈出一個(gè)文字頁面“歡迎使用授權(quán)軟件”,點(diǎn)擊同意后再繼續(xù)啟動(dòng)程序
怎么來做到程序還沒有啟動(dòng)的時(shí)候顯示呢?
用甚么函數(shù)寫在甚么地方 給個(gè)例子看看?
-----------------------------------------------------------------
beover1984?? 回答:
---------------------------------------------------------------------
Code:
HBufC *header = StringLoader::LoadLC( R_ABOUT_HEADER, iCoeEnv );
HBufC *body = StringLoader::LoadLC( R_ABOUT_TEXT, iCoeEnv );
CAknMessageQueryDialog *dlg = CAknMessageQueryDialog::NewL( *body );
dlg->PrepareLC( R_AVKON_MESSAGE_QUERY_DIALOG );
dlg->SetHeaderTextL( *header );
dlg->RunLD();
CleanupStack::PopAndDestroy( 2, header );
上面的代碼可以彈出一個(gè)帶"確定"和"取消"的對(duì)話框,在UI的ConstructL()中判斷dlg->RunLD();的返回值就可以了.
--------------------------------------------------------------------------------------------
windnoway? 問:
------------------------------------------------------------------------------------------
兄弟您看一下是否正確
我在**appui.cpp中加入
#include<avkon.rsg> //for R_AVKON_MESSAGE_QUERY_DIALOG
_LIT(R_ABOUT_HEADER,"message");
_LIT(R_ABOUT_TEXT,"Copyright 2006 SE");
HBufC *header = StringLoader::LoadLC( R_ABOUT_HEADER, iCoeEnv );
HBufC *body = StringLoader::LoadLC( R_ABOUT_TEXT, iCoeEnv );
CAknMessageQueryDialog *dlg = CAknMessageQueryDialog::NewL( *body );
dlg->PrepareLC( R_AVKON_MESSAGE_QUERY_DIALOG );
dlg->SetHeaderTextL( *header );
dlg->RunLD();
CleanupStack::PopAndDestroy( 2, header );
void CFreeJoyAppUi::ConstructL()
{
BaseConstructL();
if (dlg->RunLD())
{
//這里就寫明啟動(dòng)的時(shí)候啟動(dòng)的程序了
}
}
//兄弟這樣寫沒有錯(cuò)誤吧
-------------------------------------------------------------------------------------------------------
beover1984?? 回答:
----------------------------------------------------------------------------------------------------
Code:
.......
if( !dlg->RunLD() )? //選擇"取消"退出程序
{
??? Exit();
}
VC中的CString類,在symbian中用什么解決
問題:
在VC中的CString類,可以用什么代替呢?請(qǐng)大家指教
解決:
Symbian平臺(tái)上提供了描述符用于處理字符串,其中HBufC是在heap上創(chuàng)建的,并且提供了ReAlloc()用于重新分配空間,但是不會(huì)像CString那樣在空間不夠時(shí)自動(dòng)分配,需要自己做處理.
關(guān)于在手機(jī)上安裝的問題
問題:
我用自己的SIS文件在手機(jī)上安裝之后,只出現(xiàn)圖標(biāo),但是老是打不開程序,請(qǐng)問是什么原因。
我的SIS文件是在C:/Symbian/8.0a/S60_2nd_FP2_SC/epoc32/tools下創(chuàng)建的,為什么在其他目錄下用不了makesis的? 老是提示出錯(cuò)。
解決:
把 C:/Symbian/8.0a/S60_2nd_FP2_SC/epoc32/tools這個(gè)路徑加到環(huán)境變量path中,然后重啟一下就能在任意目錄 使用makesis了,程序不能在真機(jī)上啟動(dòng)很可能是打包時(shí)少打了一些資源文件引起的,建議檢查一下PKG文件,或者編譯打包一個(gè)例子試一下.
不通過rss文件,程序手動(dòng)構(gòu)建CEikEdwin的問題
問題:
我不想用rss來構(gòu)建CEikEdwin,因?yàn)镃EikEdwin會(huì)經(jīng)常改變輸入限制。所以考程序來設(shè)置比較好。
但我一個(gè)只讓輸入英文的輸入框構(gòu)建如下:
iPSEdwin = new (ELeave) CEikEdwin;
iPSEdwin->SetContainerWindowL(*this);
iPSEdwin->ConstructL(EAknEditorFlagDefault,16,16,1);
iPSEdwin->SetInputCapabilitiesL(TCoeInputCapabilities::EWesternAlphabetic );
可運(yùn)行后發(fā)現(xiàn),只能輸入數(shù)字,右上腳的輸入法提示也沒有了。
但另外一個(gè)只讓輸入數(shù)字的輸入框構(gòu)建如下:
iIDEdwin = new (ELeave) CEikEdwin;
iIDEdwin->SetContainerWindowL(*this);
iIDEdwin->ConstructL(EAknEditorFlagDefault,16,16,1);
iIDEdwin->SetInputCapabilitiesL(TCoeInputCapabilities::EWesternNumericIntegerPositive);
這就是正常的,只有數(shù)字輸入,右上角的輸入法提示也是正確的。
我該如何設(shè)置CEikEdwin的輸入限制,不通過rss來構(gòu)建
解決:
可以使用下面的代碼實(shí)現(xiàn)只能輸入字母的限制:
Code:
iPSEdwin = new (ELeave) CEikEdwin;
iPSEdwin->SetContainerWindowL(*this);
iPSEdwin->ConstructL(EAknEditorFlagDefault,16,16,1);
iPSEdwin->SetAknEditorFlags(EAknEditorFlagLatinInputModesOnly);
壓縮SVG文件
我們可以在S60第二版,FP3的SDK中通過SVGTBINENCODE.EXE程序來對(duì)Scalable Vector Graphics(SVG)圖形文件進(jìn)行二進(jìn)制編碼和壓縮。
SVGTBINENCODE的使用方法為:
1、備份你的.svg文件——你將使用一個(gè)不可編輯的壓縮版本覆蓋原來的那個(gè)。
2、對(duì).svg文件在模擬器目錄中進(jìn)行拷貝。如%EPOCROOT%/epoc32/winscw/c/system/temp/
3、在命令行方式下,運(yùn)行svgtbinencode壓縮程序。
cd %EPOCROOT%/epoc32/release/winscw/udeb svgtbinencode -Dnogui -- c:/system/temp/sourceimage.svg
這將在同樣目錄下生成一個(gè)二進(jìn)制編碼版本的SVG圖形文件,其擴(kuò)展名為.svgb
將這個(gè).svgb文件拷貝到原來.svg文件所在位置。
刪除老的.SVG文件,因?yàn)槟銓⒁脡嚎s版本去替代它。
將這個(gè).svgb文件重命名為.svg擴(kuò)展名。
運(yùn)行MifConv.exe程序來生成一個(gè)multi-icon文件(.MIF),如果使用擴(kuò)展過的makefile(icons.mk),那這些在編譯過程中會(huì)自動(dòng)完成。
注意,MifConv無法識(shí)別.svgb擴(kuò)展名,如果你沒將其改名為.svg擴(kuò)展名那它將無法識(shí)別接收這個(gè)二進(jìn)制編碼的SVG文件。
調(diào)用掛機(jī)鍵時(shí)行為發(fā)生變化
標(biāo)題: 調(diào)用掛機(jī)鍵時(shí)行為發(fā)生變化
設(shè)備, 軟件 版本: S60 2nd Edition, Feature Pack 3? S60 3rd Edition
說明:
從S60第二版,FP3開始向后,按下掛機(jī)鍵將導(dǎo)致程序關(guān)閉。
詳細(xì)描述:
在早期S60設(shè)備上,當(dāng)我們按下掛機(jī)鍵時(shí)(就是紅色的end鍵),當(dāng)前程序?qū)?huì)切換到后臺(tái)而不會(huì)被關(guān)閉。但從S60第二版,FP3開始,當(dāng)我們按下掛機(jī)鍵時(shí)將導(dǎo)致當(dāng)前運(yùn)行的程序關(guān)閉。
情景重現(xiàn):
運(yùn)行一個(gè)第三方程序,按下掛機(jī)鍵,程序?qū)?huì)被關(guān)閉,設(shè)備會(huì)切換到主畫面。
解決方案:
這是一個(gè)改進(jìn)的特性,因此無法饒過掛機(jī)鍵操作所引發(fā)的行為。如果需要切換程序時(shí),終端用戶應(yīng)該使用菜單鍵去處理以避免掛機(jī)鍵導(dǎo)致程序的關(guān)閉。通過按1到2次菜單鍵來切換程序或返回待機(jī)畫面。
在異常發(fā)生后音頻流處于不穩(wěn)定狀態(tài)
標(biāo)題: 在異常發(fā)生后音頻流處于不穩(wěn)定狀態(tài)
設(shè)備, 軟件 版本: S60 2nd Edition, FP1, FP2, and FP3
說明:
如果程序因?yàn)楫惓6K止了音頻播放,那重新打開它的話將會(huì)引發(fā)錯(cuò)誤。
詳細(xì)描述:
如果程序因?yàn)橐粋€(gè)音頻流操作(使用CMdaAudioOutputStream或CMMFDevSound對(duì)象打開或運(yùn)行)引起中斷并終止運(yùn)行,那如果再次試圖使用如CMdaAudioOutputStream::OpenL去打開它時(shí)就會(huì)引發(fā)錯(cuò)誤。
如果想要成功再次打開那個(gè)音頻流,我們需要將設(shè)備重新啟動(dòng)。
情景重現(xiàn):
在音頻流播放出現(xiàn)異常中斷后,嘗試去調(diào)用CMdaAudioOutputStream::OpenL(),將無法得到返回,程序因此會(huì)掛起。
當(dāng)鍵盤鎖定被取消時(shí)可能會(huì)導(dǎo)致無意中將程序切換到后臺(tái)
標(biāo)題: 當(dāng)鍵盤鎖定被取消時(shí)可能會(huì)導(dǎo)致無意中將程序切換到后臺(tái)
設(shè)備, 軟件 版本: S60 2nd Edition, FP2, Nokia 6630, Nokia 6680
S60 2nd Edition, FP3, N70, N90
說明:
當(dāng)使用CAknAppUi::SetKeyBlockMode()取消鍵盤鎖定功能時(shí),一些按鍵的組合可能會(huì)導(dǎo)致程序被切換到后臺(tái)。
詳細(xì)描述:
大部分S60游戲都會(huì)將鍵鎖定模式取消,以便多鍵同時(shí)按下時(shí)不影響游戲。這可以通過調(diào)用應(yīng)用程序UI(CAknAppUi)來完成:
SetKeyBlockMode(ENoKeyBlock)
在S60第二版FP2或更新的版本中,如果為鍵盤鎖定模式取消狀態(tài),那下列按鍵組合被同時(shí)按下會(huì)導(dǎo)致程序被切換到后臺(tái):
‘7’ + ‘8’ + ‘0’ + ‘*’
‘9’ + ‘0’ + ‘#’
解決方案:
目前沒有好的解決方案,游戲設(shè)計(jì)中應(yīng)該避免用戶偶然按下上述按鍵組合。
導(dǎo)入工程到IDE時(shí)圖象資源無法生成
標(biāo)題: 導(dǎo)入工程到IDE時(shí)圖象資源可能無法生成
設(shè)備, 軟件 版本: S60 2nd Edition, FP3,S60 3rd Edition
說明:
當(dāng)我們將一個(gè)Symbian應(yīng)用程序工程導(dǎo)入到IDE時(shí)(如MetroWorks CodeWarrior或Microsoft Visual Studio),試圖編譯它,但bitmap資源會(huì)無法生成。
詳細(xì)描述:
在 S60第三版上,multi-image文件(.mbm或.mif)以及相關(guān)的image header files(.mbg)是通過mifconv圖象轉(zhuǎn)換工具生成的。是bld.inf中通過一個(gè)擴(kuò)展的makefile來完成的,這個(gè)方法在S60 2nd Edition, Feature Pack 3.就開始被支持。
這些擴(kuò)展的makefile不會(huì)在IDE中隨著工程的編譯而被執(zhí)行,因此圖片文件和頭文件將不會(huì)在編譯時(shí)自動(dòng)產(chǎn)生,通常這就導(dǎo)致工程因?yàn)槿鄙?mbg文件而失敗。
解決方案:
我們可以通過abld命令去生成這些圖片資源,到/group目錄下,輸入
bldmake bldefiles
abld resource
在此后,工程就能被順利導(dǎo)入IDE并被編譯,注意如果圖片資源(source bitmaps或SVG images)被修改了,那這個(gè)過程還要重復(fù)做一次。
? 轉(zhuǎn)自:http://www.cppblog.com/khan/archive/2007/06/18/26572.html
總結(jié)
以上是生活随笔為你收集整理的Symbian开发——Symbian开发知识(转)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中readlines是什么意
- 下一篇: python关键词挖掘_seo必备工具,