Symbian OS C++ for Windows C++ programmers Andy Weinstein, Degel Software Ltd Version 1.0, Oct 2002 1.簡介。
本文討論了當一個典型的Windows C++程式員初次接觸Symbian作業系統時可能遇到的問題。我們開發過三個成功版本Symbian作業系統的經驗使我們十分清楚在這個不算豐富穩定的環境中工作什麼才是困難的。Symbian成功的一個原因是許多手機生產商非常不希望被綁在微軟這條“賊船”上,另一個原因是Symbian整合了輕量級、一流的系統,同時又可以提供如此廣泛的功能。這裡的一些提示也許會對開發成功的Symbian作業系統應用程式有所協助。
2.文檔和資源。
對於一個普通的Windows程式員來說,他對Symbian作業系統首先注意到的方面就是相比起微軟的進階精良裝備來說,Symbian開發文檔實在是太少了。雖然這種情況正在得到改善,某些API類仍然沒有相關文檔。比如CEikRichTextEditor這個類在文檔中就沒有獨立條目。CRichText這個類包括了大多數相關功能,被收入了文檔,但你可能並不知道何時第一次使用這種控制(參見我們下面關於對象結構的說明)。
相對花費大量的人力物力去完善文檔,更簡便的方法基於這樣一種事實:Symbian提供了大量的原始碼(雖然還不是整個作業系統)和常式。程式員無需猜測許多API的行為——他們只要看看執行情況。要是這樣還不夠,Symbian對一些組件,例如Word,一樣提供了原始碼。API和常式相結合足以滿足大多數程式員的需要。
從6.0版開始,Symbian作業系統95%的原始碼是對其白金夥伴項目(Platinum Partner Program,http://www.symbian.com/partners/part-platnm.html)成員開放的。這個需要額外付費註冊。這個項目的影響之一就是某些老版本開發包的完整原始碼不再提供,取而代之的是Symbian或者Nokia公司一邊繼續完善文檔,一邊提供不斷擴充的常式。比如隨Series 60提供的文檔就有一個名為“如何操作rich text”的獨立條目(雖然CEikRichTextEditor仍然沒有條目)。
文檔中還有許多其他有用的,寫得很好的“How to”文章。在Series 60中,文檔和常式的結合使用是顯而易見的——文檔中對每一個Avkon UI類都直接引用有常式。
Windows程式員還有一個要習以為常的事情是缺乏有用的外部資源,雖然這種情況正在得到改善。《專業Symbian編程》(‘Professional Symbian Programming’ (PSP))包含了許多有用的資訊,但是作為快速參考就不太合適,而且它成書於Symbian作業系統第5版的時候——新版將於2003年早些時候面世。PSP還不算過時,但情況有所改變,尤其是在UI層次上。有本書叫《Symbian裝置無線Java》(‘Wireless Java for Symbian Devices’)也許更新一些,可對C++開發人員沒什麼用處。還有《Symbian作業系統通訊編程》(‘Symbian OS Communications Programming’)和《Series 60及Symbian作業系統編程》(‘Programming for Series 60 and Symbian OS’)也已上架。更多細節可以在http://www.symbian.com/books/index.html找到。
線上文檔和Q-A資源確實有助於彌補空白。Symbian自己設立了“Symbian開發人員網路”,這是一個集論壇、FAQ、範例和其它有用資訊於一身的網路資源。它的地址是http://www.symbian.com/developer.Nokia也有一個類似的項目叫做“Nokia論壇”,網址位於http://www.forum.nokia.com.到底該去哪裡可並不一定,而且你貼出了問題也不一定就會有答案——這依賴於你其它的開發夥伴的與人為善。Symbian和Nokia的內部人員有時的確會出現在這裡,但是如果你希望從知道答案的那個人口中得到確切回覆,你需要付費註冊。Symbian的付費登入位址在http://www.symbian.com/partners/part-servs.html的“Partner Programs”中,Nokia的則可以從Nokia論壇的“Developer Support, Technical Case Solving”中找到。不過還是先看看免費資源吧:這裡有大量有用的最新資訊和資源,包括定時的開發包升級。
3.對象結構。
Symbian作業系統有一個需要花費時間來熟悉的方面在於他非常強大的對象結構。例如,一個列表框(list box)不是一個對象——而是四個:列表框對象(list box object)、模型(model)、視圖(view)和繪圖器(drawer)。它們之間的功能劃分是可以預期並且很符合邏輯的。
編輯控制就複雜的多。乍一看上去,它好像只有兩個主要對象:UI控制和一個包含處理文字格式設定化的文字物件。但是對格式化的操作引入了對字元格式設定化和對段落格式化的更進一步的對象。這些,按照次序,使用了獨立的mask對象來指示顯示了你希望對任何給定調用定位的格式化的API調用。所以操作文本顯示為黑體還是非黑體,同時還影響到行間距的代碼就需要用到CEikRichTextEditor、CRichText、TCharFormat、TCharFormatMask、CParaFormat和CparaFormatMask這幾個類。這裡有一段這樣的代碼:TCharFormat defaultFormat;TCharFormatMask formatMask;formatMask.SetAttrib(EAttFontStrokeWeight);CRichText* text = iDisplay->RichText();text->Reset();for (int i = 0; i < 10; ++i)
{ TPtrC boldText = getBoldPiece(i);TPtrC plainText = getRomanPiece(i);……
TInt insertPos = text->DocumentLength();text->SetInsertCharFormatL(*iCharFormat, formatMask, insertPos);text->InsertL(insertPos, boldText);text->CancelInsertCharFormat();insertPos = text->DocumentLength();text->SetInsertCharFormatL(defaultFormat, formatMask, insertPos);text->InsertL(insertPos, plainText);text->CancelInsertCharFormat();} CParaFormat paraFormat;TParaFormatMask paraFormatMask;iDisplay->RichText()->GetParaFormatL(¶Format, paraFormatMask,0, iDisplay->TextLength());paraFormatMask.ClearAll();paraFormatMask.SetAttrib(EAttLineSpacing);paraFormatMask.SetAttrib(EAttLineSpacingControl);paraFormat.iLineSpacingControl = CParaFormat::ELineSpacingExactlyInTwips;CGraphicsDevice* screenDevice = iEikonEnv->ScreenDevice();TInt paraDelta;……
TInt lineHeight = screenDevice->VerticalPixelsToTwips(iRegularFont->HeightInPixels() + paraDelta);paraFormat.iLineSpacingInTwips = lineHeight;iDisplay->RichText()->ApplyParaFormatL(¶Format, paraFormatMask, 0, iDisplay->TextLength());但是這還不是全部——關於文本視圖對象還另有天地,特別是CTextView和CTextLayout,連同他們的協助對象一起。當我們想在編輯控制中定位滾動點,以使文本的最後一行可以處於編輯控制底部之上一行的位置,我們就不得不瞭解到CTextView的存在,以及如何獲得它,還有關於CTextView::SetViewL、TViewYPosQualifier::SetHotSpot及TViewYPosQualifier::SetMakeLineFullyVisible.他們看起來是這個樣子的:TInt yPos = iDisplay->TextView()->ViewRect()。iBr.iY;TViewYPosQualifier yPosQualifier;yPosQualifier.SetHotSpot(TViewYPosQualifier::EFViewBottomOfLine);yPosQualifier.SetMakeLineFullyVisible(TViewYPosQualifier::EFViewForceLineFullyVisible);iDisplay->TextView()->SetViewL(iDisplay->TextLength(),yPos,yPosQualifier,CTextView::EFViewDiscardAllFormat);誰會想得到呢?我們的一位同事就是不相信這是就此可行的惟一途徑,但是他通過利用許多(各種各樣的)存在於各個類之中的各種API,試用了各種不同的方法來證明了這一點。
我們正在描述的這種複雜性其實是因為Symbian作業系統提供的功能實在太豐富了,理解這一點很重要。一旦你瞭解了這個領域,你就會對Symbian作業系統的對象結構是如此明智感激不盡,然後很快你就會發現你能夠預知你需要的函數藏在什麼地方。如此重複,你會發現我們剛開始的困惑現在已經變成了一種審美享受。