window ce

dows dows dows

什麼是Windows CE?
Windows CE作業系統是Windows家族中的成員,專門設計給掌上型電腦(HPCs)所使用的電腦環境。這樣的作業系統可使完整的可攜式技術與現有的Windows桌面技術整合工作。Windows Mobile 2003 for Smartphone作業系統與Windows Mobile 2003 for Pocket PC作業系統一樣,都是基於Windows CE架構的。
可見,我們日常所說的Smartphone系統和Pocket PC系統都是基於Windows CE架構的智慧型手機系統,兩者有相似之處,但又存在差別。相似之處是,兩者同屬Windows mobile系列作業系統,都是基於微軟PC的Windows作業系統演變而來,因此,它們的操作界面非常相似。同時在硬體系統上,採用微軟智慧型系統的手機一般都採用了英特爾嵌入式處理器,主頻比較高,另外,採用該作業系統的智慧型手機在其它硬體配置(如記憶體、儲存卡容量等)上也較採用其它作業系統的智慧型手機要高出許多,因此性能比較強勁,操作起來速度會比較快。但是,此系列手機也有一定的缺點,如因配置高、功能多而產生耗電量大、電池續航時間短、硬體採用成本高等缺點。
不同之處是,Smartphone基於Windows CE核心開發的,基於該作業系統的手機無需藉助手寫筆,只需用手機提供的鍵盤就能完成幾乎所有的操作,因此,使用該作業系統的手機用戶單手操作即可,而Pocket PC Phone則必須通過手寫筆才能操作,也就是說兩類系統最大的不同表現操作方式上。另外,儘管都是基於Windows系統,但在套用軟體上也不盡相同。
Windows CE程式設計之歷史簡介
為了理解Windows CE的歷史,你需要理解作業系統和使用作業系統的產品之間的區別。作業系統是微軟內部一組核心團隊開發的。他們的產品就是作業系統自身。其他團隊,比如開發Pocket PC的團隊,在作業系統即將發布的時候,獲得並使用最新版本的作業系統。這種劃分成兩部分的方式,可能對理解Windows CE是怎么發展的會產生一些混淆。下面讓我們分別看一下這兩部分的歷史--設備和作業系統自身。
設備
首批為Windows CE設計的是手持式“管理器”設備,配有480*240或640*240的螢幕和Chiclet鍵盤(計算機常用的一種鍵盤,有一個很小的矩形鍵盤)。這些設備,稱為手持式PC,在1996年首次面世。在Fall Comdex 97大會上,Windows CE 2.0,一個進行了顯著更新的作業系統版本發布了,和它配套的是類似的更新一些的硬體,具有640*240的橫向螢幕,一些是彩色的,還具有略大一些的鍵盤。
1998年1月,消費電子展覽會上,微軟宣布了兩個平台,掌上電腦(譯者註:Palm-size PC可以看作Pocket PC的前身,其中使用Windows CE 2.x的稱為Palm-size PC,使用Windows CE 3.x的稱為Pocket PC)和車載PC(譯者註:Auto PC是Windows CE的一種套用模式,多用在一些車載電腦、工業自動控制等場合,可按客戶需要修改輸入輸出方式而不限定使用原有的程式。)。掌上電腦目標直接瞄準了由Palm 0s統治的基於筆式的管理器市場。掌上電腦具有縱向顯示的特點,並配有240*320的螢幕,使用輸入筆來作為輸入方式。但是很不幸,對Windows CE愛好者來說,對這種原始掌上電腦,公眾顯然缺乏熱情。
此後,出現了一種新的迷你膝上式Windows CE設備,配備了觸摸式輸入鍵盤和VGA/Super VGA螢幕。這種設備被稱為H/PC(專業版),電池可使用10小時,並配備了微軟Pocket Office軟體改進版。這種設備中有許多具有內置Modem,一些甚至配備了thenstandard 螢幕,移動軌跡墊或者IBM軌跡球設備。
2000年4月,微軟宣布了Pocket PC,它對老式掌上電腦(Palm-size PC)做了極大的增強。最初的Pocket PC使用預發布的具有更多功能的Windows CE 3.0。Pocket PC的用戶界面也有所不同,具有更加整潔的2緯外觀和修改過的主頁-Today桌面。然而,Pocket PC最重要的特性是極大的改進了Windows CE的性能。微軟做了很多工作來調優Windows CE的性能。這些改進加上更快的CPU,可以讓系統像Pocket 管理器期望的那樣運行的更快。在這種Pocket PC里,摩爾定律使得Windows CE設備可以跨越這條線:現在硬體已經有能力提供Windows CE需要的運算能力了。
手持式PC在2000年時升級到了Windows CE 3.0。雖然這些系統(現在稱為手持式PC2000)在消費領域沒有成功,但在工業領域找到了市場。它憑藉相對低的費用,大螢幕和長時間電池能力滿足了這個機會市場。
2001年晚些時候,Pocket PC更新為Pocket PC 2002。這次發布使用了Windows CE3.0的最終發布版本,並做了一些用戶接口方面的改進。同時也增加了Pocket PC Phone版本,在Pocket PC設備中集成了蜂窩電話支持功能。這些設備具有了Pocket PC的功能,也具有蜂窩電話的聯通功能,形成了新一代的幾乎可以始終連線的移動軟體。
微軟的另一組人發布了Smart Display(譯者註:一種具有觸控螢幕的無線監視器,可以通過802.11b無線網路連線到個人計算機,並使用Windows XP Professional作業系統的“Remote Desktop”(遠程桌面)來訪問主機)。它使用Windows CE.NET 4.1系統,具有平板式設備形式,有無線網路訪問能力,有一個底座可以連線到PC上。當使用底座的時候,它可以做第2個顯示器。當不用底座的時候,它可作為PC的移動顯示器。
2003年春季,Pocket PC團隊發布了升級版的Pocket PC,稱為Pocket PC 2003。系統在用戶接口方面沒有很多變化,但由於是基於Windows CE.NET 4.2,所以在穩定性和性能方面都有了巨大改進。Pocket PC 2003還集成了藍牙支持功能,OEM廠商可以選擇是否包含該功能。
微軟還和OEM廠商合作生產基於Windows CE的蜂窩電話。這些電話中的少部分被稱為Smartphone(智慧型電話),在2002年末發布了,最初是基於Windows CE 3.0。2003年升級到了Windows CE4.2,並增加了一系列特徵,包括 .NET runtime功能。
新設備一直不斷在發布,例如 Media to Go設備,就是使用硬碟來存儲的移動視頻播放器。Windows CE作業系統的強大功能,使應用程式憑藉運行在這些設備上的簡單作業系統 超越了系統能力。
作業系統
雖然面向消費者的產品可以不斷產生新聞熱點,但最重要的開發工作仍然在作業系統自身。Windows CE從1.0之日就開始不斷演化,當它還是一個簡單的管理器作業系統時就被寄予厚望。從Windows CE 2.0開始一直持續到今日,微軟不斷發布Windows CE的嵌入式版本,使開發者可以用在他們自定義的硬體上。雖然像Pocket PC等消費平台占據了宣傳的主體,但對基本作業系統的改進是使諸如Pocket PC和Smartphone之類的設備能夠運做的基礎。
在Fall Comdex 1997大會上,Windows CE 2.0隨著手持式PC 2.0一起發布了。Windows CE 2.0增加了網路支持,包括Windows 標準網路功能,支持NDIS miniport驅動模式,以及通用NE2000網路卡驅動支持。雖然增加的COM被限制在進程內服務,但可以用來支持腳本編寫。引入了新的顯示驅動模式,可以支持像素深度,而不再是Windows CE 1.0中原始的每像素2位了。Windows CE 2.0是Windows CE作業系統中第一個與諸如H/PC等產品分離,獨立發布的版本。開發者可以購買Windows CE 嵌入式工具包(ETK),它可以讓開發者為特殊的硬體平台定製Windows CE。然而,用過ETK後,開發者會發現,這個產品的功能還沒有達到它所宣稱的目標。
隨著掌上電腦(Palm-size PC)在1998年初發布後,Windows CE又在不斷改進。雖然Windows CE 2.01沒有按ETK形式發布,但它在減少作業系統和應用程式大小方面做的努力還是值得稱道的。在Windows CE 2.01中,C運行時庫從每個EXE和DLL都要綁定的靜態程式庫中去掉了,放到了作業系統里。這極大的減小了作業系統和應用程式的大小。
1998年8月,微軟發布了H/PC,配套的發布了作業系統的新版本-2.11版。Windows CE 2.11是從未正式發布的Windows CE 2.1的服務升級包。這一年年末,Windows CE 2.11作為Windows CE平台的2.11版本,發布給了嵌入式開發者社區。該版本支持改進的對象存儲,允許要存儲的檔案大於4M。還增加了對控制台程式的支持,同時增加了MS-DOS風格的命令行解釋器CMD.exe的Windows CE支持。Windows CE2.11還增加了Fast IR,用於支持IrDA的4M紅外線標準,同時增加了一些特殊功能來支持IP多點傳送。最初的安全概念被引入:設備可以檢查和拒絕裝載沒有被認證的模組。
Windows CE 2.12也是作為2.1-白樺(Windows CE 2.1的代號)的服務包發布的。這次發布中最大的亮點是一個增強的平台Builder工具集,它具有一個圖形化的前端界面。用一個新的通知接口調整了系統操作,新的接口將不同的通知功能進行了組合。通知的用戶接口暴露在平台Builder中,允許嵌入式套用開發者定製通知對話框。微軟基於PC的Internet瀏覽器 IE 4.0也被引入到Windows CE中,稱為Genie-通用IE控制項。這個HTML瀏覽器控制項完善了簡單小巧的Pocket Internet瀏覽器。微軟訊息佇列(MMQ)也被加了進去。Windows CE 2.11中的安全功能“運行/不運行(go/no go)”也增加了“運行,但不信任(go,but don't trust)”的選項。這樣,不被信任的模組可以運行,但不能調用關鍵功能集,也不能修改註冊表的某些部分。
期待已久的Windows CE 3.0終於在2000年中發布了。這次發布是跟隨同年4月發布的Pocket PC的,它使用了Windows CE 3.0略早一些的內部版本。Windows CE 3.0最大的亮點在它的核心,核心為更好的支持實時功能而做了最佳化。增強後的核心,支持256個執行緒優先權(之前的版本是8個),可調整執行緒周期,可嵌套的中斷服務程式,並減少了核心等待時間。
Windows CE 3.0改進的地方不僅僅在核心上。一個新的COM組件被加入進來,用來完善2.0就有的進程內COM功能。新的組件支持完整的進程外COM和DCOM功能。對象存儲區域也做了改進,可以支持256M RAM了。對象存儲區域裡的檔案大小限制也提高到了32M/檔案。Platform Builder 3.0的附加的軟體包加入了更多的功能,增加了media player控制項,提高了多媒體支持。用PPTP,ICS和遠程桌面顯示功能改進了網路支持。還正式引入了DirectX API。
Windows CE接下來的一個版本,改變的不僅僅是新特性,產品的名字也改了。2001年初,Windows CE.NET 4.0發布了。這個版本里,改變了虛擬記憶體的管理方式,將每個應用程式的虛擬記憶體空間擴大了1倍。Windows CE.NET 4.0還增加了新的驅動裝載模式,服務(Services)支持,新的基於檔案的註冊選項,藍牙功能,802.11以及1394支持。具有諷刺意味的是,Windows CE.NET 4.0雖然叫.NET,但卻不支持.NET 精簡框架。
2001年末,Windows CE 4.1跟隨Windows CE 4.0之後發布了,增加了IP v6支持,Winsock2支持,一組支持applets的新功能,以及一個叫Power Manager的例子。Windows CE 4.1支持.NET 精簡框架。.NET 運行時庫作為一個快速修復包(QFE),在作業系統發布後提供的。
2003第2季度,Windows CE.NET 4.2發布了。這次升級,提供了很棒的、OEM廠商期待的新特性-在嵌入式系統上支持Pocket PC應用程式。Pocket PC特有的API,比如選單條、軟輸入法以及其它解釋器特性,被移植到基本作業系統里了。為支持名字空間擴展,瀏覽器Shell被重寫。通過在某些CPU上直接支持硬體分頁表功能,核心性能得到了改進。
簡述Win CE開發特性及忠告
最近一段時間,移動設備開發越來越多的成為了程式設計師社區的話題。移動設備主要包括智慧型手機和PDA,是嵌入式開發中很重要的一個方向。在智慧型手機領域被大多數手機廠商支持的J2ME無疑是領頭羊,微軟CE平台的SmartPhone也逐漸成為關注焦點。一直不溫不火的PDA市場,也在行業套用領域有所收穫,Pocket PC由於其開發與Windows平台的一致性而得到了開發人員的青睞。
在長期關注程式設計師論壇的過程中,我發現由於Windows CE開發的獨特性,加之多個版本並存、缺乏中文參考資料,所以論壇上充斥著大量相同的入門問題。我希望在這裡能夠為剛轉入Windows CE開發的程式設計師明晰一些概念,將現有的Windows CE版本與開發工具之間的關係給大家解釋清楚。
Windows CE與平台開發
Windows CE是微軟為嵌入式設備打造的作業系統,而嵌入式設備可謂多種多樣,這就要求CE作業系統必須是可定製的,所以微軟將Windows CE設計為模組化的作業系統。說簡單點,我們可以把Windows CE想像成一盒積木,你可以用積木搭建出任何物體,但不一定要把所有的積木都用上。
Windows CE搭建出來的物體就是平台,是適應某種有固定標準的嵌入式設備的作業系統子集,最著名的平台就是Pocket PC了,是提供給沒有鍵盤的掌上電腦使用的平台。由於平台和硬體的一致性,所以有時候我們也用平台的名稱來稱呼整個系統——硬體與作業系統的總和。
我們也可以自己開發平台,開發工具是微軟提供的Platform Builder,Platform Builder的版本號是和Windows CE的版本號一致的。
更多程式設計師關心的是應用程式的開發,而應用程式開發是針對特定平台的,我們在開發之前必須安裝目標平台的SDK,才能夠開發出適應目標平台的開發工具。
Windows CE開發環境綜述
初學者另外一個比較糊塗的概念是版本的問題,現在市面上能夠見到Windows CE的兩代產品,它們的核心分別基於Windows CE 3.0和Windows CE.NET(即4.0)。
微軟將今年剛面世的Pocket PC 2003和Smart Phone 2003統稱為Windows Mobile 2003,我們大多數時候還是習慣地沿用老稱謂。
而市面上經常見到的Pocket PC 2002是基於Windows CE 3.0的平台,而Pocket PC 2003則是基於Windows CE.NET的平台,需要注意的是,Pocket PC 2003的核心是Windows CE.NET 4.2。而SmartPhone2003也是基於Windows CE.NET的。SmartPhone的最初版本是2002,基於Windows CE 3.0的,但是微軟沒有推出SmartPhone2002的中文版。
清晰了平台與CE之間的關係,解釋平台與開發工具之間的關係就很容易了。微軟提供給應用程式開發者的工具包括:Embedded Visual Tools 3.0,其中包括Embedded Visual C++ 3.0和Embedded Visual Basic 3.0;Embedded Visual C++ 4.0和Visual Studio.NET。
開發工具的版本號是與Windows CE的版本號對應的。EVC3.0和EVB3.0是用來開發基於Windows CE 3.0平台的應用程式的,比較常見的平台有:Pocket PC 2002、Pocket PC 2000、Palm-size PC、HPC。而EVC4.0是用來開發Windows CE.NET平台的程式的,主要包括Pocket PC 2003和SmartPhone 2003。
Visual Studio.NET針對嵌入式設備開發需要SDE的支持,而VS.NET 2003中包括了SDE,不需要另外安裝。Visual Studio.NET開發的程式需要目標平台支持.NET Compact Framework。現在支持.NET Compact Framework的平台有Pocket PC 2002和Pocket PC 2003。這裡需要注意的是SmartPhone 2003是不支持.NET Compact Framework的。
EVB開發入門
微軟已經宣布EVB不再支持Windows CE.NET,所以EVB的最終版本是3.0。但由於EVB的易上手性和快速開發的特點,在VS.NET橫空出世之前,它成為Windows CE平台上快速開發的不二之選。現在EVB仍然適合Windows CE 3.0平台上小型應用程式的快速開發。如果您不是專職的Windows CE程式設計師,而只是需要在Windows CE平台上開發整個系統的一部分,那么EVB可以讓您用很短的時間開發出您想要的程式。
EVB的開發環境的搭建也是十分簡單,您可以從微軟的網站上下載EVT 2002,其中包含了EVC 3.0、EVB 3.0和Pocket PC 2002 SDK和SmartPhone 2002 SDK。按照提示將EVB和Pocket PC 2002 SDK安裝好後就可以進行開發了。SDK中包含模擬器,在沒有實際設備的情況下,可以利用模擬器來調試程式。
這裡需要注意的是,開發環境和模擬器之間是通過網路連線協定進行通訊的,所以開發所用的計算機上必須有一個活動的網路連線。如果沒有,可以安裝微軟的虛擬網卡。
EVB的開發環境與VB類似,因為Windows CE應用程式需要在模擬器或者實際設備上調試,所以我們必須選擇程式的輸出目標。如果您選擇了Emulation,在您按下運行(或F5)後,EVB將自動啟動模擬器,並把程式下載到模擬器中。
由於新的Windows CE.NET將不再支持EVB,微軟建議EVB程式設計師使用VB.NET開發新的程式,而對於原有的EVB程式也給出了遷移路徑,關於這方面的論述,您可以參考MSDN文章《Moving from eMbedded Visual Basic to Visual Basic .NET》。
EVC開發入門
無論是Win32平台還是WinCE平台,Visual C++都是一個強大的開發工具。而EVC也是WinCE上的主流開發工具。EVC支持MFC類庫的子集,可以給開發者提供最強大的支持,也使Win32平台上的VC程式設計師可以很容易地遷移到WinCE平台上。但由於MFC類庫需要一個DLL,所以對某些存儲空間有限的嵌入式設備來說,這是個很大的負擔,所以SmartPhone就不支持MFC。
說這么多,讓我們來創建一個EVC的工程。是不是和VC很像,需要提醒大家注意的是,由於嵌入式設備支持的CPU種類很多,我們在選擇創建工程類型的同時,也要把該工程所支持的CPU類型選擇好。創建工程的過程和VC是一樣的。當然不同的平台支持的工程類型是不同的,比如Pocket PC 2003有支持MFC和API的兩種工程,而SmartPhone 2003則只有支持API的一種工程。
EVC中比VC環境中多了一行下拉選單的選項,分別用來選擇:工程、SDK、CPU類型和輸出設備。以Pocket PC為例,在實際設備上調試應該選擇Win32(WCE ARMV4)Debug ,而在模擬器上則需要選擇Win32(WCE emulator)Debug。
VS.net開發入門
又來到我們的.NET時間了,我怎么說又?最近大家都被JAVA和.NET搞得頭昏腦脹了吧?不管大家怎么吵,.NET Compact Framework對於手中缺少開發利器的嵌入式程式設計師無疑是一大福音。Visual Studio .NET 2003完全支持對移動設備的開發,好了,讓我們開始一段奇幻的.NET之旅吧。
打開VS.net 2003,選File - New – Project,就打開了上面的界面。讓我們來建立一個Visual C#的工程,然後選擇Smart Device Application,然後OK。
你在這裡要選擇目標設備:Pocket PC、SmartPhone、Windows CE(指的是其他平台),下面則是選擇創建的工程類型,我們選擇“Windows Application”,左邊是選擇的平台所支持的模擬器。最後點擊OK,我們就可以進入VS.NET的主界面了。
選擇輸出設備的情況和EVB十分類似,只需要選擇輸出設備,而不用選擇CPU類型。當然了,因為.NET是運行在虛擬機上的了。在CPU類型眾多的嵌入式領域,.NET和JAVA才能真正發揮自己的強項。
當然,我們也可以選擇VB.NET作為開發智慧型設備的語言,情況和C#完全一樣。目前智慧型設備開發只支持C# 和VB.NET。愛好C++的程式設計師可能還要等上一段時間。
Windows CE 開發的忠告
可以說當我們花了大部分時間將已有的應用程式移植到Microsoft Windows CE中。一般說來,這個計畫不是太難。我們起步於Microsoft Win32代碼,當然Windows CE是基於Win32應用程式接口(API)的。有利的是,我們的應用程式(即Raima 數據管理器)有方便的使用接口,並包含一個大約由150個子函數組成的庫,這些函式都是由C語言寫成,可以用來創建、管理和訪問資料庫。
按建立應用程式的方式來說,我們原以為將它移植到Windows CE中是一項相對簡單的C語言編程練習。然而,我們不久便遇到好些困難。從粗心大意的錯誤開始,比如在基於Windows NT 的Windows CE仿真器上使用Microsoft Windows NT庫,接著又違背Windows CE的編程戒律,如"千萬不要給Unicode(國際標準組織10646標準)字元分配奇數記憶體地址"。
大約有百分之九十的問題或多或少地與Unicode有關。儘管Unicode編程不難,但是,當給單位元組字元編寫代碼時,很容易出錯(我有過許多次錯誤)。
下面這些忠告是根據我們在Windows CE上編寫Raima 數據管理器的經驗總結出來的,但我相信,在做任何其它Windows CE程式之前,它們都值得借鑑。畢竟大多數Windows開發者,當他們創建第一個Windows CE應用程式時,真正運用的是已掌握的Win32知識。
不要在仿真器上使用Windows NT庫
這裡所討論的第一個錯誤實在太愚蠢了,但我還是陷了進去,也許你也會。當用Microsoft VC++(5.0版)創建一個Windows CE程式時,你會發現,包含路徑(include)、 庫路徑(library)、及可執行程式路徑被自動調整以匹配反應目標環境的選擇。因此,比如說為Windows CE模擬器建立應用程式時,你會發現,include路徑沒有指向Win32的包含檔案(在VC目錄下),而是指向Windows CE包含檔案(在WCE目錄下)。千萬別去修改。
由於Windows CE在Windows NT下運行,所以仿真器上運行的程式能夠調用任一Windows NT動態程式庫(DLL)中的函式,即使這個DLL不是模擬器的成員也一樣。顯然,這不是很好的事,因為相同的函式也許在手持PC(H/PC)或Windows CE設備上不可用,而你的軟體最終要能在這些設備上運行。
第一次將非Unicode應用程式裝入Windows CE仿真器時,你會發現,許多正在使用的函式它都不支持,例如美國國家標準協會(ANSI)定義的字元函式strcpy()。這也許引誘你去連結Windows NT 運行時間庫,以便能解決所有問題。
如果你是剛開始用Windows CE編程,可能你能用的包含檔案和庫檔案是明顯的。答案就是,你不要採用那些在寫普通Win32或非Windows CE程式時使用的包含檔案和庫檔案。
不要混淆TCHARs和bytes
如果你正在Windows CE上寫非Unicode應用程式,你或許要將所有的字元串從單個字元(chars)轉換為寬字元(widechars)(例如,C變數類型whcar_t)。幾乎所有Windows CE支持的Win32和運行時間庫函式都要求寬字元變數。Windows 95不支持Unicode,然而,為了使程式代碼具有可移植性,你要儘可能採用tchar.h中定義的TCHAR類型,不要直接使用wchar_t
TCHAR是定義為wchar_t還是char,取決於預處理器的符號UNICODE是否定義。同樣,所有有關字元串處理函式的宏,如_tcsncpy宏,它是定義為Unicode函式wcsncpy還是定義為ANSI函式strncpy,取決於UNICODE是否定義。
在現存的Windows應用程式中,有些代碼也許暗示字元長為單位元組。這在給字元串分配記憶體時經常用到,例如:
int myfunc(char *p)
{
char *pszFileName;
pszFileName = malloc(MAXFILELEN);
if(pszFileName)
strncpy(pszFileName, p, MAXFILELEN);
/*etc*/
在這段代碼中,分配的記憶體塊應該寫作(MAXFILELEN * sizeof(char)),但是大多數程式設計師喜歡將它簡化為MAXFILELEN,因為對於所有的平台來說sizeof(char)的值等於1。然而,當你用TCHARS代替多個字元時,很容易忘記這種固有的概念,於是將代碼編寫成下面的形式:
int myfunc(TCHAR *p)
{
TCHAR *pszFileName;
PszFileName = (TCHAR*)malloc(MAXFILELEN);
If (pszFileName)
tcsncpy(pszFileName, p, MAXFILELEN);
/*etc*/
這是不行的。它馬上會導致出錯。這裡的錯誤在於malloc函式中指定變數大小為bytes,然而_tcsncpy函式中使用的第三個變數卻指定為TCHARs而不是bytes。當UNICODE被定義時,一個TCHAR等於兩個位元組數(bytes)。
上述代碼段應該改寫為:
int myfunc(TCHAR *p)
{
TCHAR *pszFileName;
PszFileName = (TCHAR*)malloc(MAXFILELEN * sizeof(TCHAR));
if(pszFileName)
tcsncpy(pszFileName, p, MAXFILELEN);
/*etc*/
不要將Unicode 字元串放入奇數記憶體地址
在Intel系列處理器上,你可以在一奇數記憶體地址儲存任何變數或數組,不會導致任何致命的錯誤影響。但在H/PC上,這一點不一定能行 ? 你必須對大於一個位元組的數據類型小心謹慎,包括定義為無符號短型(unsigned short) 的wchar_t。當你設法訪問它們的時候,將它們置於奇地址會導致溢出。
編輯器經常在這些問題上提醒你。你無法管理堆疊變數地址,並且編輯器會檢查確定這些地址與變數類型是否相匹配。同樣,運行時間庫必須保證從堆中分配的記憶體總是滿足一個word邊界 ,所以你一般不必擔心那兩點。但是,如果應用程式含有用memcpy()函式拷貝記憶體區域的代碼,或者使用了某種類型的指針算術以確定記憶體地址,問題也許就出現了。考慮下面的例子:
int send_name (TCHAR * pszName)
{
char *p, *q;
int nLen=(_tcslen(pszName) + 1) * sizeof(TCHAR);
p=maloc(HEADER_SIZE + nLen);
if(p)
{
q = p + HEADER_SIZE;
_tcscpy((TCHAR*)q, pszName);
}
/* etc */
這段代碼是從堆中分配記憶體並複製一個字元串,在字元串的開頭留一個HEADER_SIZE的大小。假設UNICODE定義了,那么該字元串就是一個widechar字元串。如果HEADER_SIZE是一個偶數,這段代碼就會正常工作,但如果HEADER_SIZE為奇數,這段代碼就會出錯,因為q指向的地址也將為奇數。
注意,當你在Intel系列處理器中的Windows CE仿真器上測試這段代碼時,這個問題是不會發生的。
在這個例子中,只要確保HEADER_SIZE為偶數,你就可以避免問題的發生。然而,在某些情況下你也許不能這么做。例如,如果程式是從一台式PC輸入數據,你也許不得不採用事先定義過的二進制格式,儘管它對H/PC不適合。在這種情況下,你必須採用函式,這些函式用字元指針控制字元串而不是TCHAR指針。如果你知道字元串的長度,就可以用memcpy()複製字元串。因此,採用逐個位元組分析Unicode字元串的函式也許足以確定字元串在widechars中的長度。
在ANSI和Unicode字元串之間進行翻譯
如果你的Windows CE應用程式接口於台式PC,也許你必須操作PC機中的ANSI字元串數據(例如,char字元串)。即使你在程式中只用到Unicode字元串,這都是事實。
你不能在Windows CE上處理一個ANSI字元串,因為沒有操縱它們的庫函式。最好的解決辦法是將ANSI字元串轉換成Unicode字元串用到H/PC上,然後再將Unicode字元串轉換回ANSI字元串用到PC上。為了完成這些轉換,可採用MultiByteToWideChar()和WideCharToMultiByte () Win32 API 函式。
對於Windows CE 1.0的字元串轉換,劈開(hack)
在Windows CE 1.0 版本中,這些Win32API函式還沒有完成。所以如果你想既要支持CE 1.0又能支持CE 2.0,就必須採用其它函式。將ANSI字元串轉換成Unicode字元串可以用wsprintf(),其中第一個參數採用一widechar字元串,並且認識"%S"(大寫),意思是一個字元串。由於沒有wsscanf() 和 wsprintfA(),你必須想別的辦法將Unicode字元串轉換回ANSI字元串。由於Windows CE 1.0不在國家語言支持(NLS)中,你也許得求助於hack,如下所示:
/*
Definition / prototypes of conversion functions
Multi-Byte (ANSI) to WideChar (Unicode)
atow() converts from ANSI to widechar
wtoa() converts from widechar to ANSI
*/
#if ( _WIN32_WCE >= 101)
#define atow(strA, strW, lenW) \
MultiByteToWidechar (CP_ACP, 0, strA, -1, strW, lenW)
#define wtoa(strW, strA, lenA) \
WideCharToMutiByte (CP_ACP, 0, strW, -1, strA, lenA, NULL, NULL)
#else /* _WIN32_WCE >= 101)*/
/*
MultiByteToWideChar () and WideCharToMultiByte() not supported o-n Windows CE 1.0
*/
int atow(char *strA, wchar_t *strW, int lenW);
int wtoa(wchar_t *strW, char *strA, int lenA);
endif /* _WIN32_WCE >= 101*/
#if (_WIN32_WCE <101)
int atow(char *strA, wchar_t *strW, int lenW)
{
int len;
char *pA;
wchar_t *pW;
/*
Start with len=1, not len=0, as string length returned
must include null terminator, as in MultiByteToWideChar()
*/
for(pA=strA, pW=strW, len=1; lenW; pA++, pW++, lenW--, len++)
{
*pW = (lenW = =1) ? 0 : (wchar_t)( *pA);
if( ! (*pW))
break;
}
return len;
}
int wtoa(wxhar_t *strW, char *strA, int lenA)
{
int len;
char *pA;
wchar_t *pW;
/*
Start with len=1,not len=0, as string length returned
Must include null terminator, as in WideCharToMultiByte()
*/
for(pA=strA, pW=strW, len=1; lenA; pa++, pW++, lenA--, len++)
{
pA = (len==1)? 0 : (char)(pW);
if(!(*pA))
break;
}
return len;
}
#endif /*_WIN32_WCE<101*/
這種適合於Windows CE 1.0的實現辦法比使用wsprintf()函式要容易,因為使用wsprintf()函式更難以限制目標指針所指向的字元串的長度。
選擇正確的字元串比較函式
如果你要分類Unicode標準字元串,你會有以下幾個函式可供選擇:
wcscmp(), wcsncmp(), wcsicmp(), 和wcsnicmp()
wcscoll(), wcsncoll(), wcsicoll(),和wcsnicoll()
CompareString()
第一類函式可用來對字元串進行比較,不參考當地(Locale)或外文字元。如果你永遠不想支持外文,或者你僅僅想測試一下兩個字元串的內容是否相同,這類函式非常好用。
第二類函式使用現有的當地設定(current locale settings)(系統設定,除非你在字元串比較函式之前調用了wsetlocale()函式)來比較兩個字元串。這些函式也能正確分類外文字元。如果當地的字元"C"("C" locale)被選定,這些函式與第一類函式就具有了相同的功能。
第三類函式是Win32函式CompareString()。這個函式類似於第二類函式,但是它允許你指定當地設定(the locale)作為一個參數,而不是使用現有的當地設定(current locale settings)。CompareString()函式允許你選擇性地指定兩個字元串的長度。你可以將第二個參數設定為NORM_IGNORECASE,從而使函式比較字元串時不比較大小寫。
通常,即使不將第二個參數設定為NORM_IGNORECASE,CompareString()函式也不用來區分大小寫。我們經常用wcsncoll()函式來區分大小寫,除非使用當地的字元"C"("C" locale)。所以,在我們的代碼中,不使用CompareString()函式來區分大小寫,而用wcsncoll()函式來區分大小寫
不要使用相對路徑
與Windows NT不一樣,Windows CE沒有當前目錄這個概念,因此,任何路徑只是相對於根目錄而言的。如果你的軟體給檔案或目錄使用相對路徑,那么你很可能把它們移到別的地方了。例如,路徑".\abc"在Windows CE中被當作"\abc"看待。
移走了對calloc()和 time()函式的調用
C運行庫中的calloc()函式不能使用,但是malloc()函式可以代替calloc()函式。並且不要忘記,calloc()函式初始化時分配的記憶體為零,而malloc()函式不一樣。同樣,time()函式也不能使用,但你可以使用Win32函式GetSystemTime()函式代替time()函式。
經過以上的警告後,你會高興地學習最後令你驚訝的兩點忠告。
不需要改變Win32 輸入/輸出(I/O)檔案的調用
Win32的輸入輸出函式,Windows CE也支持。允許你象訪問Win32檔案系統那樣訪問對象。CreateFile()函式在Windows CE中不能辯認標誌FILE_FLAG_RANDOM_ACCESS,但是這個標誌僅用作可選的磁碟訪問,並且不影響函式調用的功能。
不要擔心位元組的狀態
當我們把應用程式寫入Windows CE時,有了一個美好的發現,那就是Windows CE的數字數據類型的位元組狀態與Intel結構的位元組狀態一樣,在所有的處理器上,Windows CE均支持。
幾乎象所有的資料庫引擎一樣,Raima資料庫管理器在資料庫檔案中以二進制形式保存數字數據。這就意味一個記錄無論何時寫入資料庫或從資料庫讀出,均被當作一系列的位元組來處理,不管它域的內容。只要資料庫檔案不要傳給別的任何系統,數字數據的位元組狀態問題就解決了。如果資料庫檔案被一個來自原始系統且帶有不同位元組狀態的處理器訪問,數字數據將被誤解。
無論何時,當你在擁有不同處理器的機器上傳輸檔案時,就會出現這個問題。在這個問題上,值得高興的是所有類型的處理器都使用相同的位元組狀態。
在使用Windows CE時,這些忠告應該引起你足夠的重視,避免學習時走彎路。

相關詞條

相關搜尋

熱門詞條

聯絡我們