Delphi2007升級到Delphi 2010總結(jié)這兩天把一個使用Delphi2007成功升級到了Delphi2010,。升級途中很艱辛,總結(jié)了 以下經(jīng)驗與大家分享,。另外,,D7使用的第三方組件,由于官方?jīng)]有發(fā)布For Delphi2010的更新,,修改的第三 方組件列表見文章尾部,。 1,PChar 因為Delphi不支持無類型指針的算術(shù)運算,,很多程序員使用 PChar來代替Pointer,,即使指針指向目標(biāo)并不是PAnsiChar。 考慮如下代碼: var P:PChar; Buffer:Pointer; begin GetMem(Buffer,255); P:=Buffer; p^:=#1; Inc(P); p^:=#2; FreeMem(Buffer,255); end; 在2010中PChar已經(jīng)不再表示PAnsiChar而是表示PWideChar,,如果依然這樣寫,,運行時很可能會得到一個內(nèi)存訪問錯誤。因為每 次Inc(P),,實際上指針向前移動了2字節(jié),,因為SizeOf(WideChar)=2,Inc(P)相當(dāng)于 P:=P+SizeOf(WideChar),。 解決方法是把PChar替換成PAnsiChar 2,,Move FillChar CopyMemory 這些函數(shù)依賴的是字節(jié)長度,往往我們直接使用Length(Str)來獲取,,這是行不通的,。 考慮如下代碼: var P1,P2:String; begin P1:='test'; SetLength(P2,Length(P1)); Move(P1[1],P2[1],Length(P1)); 在2010中String默認(rèn)映射到UnicodeString,單個字符是2字節(jié),,所以上文中P1實際占用了8字節(jié)內(nèi)存,,而傳給Move函數(shù)的長 度只有4字節(jié),最終結(jié)果是P2="te",。 解決辦法1: 修改String為AnsiString,,該方案雖然可行,但你的程序就享受不到Unicode待遇了,。 解決辦法2: SetLength 函數(shù)不要修改,,因為他的長度參數(shù)是字符長度,,而不是字節(jié)長度。 Move函數(shù)的最后一個參數(shù) Length(P1) 修改成 Length(P1)*SizeOf(Char),。 注意:不要偷懶使用萬一老師說的ByteLength函數(shù),,該函數(shù)并沒有For AnsiString的重載,編譯器會 把參數(shù)隱式轉(zhuǎn)化為UnicodeString然后,,ByteLength函數(shù)計算UnicodeString的長度,。例如:一旦你不小心傳入了一個 AnsiString類型長度為4的字符串,函數(shù)會返回8,,而不是你期望的長度4。 3,,Key in ['a'..'z','B','C'] 這類代碼最好替換成CharInSet(Key,['a'..'z','B','C']) 不然會當(dāng)作AnsiChar處理,。 4,WideString 代碼中的所有WideString都考慮替換成String,,現(xiàn)在 WideString只是為了與COM兼容而存在,,且沒有引用計數(shù),性能低下,。 5,,Tnt控件 如果你的工程使用了Tnt控件或以前的WideTextPos WideStringReplace之類的東西都替換成標(biāo)準(zhǔn)的吧,不用曲線救國了,。 待續(xù)………… ---------經(jīng)過修改,,可以在Delphi2010下運作的第三方組件-------------- 1,PNGDelphi 2,,EmbeddedWB 3,,SynEdit的語法高亮組件 unihighlighter 4,JEDI Win32API Header 這些組件現(xiàn)在可以在Delphi2010下運作了,。 6,引用AnsiStrings單元 如果你有必要使用 AnsiLowerCase AnsiCompareStr之類的函數(shù),一定要引用AnsiStrings單元,。 如果你不引用該單元,,即便編譯不報錯,你實際上是用的還是Unicode版本的函數(shù),,會有隱式的轉(zhuǎn)化,。不信你打開參數(shù)自動完成,看看IDE提示給你的類型是什么,?天啊AnsiLowerCase參數(shù)竟然還是String,,而不是AnsiString??磥鞤elphi2010太迫切的要拋棄Ansi字符串了,,以至于你不引用AnsiStrings單元,所有Ansixxxx函數(shù)實際上還是Unicode版本。 7,,AnsiCopy AnsiPos AnsiDelete 不要用AnsiCopy AnsiPos AnsiDelete,,因為Copy Pos Delete三個函數(shù)已經(jīng)有了For Ansi的重載。 8,,把Char轉(zhuǎn)化為小寫用什么,? 答案:試試看Character單元的新函數(shù) ToUpper ToLower。以前我都是用System里面的UpCase函數(shù),,現(xiàn)在依然可用不過卻找不到LowCase DownCase之類的函數(shù),,困擾我好久好久。索性全使用Character單元提供的新函數(shù)吧,。 9,,編譯期警告:[DCC Warning] Unit1.pas(31): W1057 Implicit string cast from 'AnsiString' to 'string' 如果你的代碼中包含了兩種字符串(Unicode、Ansi)之間進行隱式轉(zhuǎn)化的時候就會出現(xiàn)該提示,。 如下代碼就會觸發(fā)該警告: var Unicode:String; Ansi:AnsiString; begin Ansi:='test..'; Unicode:=Ansi; 把舊版本的Delphi項目升級到2010,,我通常都是借助編譯警告來快速尋找需要改動的部分。通常你可以把賦值雙方都聲明為String(默認(rèn)影射到UnicodeString),,就可以避免該警告,。但如果你確定必須在此處保留Ansi并進行轉(zhuǎn)化的時候,建議你顯式的轉(zhuǎn)化他們(例如:Unicode:=String(Ansi);),,這樣可以避免該警告,,方便你在升級過程中繼續(xù)尋找其他需要修改的地方。 10,,Readln Writeln 寫入文件時候要注意 如果你傳給Writeln一個AnsiString,,那么它也會在文件中寫入AnsiString,那么你讀取得時候就必須傳給Readln一個AnsiString的類型,,否則就是亂碼,。例如舊工程的配置文件是Ansi的,而你已經(jīng)把相關(guān)讀取配置的代碼升級為支持Unicode,,那么運行工程前你首先要用記事本之類的工具把配置文件另存為成Unicode編碼,。當(dāng)然你還要注意跳過Unicode文件頭的兩個字節(jié)FE FF。 11,,別再用String來操作二進制數(shù)據(jù)了 一定要記住String只是字符串,,不要把它當(dāng)作緩沖區(qū)、內(nèi)存流使用,。我的項目中,,有很多地方是使用字符串來處理二進制數(shù)據(jù),導(dǎo)致在本次升級中頗為費腦,。如果當(dāng)時用TBytes或TStream就好了,。 反面教材: var Int1,Int2,Int3,Int4:Integer; Buf:String; begin SetLength(Buf,12); Move(Int1,Buf[1],SizeOf(Integer)); Move(Int1,Buf[5],SizeOf(Integer)); Move(Int1,Buf[9],SizeOf(Integer)); Buf:=Buf+'前面有3個Integer,。'; 12,還是PChar 注意在2010中是這樣的: PChar= Pointer to a WideChar array; PAnsiChar = Pointer to a AnsiChar array; 如果你還像是在Delphi 7中那樣:PChar(AnsiString)那后果過是很嚴(yán)重的,。 |
|