全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:5508
推到 Plurk!
推到 Facebook!

將項目從delphi7升級到DelphiXE(delphi2011)

 
pcboy
版主


發表:177
回覆:1838
積分:1463
註冊:2004-01-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2011-01-04 08:50:32 IP:61.219.xxx.xxx 訂閱
將項目從delphi7升級到DelphiXE(delphi2011)
文章來源
http://www.delphishare.com/index.asp?id=1274
google翻譯並整理(俄文看不懂,整理只能按自己理解了,有錯誤希望大家糾正)
之前,DelphiXE的項目遷移問題的講的很少,不僅需要瞭解Unicode的,還需要一些其他的關注。在以下文章有很好的描述:
第1部分 (Delphi的Unicode世界第一部分:什麼是Unicode,你為什麼需要它,以及如何在Delphi中使用它 第一樓)
第2部分 (Delphi的Unicode世界第二部分:新的RTL特點和類來支持Unicode 第二樓)
第3部分 (Delphi的Unicode世界第三部分:修改你的代碼 第3樓)

在過去的一年,遷移項目到Delphi XE獲得了成功,並總結了量的經驗:
然而,有些其他性質的問題或,不是這方面的。
現在,沒有了這種「非技術」的問題。你得到一個Delphi XE的同時將獲得所有Delphi2010,Delphi2009,Delphi2007和Delphi 7的授權,這樣就能包容早期版本。
現在您可以執行順利遷移:「舊」項目(即那些不再要求發展,但前提是有用的),繼續在Delphi 7運行,並在適當的時候轉移到DelphiXE的最新版本。
如何得到以前的Delphi版本:
1)創建一個在Embarcadero的開發者網絡帳戶,如果它尚不存在。購買新產品時一般會註冊;
2)註冊一個新的產品(不是拿到key,過去是不可能的);
3)按照該鏈接並得到key: http://www.embarcadero.com/xe-earlier-versions ;
請注意,以前的版本可以在從購買之日起180天內,此優惠購買時獲得有效的「象徵性」(個人)牌照。
發表於DelphiXE的弗塞沃洛德列昂諾夫9月27日,2010
part1
google翻譯並整理
Delphi的Unicode世界第一部分:什麼是Unicode,你為什麼需要它,以及如何在Delphi中使用它

上傳者:Aleg Azarousky
摘要:本文討論了什麼是Unicode,Delphi使用unicode有什麼好處,以及如何使用2009年推出Delphi 中包含的Unicode
簡介
互聯網已經摧毀了有可能阻礙在世界各地分發軟件的地理障礙。因此,程序可以不再基於純粹的ANSI。世界採納以文字和數據傳輸標準的 Unicode(Unicode)。這可以讓你輸入一個在世界上的書面語言和使用任何虛擬的Unicode支持是現在 - 是在全球技術生態系統的規範。
什麼是Unicode?
Unicode是一種編碼方案,支持幾乎所有文字都是一個字符集編碼。 Unicode 允許計算機支持幾乎任何語言,它的發展下的Unicode協會(Unicode協會)控制在一個特殊的標準錄製的書面文本。簡言之,Unicode是 一個系統,允許任何人使用你喜歡的字母表。例如,是一個克林貢(星際迷航中的某外星人種)的Unicode版本。
在此之前的文章,你不應該給你的目標是Unicode是什麼以及它如何工作,在這裡你將瞭解如何開始使用Delphi 2009的Unicode的全部信息。如果您需要有關 Unicode好故事,我們建議您閱讀這篇優秀的文章「絕對最低,必須知道每一個的字符集Unicode的軟件開發人員」(下稱「絕對最低每一個軟件開發的,積極的要關於Unicode和字符集知道(不!借口)「。,斯波斯基寫成由Joel喬爾正確指出的:」這並不難「這篇文章,我的第三部分,將談談 Unicode是如此重要的原因,以及如何Delphi將推出一種新類型的UnicodeString。。
為什麼我需要的Unicode?
Delphi2009 在眾多的創新中最主要的是Unicode,它貫穿於整個產品的運行。在Delphi中普通的字符串(字符串)現在是一個Unicode字符串(基於 Unicode的字符串)。Delphi的一切都是與此相關的,它是IDE,編譯器的RTL和VCL,完全支持Unicode。
Delphi 過渡到Unicode - 自然。 Windows本身是完全基於Unicode的系統,所以這是很自然的為它編寫的應用程序,默認情況下應該使用 Unicode字符串。對於Delphi開發者不僅受益於事實,即它們現在可以使用和Windows相同的數據類型,。
Unicode 支持揭示了Delphi開發者的新的可能性:他們現在可以用Unicode讀,寫,接收,發送,顯示任何數據 - 任何事情都可以用Delphi構造。不用改變多少代碼,你可以準備你的應用程序的任何數據,您,您的客戶或用戶操作。以前的應用程序只能工作在ANSI記錄數據,可以很容易地修改,以與幾乎世界上任何字符集。
Delphi開發人員,即使他們不用做任何事情,現在都可以進入世界市場,以本地化開發然後翻譯成幾種語言。 Windows本身有許多不同的本地化版本,在Delphi編寫的應用程序,應該能與不同的語言所支持的Windows相適應,包括任何日文,中文,希臘文或俄文。您的程序的用戶可能無法進入的ANSI文本或不使用ANSI路徑名稱。基於ANSI的應用程序,在這種情況下並不總是就像希望那樣工作。基於Windows的應用程序在Delphi中創建完整的Unicode支持,在這種情況下,將正常工作。即使你不面對所有語言環境,告訴最終用戶他們仍然能正常工作,無論何種語言。
對於現有的ANSI - Delphi中創建的應用程序,本土化的優勢,進入世界市場(使用 Unicode)可能非常大。如果你要本地化的應用程序,Delphi可以很容易做到正確的應用過程中(設計時)的創建它。包的IDE直接讓你翻譯,編譯和部署從開發環境(IDE)的應用程序。如果您需要外部資金的轉移,開發環境可以導出一個譯員可以用便攜式外部經理轉換(外部翻譯經理)使用的形式您的項目。這些工具與Delphi中,和C Builder的,這使得您的應用程序簡單方便的本地化。
世界上使用Unicode,現在開發商和Delphi,很容易成為一個不可分割的組成部分。所以,如果你希望有機會與工作在Unicode數據,或者如果你想打開你的應用程序開發和全球市場的方式,Delphi 2009可以幫你做到這一點用。
一點術語
Unicode 是基於一個新的詞彙。例如,在「字符»(字符)的Unicode的概念並沒有準確地反映你的習慣來理解它。 Unicode是一種更準確的術語「代碼點» (代碼點)。在Delphi 2009,調用一下SizeOf(炭)將返回2,但是這並不是唯一的功能。在某些情況下,根據編碼,符號,可能需要兩年以上的字節。此類字符的序列被稱為「代理項對。」因此,「代碼點」 - 一個獨特的代碼分配到Unicode協會指定的元素。大多數情況下它是作為「符號」,但並不總是一樣的。
另一個術語,是指為Unicode,它是「物料清單」或字節順序標記。這是一個很短的前綴,在該文本文件的開頭插入來形容該文件中使用的編碼。 MSDN上有什麼一個BOM偉大的文章。一類新的TEncoding(將在第二部分所述)有一個方法 GetPreamble,對於給定的BOM編碼的回報。
這是所有需要解釋,但現在讓我們來看看如何使用Unicode字符串Delphi 2009的作品。
一種新型的UnicodeString
Delphi2009 年默認字符串類型,是一種新型的UnicodeString。默認情況下,類似的UnicodeString為UTF - 16,在Windows中使用的相同。這是不同於以往的版本,它使用默認的類型AnsiString類型。在Delphi的RTL同期處理Unicode數據使用類型 WideString類型,而不是AnsiString類型,不計算在內的鏈接(而不是引用計數)的數量,因此不能被作為一個Delphi型「的默認字符串開發商看到。
Delphi2009年新的UnicodeString類型是設計了這樣一種方式相結合的優勢和AnsiString類型,和WideString。的UnicodeString可以包含Unicode字符,以及單字節的ANSI字符。 (請記住,您仍然可以使用 AnsiString類型和WideString)。 CHAR和PChar類型的類型現在分別代表和WideChar 和PWideChar。請注意,沒有一種類型的並沒有消失,所有類型,這是由開發人員使用繼續存在和運作,和以前一樣。
因此,在Delphi2009的原始字符串(string)將等同的UnicodeString,正常字符(char) - 現在WideChar,一個指針(PChar類型) - 現在是PWideChar。
也就是說,編譯器給出下面的代碼:
type
string = UnicodeString;
Char = WideChar;
PChar = PWideChar;

UnicodeString可以指定任何其他類型的字符串值,AnsiString類型之間的分配和的UnicodeString會導致相應的轉換。因此,分配一個Unicode串的ANSI -行數據將會丟失如果Unicode字符串包含單字節的數據,因為這種類型的字符串 AnsiString類型轉換發生的損失不是單字節的數據。
重要的是要明白的UnicodeString了所有的其他字符串類型所享有的優勢(當然,除了優勢明顯的機會包含Unicode格式的數據)。您仍然可以附加任何字符串數據,參考他們的元素的索引,就可以與他們的符號「 」等
例如,一個字符的Unicode字符串可以通過索引訪問。考慮下面的代碼:
var
MyChar: Char;
MyString: string;
begin
MyString := 『This is a string』;
MyChar := MyString[1];
end;

MyChar變量將包含從第一的位置,即「T」型性格。這段代碼執行的操作是不變的。倘若我們與Unicode數據的工作:
var
MyChar: Char;
MyString: string;
begin
MyString := 『世界您好『;
MyChar := MyString[1];
end;
MyChar變量將包含從第一個位置,即「世」字。
勞動教養有一個隱藏的代碼頁轉換和元素大小的其他功能。如果用戶使用的移動到一個字符數組,它可能沒有擔心的元素的大小。
正如你可能已經猜到,這種新型串導致在現有的代碼更改。一個字符(char)的已不再是一個字節。事實上,一個字甚至不總是一個雙字節!因此,你可能要改變一些現有的代碼。我們一直在努力使盡可能簡單的過渡到新版本,並有信心,你現在可以實現非常快。在第二和第三部分,根據有關的新類型的 UnicodeString將繼續本文,您將瞭解新的Unicode特性RTL和編寫程序,您可能需要使用你的代碼中的具體方法。這篇文章將幫助你轉換為 Unicode,容易和輕鬆。
結論
除了Unicode字符串的事實,現在由默認字符串,Delphi現在能夠接收,處理和顯示,在世界上任何腳本或代碼頁。你的應用程序在Delphi 2009創建將可以輕易地與Unicode文字工作,幾乎所有的Windows支持的語言。用Delphi開發人員,現在可以輕鬆地找到並移動到另一種語言中的應用,以達到市場中,他們曾經是能去工作。居住在世界各地的Unicode,現在你的Delphi應用程序可以住在這兒。
在第二部分我們會考慮的Delphi運行時庫,這將允許您方便地使用Unicode字符串的變化。
google翻譯並整理
在在Unicode世界第二部分[全部]Delphi:新的RTL特點和類來支持Unicode
上傳者:弗拉基米爾Panarin
摘要:本文介紹的新功能提布隆運行時庫,這將有助於在使用Unicode字符串的工作。
簡介
在第一部分中,我談到了如何利於Delphi開發者對Unicode的支持,因為它允許您使用任何字符在Unicode宇宙套。我們已經回顧了新的UnicodeString類型和使用它在Delphi中的基本技術。
在第二部分我們來看看運行時庫的Delphi引入一些新功能支持Unicode,和一般技術處理字符串。
TCharacter類
蒂布龍的RTL包括一個新的類TCharacter,模塊中的字符描述。這是一個完全由私人類靜態函數組成。開發人員並不需要實例TCharacter,相反,最好只調用它的靜態方法。這個類是各種職務,包括:
字符轉換為大寫或小寫
確定什麼樣的性格類型屬,也就是說,這個數字是字母,標點符號,或別的東西。
TCharacter使用由Unicode協會規定的標準。
開發人員可以使用類TCharacter,執行許多上以前完成的一組符號(字符集的)不同的動作。例如,下面的代碼:
uses
Character;
begin
if MyChar in [『a』...』z』, 『A』...』Z』] then
begin
...
end;
end;

可以很容易地被替換如下:
uses
Character;
begin
if TCharacter.IsLetter(MyChar) then
begin
...
end;
end;

字符單元也包含了該履行TCharacter類似的功能相同的動作不同的功能數量。因此,如果你喜歡簡單地調用上面可以寫一寫如下功能:
uses
Character;
begin
if IsLetter(MyChar) then
begin
...
end;
end;

因此,TCharacter類可用於執行大多數操作或測試,你可能需要。
此外,為確定是否TCharacter一個字符上限或下限的代理對部分方法。
類TEncoding
Tiburon的RTL的還包括一個新的類TEncoding。它的目的 - 要求特定類型的編碼,所以你可以告訴VCL的,什麼類型的編碼在您的特定情況下使用。
例如,你有一個TStringList的實例,包含文字,你要寫入一個文件。以前,你可以這樣寫:
開始
...
MyStringList.SaveToFile('SomeFilename.txt');
...
結束;
和文本將被寫入到一個在ANSI編碼的文件默認情況下使用。此代碼仍然可以正常工作 - 它寫在文件中的文本,使用,像以前一樣,美標ANSI編碼,但現在,Delphi支持Unicode字符串,開發人員可能需要編寫任何特殊編碼的字符串數據。因此,SaveToFile(如LoadFromFile)現在有一個可選的第二個參數指定編碼你想要的:
begin
...
MyStringList.SaveToFile(『SomeFilename.txt』, TEncoding.Unicode);
...
end;
運行此代碼,該文件將被寫在Unicode(UTF - 16中)。
TEncoding也可以轉換從一個編碼的字節設置為另一個,以獲取有關字節和/或在一個字符串或字符數組字符的信息轉換成字節數組(數組的字節(Tbytes的))等等,這取決於字符串的編碼或任何字符串字符數組。
TEncoding類包含以下屬性,這給接觸到不同的編碼:
class property ASCII: TEncoding read GetASCII;
class property BigEndianUnicode: TEncoding read GetBigEndianUnicode;
class property Default: TEncoding read GetDefault;
class property Unicode: TEncoding read GetUnicode;
class property UTF7: TEncoding read GetUTF7;
class property UTF8: TEncoding read GetUTF8;
默認屬性是指為ANSI活躍的代碼頁。 Unicode的屬性是指為UTF - 16。
TEncoding還包括一個功能
class function TEncoding.GetEncoding(CodePage: Integer): TEncoding;

返回一個TEncoding,代碼頁發送到參數的實例。
此外,它具有以下功能:
function GetPreamble: TBytes;
它返回一個給定的編碼的BOM。
TEncoding也與接口兼容。NET的類編碼。
TStringBuilder
在RTL現在有一類TStringBuilder。其目的是從標題明確 - 是一個類來構建(建立)線。 TStringBuilder包含一個重載函數的添加,替換和插入連續元素。這個類可以很簡單地創建許多不同類型的線路。在每個追加,插入和替換返回複製 TStringBuilder,這樣他們就可以很容易地結合起來,建立一個單一的線。
例如,你可以用它代替複雜的TStringBuilder格式。例如,你可以寫下面的代碼:
procedure TForm86.Button2Click(Sender: TObject);
var
MyStringBuilder: TStringBuilder;
Price: double;
begin
MyStringBuilder := TStringBuilder.Create('');
try
Price := 1.49;
Label1.Caption := MyStringBuilder.Append('The apples are $').Append(Price).
AAppend(' a pound.').ToString;
finally
MyStringBuilder.Free;
end;
end;

TStringBuilder也與接口兼容。NET的類的StringBuilder。
公佈新的字符串類型
Tiburon'a編譯器允許你聲明與選定的代碼頁相關聯行自己的類型。在這種情況下,任何可用的代碼頁號(MSDN上是一個優秀的可用頁面描述)。例如,如果你需要一個字符串類型,與ANSI -西裡爾相關,聲明:

type
//    ANSI- - 1251
CyrillicString = type AnsiString(1251);

在這種情況下,一個新的字符串類型與西裡爾代碼頁相關的字符串。
額外的支持Unicode的RTL
在RTL例程,增加了支持Unicode字符串的數量。
StringElementSize
StringElementSize返回該字符串元素(「代碼點」)的大小。考慮下面的代碼:
procedure TForm88.Button3Click(Sender: TObject);
var
A: AnsiString;
U: UnicodeString;
begin
A := 'This is an AnsiString';
Memo1.Lines.Add('The ElementSize for an AnsiString is: ' IntToStr(StringElementSize(A)));
U := 'This is a UnicodeString';
Memo1.Lines.Add('The ElementSize for an UnicodeString is: ' IntToStr(StringElementSize(U)));
end;

在這段代碼的執行結果如下:
The ElementSize for an AnsiString is: 1
The ElementSize for an UnicodeString is: 2

StringCodePage
StringCodePage類型的Word,該字符串返回值適當的代碼頁。
考慮下面的代碼:
procedure TForm88.Button2Click(Sender: TObject);
type
// The code page for ANSI-Cyrillic is 1251
CyrillicString = type AnsiString(1251);
var
A: AnsiString;
U: UnicodeString;
U8: UTF8String;
C: CyrillicString;
begin
A := 'This is an AnsiString';
Memo1.Lines.Add('AnsiString Codepage: ' IntToStr(StringCodePage(A)));
U := 'This is a UnicodeString';
Memo1.Lines.Add('UnicodeString Codepage: ' IntToStr(StringCodePage(U)));
U8 := 'This is a UTF8string';
Memo1.Lines.Add('UTF8string Codepage: ' IntToStr(StringCodePage(U8)));
C := 'This is a CyrillicString';
Memo1.Lines.Add('CyrillicString Codepage: ' IntToStr(StringCodePage(C)));
end;
在這段代碼的執行結果如下:
The Codepage for an AnsiString is: 1252
The Codepage for an UnicodeString is: 1200
The Codepage for an UTF8string is: 65001
The Codepage for an CyrillicString is: 1251

有幾個程序來從一個代碼頁轉換到另一個字符串。它們是:
UnicodeStringToUCS4String
UCS4StringToUnicodeString
UnicodeToUtf8
Utf8ToUnicode
此外,在RTL型介紹RawByteString,這是一個不與任何字符集關聯的字符串:
RawByteString = type AnsiString($FFFF);
任用方式RawByteString - 讓每一個可能存在的代碼頁的字符串數據的傳輸,無需任何編碼轉換。這對於程序的編碼不喜歡搜索字符串的字節的問題,非常有用。這意味著,這些例程的參數的類型必須為RawByteString。 RawByteString類型變量需要使用盡可能少,因為這會導致數據丟失。讓我們來看看為什麼。
通常,字符串類型支持的任務。
例如:
MyUnicodeString := MyAnsiString;
將如預期般運作 - 的內容將被放置在AnsiString類型的UnicodeString。作為一個規則,你可以指定一個行的另一種類型的字符串類型,編譯器做所有的工作轉變,如果可能的話。
然而,有些變化可能導致數據丟失,這應該是一個字符串時,會考慮分配具有Unicode的,字符串類型,不能包含Unicode數據類型。例如,你可以分配一個UnicodeString類型的變量AnsiString類型,但如果的UnicodeString包含不通過積極的ANSI,所包括的字符,這些字符轉換時將會丟失。考慮下面的代碼:
procedure TForm88.Button4Click(Sender: TObject);
var
U: UnicodeString;
A: AnsiString;
begin
U := 'This is a UnicodeString';
A := U;
Memo1.Lines.Add(A);
U := '        2009!!';
A := U;
Memo1.Lines.Add(A);
end;
如果操作系統是活動代碼頁1252運行此代碼後,顯示如下:
This is a UnicodeString
????? ?????????? ? ??? ??????? ? ?????????????? ?????? 2009!!

正如您可以看到從該西裡爾字符不是在Windows - 1252包括事實上,信息丟失,當您指定的UnicodeString AnsiString類型線。其結果是不可理解的文字的UnicodeString包含字符代碼頁中沒有表示的以AnsiString類型,所以這些字符流失,用問號代替。
SetCodePage
SetCodePage,聲明在模塊System.pas
procedure SetCodePage(var S: AnsiString; CodePage: Word; Convert: Boolean);

是一項新功能的RTL,定義為的是ANSI -行新的代碼頁。轉換一個可選的參數指定是否轉換為字符串傳遞給指定的代碼頁。如果轉換= False,則該行只是改變代碼頁。如果轉換= True,則傳遞的字符串將被轉換為代碼頁。
SetCodePage應謹慎使用,並十分謹慎。請記住,如果代碼頁不適合在現有的行(即轉換= false),則結果可以得到怪異。此外,如果在一個行中的數據轉化和新的代碼頁不能顯示原始字符,可能會導致數據丟失。
獲取行Tbytes的
勞動教養也包含字符串的字節數組幾個重載例程。正如你將看到在第三部分,用更好的代替了(字符串)通常的字符串數據緩衝區Tbytes的。可以很容易地做到這一點的RTL使用不同的重載版本BytesOf(),它需要一個不同類型的字符串。
結論
運行時庫Tiburon'a現在完全支持新的Unicode字符串 - 的UnicodeString。它包含訪問一個Unicode字符串,數據處理和轉換,管理代碼的網頁,並提供一個簡單的從舊版本過渡的新的類和例程。
Delphi的Unicode世界第三部分:修改你的代碼
上傳者:弗拉基米爾Panarin
摘要:本文討論了升級你的代碼到Delphi2009你需要做工作。
在本系列的第一部有人說,Delphi2009將默認UTF - 16為基礎的字符串。因此,現有代碼的某些部分可能需要修改。基本上,現有的大多數代
碼將正常工作在Delphi2009上。正如你將看到代碼中的重大變化只適用於非常具體的,甚至是深奧的時刻。不管是什麼,有必要考慮這些代碼
很可能在改特殊件下不得不修。還需要檢查這些代碼的結果,以確保UnicodeString正確的工作。
例如,用字符串的任何代碼,並與他們進行運算工作的指針應檢查與Unicode兼容。具體地說,這種代碼:
相信一下SizeOf(字符)= 1;
假設該字符串的長度等於每行的字節數;
誰寫和讀取任何永久的存儲線路,或使用作為數據緩衝區的字符串
應當進行審查,以確保這些功能並不影響工作。該代碼寫入和讀取從持久性存儲,應驗證的讀或寫一個字節為正確的字節數已經不再是一個單
一的字符。
作為一般規則,在代碼的任何變化都相當簡單,可以用最小的努力取得。
部分,應「的工作就是這樣」
它側重於那些部分代碼,這將繼續工作,不需要任何更改與新的UnicodeString正常。 VCL和勞動教養已經完全更新,以與Delphi2009年,總
是如此。小小的保留,是這樣的。例如,TStringList現在完全支持Unicode和所有現有的代碼,使用TStringList,應該像以前一樣。此外,T
StringList已得到增強,工作的具體使用Unicode,所以如果你想使用新功能,你可以做到這一點,但是如果你不需要 - 你可以做一點也不覺
得。
正常使用String類型
基本上,代碼,使用string類型將像以前一樣起作用。沒有任何陰影類型需要字符串變量AnsiString類型,除以下所述。廣告行應改為AnsiSt
ring類型字符串在所有的地方作為對數據緩衝區使用的地方。
運行時庫
添加到運行時庫中詳細討論了第二部分。
在這篇文章中沒有提到新的模塊添加到了RTL - AnsiString.pas。此模塊存在落後的代碼,使用或要求其工作AnsiString類型的兼容性。
代碼運行時庫運行如常,一般不需要改變。部分需要修改說明如下。
VCL的
所有的VCL支持Unicode。所有現有的VCL -組件進行安裝工作,因為他們總是被。幾乎所有的代碼,使用VCL的,一切都會正常工作。我們做了
偉大的工作,以確保VCL的兼容遺留代碼和Unicode。正常的VCL代碼不執行任何特定的字符串操作會如前。
線條的指數化
線條的指數化工程以同樣的方式和以前一樣,所以代碼的行的索引不需要改變的元素:

var
S: string;
C: Char;
begin
S := 『This is a string』;
C := S[1]; // C將包含的'T',但C,當然,WideChar
end;
長/複製/刪除/一下SizeOf的字符串
複製功能將一如既往,沒有任何變化。這同樣適用於刪除並與SysUtils單元的字符串,工作的所有其他程序。
調用長度(SomeString),一如既往,返回傳遞的字符串元素的數量。
要求每行一下SizeOf標識符將返回,因為所有的字符串聲明4, - 這是一個連和指針大小為4。
挑戰的任何線路長度返回在該行的元素數。
考慮下面的代碼:
var
S: string;
begin
S:= 'abcdefghijklmnopqrstuvwxyz';
WriteLn('Length = ', Length(S));
WriteLn('SizeOf = ', SizeOf(S));
WriteLn('TotalBytes = ', Length(S) * SizeOf(S[1]));
ReadLn;
end.

由於其實施結果將收到以下:
隱藏圖像

為PChar類型工作的指針
為PChar類型的指針與合作將像以前一樣運行。編譯器知道PChar類型的大小,所以像下面的代碼將如預期:
風var
p: PChar;
MyString: string;
begin
...
p := @MyString[1];
Inc(p);
...
end;

此代碼將完全一樣在以前的Delphi版本,但是,當然,其他類型的數據:PChar類型現在PWideChar和MyString的 - 現在的UnicodeString。
ShortString短
ShortString短保持不變,無論是在功能,並宣佈它會像以前一樣工作。
廣告ShortString短分配一個指定數量的AnsiChar'ov緩衝區。此代碼:
var
S: string[26];
begin
S:= 'abcdefghijklmnopqrstuvwxyz';
WriteLn('Length = ', Length(S));
WriteLn('SizeOf = ', SizeOf(S));
WriteLn('TotalBytes = ', Length(S) * SizeOf(S[1]));
ReadLn;
end.
顯示以下內容:
隱藏圖像

請注意,整體規模的字母 - 26,這表明該變量包含AnsiChar'y。
還要考慮下面的代碼:
type
TMyRecord = record
String1: string[20];
String2: string[15];
end;
此記錄將設在內存中,然後以同樣的方式 - 它會記錄從兩個含有AnsiChar'y AnsiString'ov。如果您有包含ShortString'i,那麼上面的代碼
將像以前的工作記錄了錄製文件,以及任何讀或寫不需要任何改變。
但請記住,煤焦 - 現在WideChar,所以如果你使用的代碼,從文件中讀取這些記錄,然後做一些像這樣:
var
MyRec: TMyRecord;
SomeChar: Char;
begin
//  MyRec  ...
SomeChar := MyRec.String1[3];
...
end;
你必須記住,在String1 SomeChar轉[3] WideChar屬於ANSIChar。如果您需要此代碼工作和以前一樣,變化的聲明SomeChar:
var
MyRec: TMyRecord;
SomeChar: AnsiChar; //    AnsiChar    ShortString
begin
//  MyRec  ...
SomeChar := MyRec.String1[3];
...
end;


必須檢查部件
在這篇文章中描述了不同的構造,應在與Unicode兼容現有的代碼進行測試。由於現在是WideChar字符,在字符數組或字符串的字節大小的數
據可能不正確。下面是一些例子的代碼結構,必須進行檢查,以確保新類型的UnicodeString兼容性。
SaveToFile / LoadFromFile
挑戰SaveToFile和LoadFromFile可以歸因於文章(部分應該「的工作就是這樣),如果他們讀,寫,正如他們以前以前的一部分。但是,您可
能要使用新的重載版本,這些程序如果你決定使用Unicode數據。
例如,TStrings現在包括以下一組重載方法:
procedure SaveToFile(const FileName: string); overload; virtual;
procedure SaveToFile(const FileName: string; Encoding: TEncoding); overload; virtual;

第二種方法 - 一個新的重載需要一個作為參數,該參數指定數據將被記錄在文件的編碼。 (。在第二部分中,您可以閱讀的類型TEncoding
描述)如果您調用一個方法,字符串數據將被記錄在相同的方式通常那樣 - 為ANSI數據。正因為如此現有代碼將一如既往完全相同。
但是,如果您需要編寫的Unicode格式的文本,你需要調用方法的第二個版本,對應的參數傳遞值類型TEncoding。如果不這樣做,將被寫入該
行作為ANSI數據很可能導致信息丟失。
因此,在這種情況下,最好的方法 - 分析的挑戰和SaveToFile LoadFromFile,並加入到他們第二次選擇,來說明如何保存或加載數據。如果
你認為永遠不會添加或Unicode字符串,你可以放下一切保持原樣。
用Chr
現有代碼的轉換中的一個字符的整數可以使用Chr價值。這可能會導致以下錯誤:
[DCC Error] PasParser.pas(169): E2010 Incompatible types: 'AnsiChar' and 'Char'

如果代碼使用染色體的功能,有其結果變量屬於ANSIChar,轉讓那麼這個錯誤可以很容易被取代位於染色體的類型屬於ANSIChar職能轉變淘汰
也就是說,下面的代碼:
MyChar := chr(i);
可以更換:
MyChar := AnsiChar(i);
字符集
也許最常見的成語,它可以為編譯器的問題是在集合符號。以前,當字符佔用一個字節,存放在集合符號並沒有創造任何困難。但是,現在宣
布為char WideChar,因此不能再在集合中。因此,如果你有這樣的代碼:
procedure TDemoForm.Button1Click(Sender: TObject);
var
C: Char;
begin
C := Edit1.Text[1];
if C in ['a'..'z', 'A'..'Z'] then
begin
Label1.Caption := 'It is there';
end;
end;
你編譯它,你會得到一個警告,看起來像這樣:
[DCC Warning] Unit1.pas(40): W1050 WideChar reduced to byte char in set expressions. Consider using 'CharInSet' function in
'SysUtils' unit.
如果你願意,你可以將代碼的缺席 - 編譯器會「知道」你正在嘗試做的,並產生正確的代碼。不過,如果你想獲得這個警告了,就可以使用
新的CharInSet:
if CharInSet(C, ['a'..'z', 'A'..'Z']) then
begin
Label1.Caption := 'It is there';
end;

CharInSet函數返回一個布爾值,該代碼將編譯沒有編譯器警告。
作為緩衝區的字符串
經常當與數據線的工作被用作緩衝區。這樣做是因為它常常是簡單 - 對字符串的工作是簡單明瞭。但是,現有的代碼,這是否在大多數情況
下,將需要更多的調整對基於事實的字符串是現在的UnicodeString。
有幾種方法來處理代碼,它使用字符串作為數據緩衝區。首先 - 它只是作為一個緩衝聲明一個變量,而不是字符串AnsiString類型為。如果
在使用Char'y代碼字節緩衝區的工作 - 這些變量聲明為屬於ANSIChar。如果你選擇這條路線,所有的代碼將一如既往,但是你應該記住:所
有的變量,這樣的字符串緩衝區的工作必須是ANSI類型。
第二,更忠實的方式 - 是從一個字符串轉換成字節數組或Tbytes的您的緩衝區。類型Tbytes的是專門為這個目的,而以同樣的方式和以前一
樣,如果你使用類型的字符串。
呼叫一下SizeOf緩衝區
呼叫一下SizeOf使用字符數組必須被檢查的有效性。考慮下面的代碼:
procedure TDemoForm.Button1Click(Sender: TObject);
var
var
P: array[0..16] of Char;
begin
StrPCopy(P, 'This is a string');
Memo1.Lines.Add('Length of P is ' IntToStr(Length(P)));
Memo1.Lines.Add('Size of P is ' IntToStr(SizeOf(P)));
end;

這在Memo1這段代碼顯示:

Length of P is 17
Size of P is 34
在此代碼,長度返回字符串中的字符數34在這種情況下,即每兩個字符字節(加上終端符號)和sizeof返回該數組使用的字節數。在以前版本
的Delphi代碼在兩種情況下會返回17。
使用FillChar
調用FillChar還需要查詢字符串和符號。考慮下面的代碼:
var
Count: Integer;
Buffer: array[0..255] of Char;
begin
// /現有代碼 - 不正確的,因為該字符串=的UnicodeString
Count := Length(Buffer);
FillChar(Buffer, Count, 0);

// 正確的Unicode - 任何權利的選項
Count := SizeOf(Buffer); // << - 設置緩衝區的大小以字節為單位
Count := Length(Buffer) * SizeOf(Char); // <<-- 設置緩衝區的大小以字節為單位
FillChar(Buffer, Count, 0);
end;

Length返回的字符的大小,但FillChar預計,將在數個字節。在這種情況下,而不是長度在使用sizeof(或應當由字符的大小長度乘以)。
此外,由於默認大小為2字符,FillChar填補了,而不是像以前字符的字節串。
var
Buf: array[0..32] of Char;
begin
FillChar(Buf, Length(Buf), #9);
end;

這將填補一元的,而不是09和○九○九美元碼字符數組。要獲得前一個結果,代碼必須改變:
var
Buf: array[0..32] of Char;
begin
..
StrPCopy(Buf, StringOfChar(#9, Length(Buf)));
..
end;

使用字母符號
下面的代碼

if Edit1.Text[1] = #128 then
認識到歐元符號,最後提供真實的ANSI代碼頁,在大多數。不過,Delphi2009年,它將給假,因為#128 - 一歐元兌多數ANSI -頁的象徵,它
在Unicode - 控制字符。歐元符號的Unicode代碼#$ 20AC條。
當升級到Delphi 2009,開發人員必須更換所有的字符代碼#128#255在他們的文字值,則:
if Edit1.Text[1] = '€' then

將作為在ANSI 128#相同,但功能正常(即確定歐元符號)在Delphi 2009(其中'€'的代碼#$ 20AC條)
使用移動
應檢討使用的功能與移動字符串或字符數組。考慮下面的代碼:
var
Count: Integer;
Buf1, Buf2: array[0..255] of Char;
begin
// 現有代碼 - 不正確的,因為該字符串=的UnicodeString
Count := Length(Buf1);
Move(Buf1, Buf2, Count);

// 正確的Unicode
Count := SizeOf(Buf1); // <<-- 設置緩衝區的大小以字節為單位
Count := Length(Buf1) * SizeOf(Char); // <<-- 設置緩衝區的大小以字節為單位
Move(Buf1, Buf2, Count);
end;
Length返回的字符的大小,但移動預計將在數個字節。在這種情況下,而不是長度在使用sizeof(或應當由字符的大小長度乘以)。
方法讀/ ReadBuffer為TStream
調用TStream.Read / ReadBuffer也應該考慮如果字符串或字符數組。考慮下面的代碼:

var
S: string;
L: Integer;
Stream: TStream;
Temp: AnsiString;
begin
// 現有代碼 - 不正確的,因為該字符串=的UnicodeString
Stream.Read(L, SizeOf(Integer));
SetLength(S, L);
Stream.Read(Pointer(S)^, L);

// 正確的數據為Unicode
Stream.Read(L, SizeOf(Integer));
SetLength(S, L);
Stream.Read(Pointer(S)^, L * SizeOf(Char)); // <<-- 設置緩衝區的大小以字節為單位

// 正確的ANSI數據
Stream.Read(L, SizeOf(Integer));
SetLength(Temp, L); // <<-- 使用臨時AnsiString類型
Stream.Read(Pointer(Temp)^, L * SizeOf(AnsiChar)); // <<-- 設置緩衝區的大小以字節為單位
S := Temp; // <<--轉換為Unicode字符串
end;
註:取決於格式的數據讀取。看到了一個新的類TEncoding說明,上面提到,以獲得有關正確的文本流中的編碼信息。
寫/ WriteBuffer
由於在案件讀/ ReadBuffer,使用TStream.Write / WriteBuffer應該檢查字符串或字符數組。考慮下面的代碼:
var
S: string;
Stream: TStream;
Temp: AnsiString;
begin
// 現有代碼 - 不正確的,因為該字符串=的UnicodeString
Stream.Write(Pointer(S)^, Length(S));

// 正確的數據為Unicode
Stream.Write(Pointer(S)^, Length(S) * SizeOf(Char)); // <<-- 設置緩衝區的大小以字節為單位

// 正確的ANSI數據
Temp := S; // <<--使用臨時AnsiString類型
Stream.Write(Pointer(Temp)^, Length(Temp) * SizeOf(AnsiChar));// <<-- 設置緩衝區的大小以字節為單位
end;
註:取決於格式的數據讀取。看到了一個新的類TEncoding說明,上面提到,以獲得有關正確的文本流中的編碼信息。
LeadBytes
替換此代碼:
if Str[I] in LeadBytes then

使用功能IsLeadChar:
if IsLeadChar(Str[I]) then

TMemoryStream的
在這種情況下,當寫入文本文件使用TMemoryStream的,重要的是,作為初始數據寫入文件的字節順序標記(BOM)。這裡有一個在BOM文件的
示例條目:
var
BOM: TBytes;
begin
...
BOM := TEncoding.UTF8.GetPreamble;
Write(BOM[0], Length(BOM));
整個編寫代碼應改為工作UTF8的編碼為Unicode字符串:
風險值
溫度:Utf8String;
開始
...
溫度:= Utf8Encode(乙方); / / < - STR基因 - 字符串寫入到文件
寫(指針(臨時)^,長度(暫));
/ /寫(指針(乙方)^,長度(乙方)); < - 這是原來的調用write寫一個字符串到一個文件

var
Temp: Utf8String;
begin
...
Temp := Utf8Encode(Str); // <--STR基因 - 字符串寫入到文件
Write(Pointer(Temp)^, Length(Temp));
//Write(Pointer(Str)^, Length(Str)); <-- 這是原來的調用write寫一個字符串到一個文件

TStringStream
TStringStream現在來自新類型TByteStream。 TByteStream增加了物業字節,使直達TStringStream的字節。 TStringStream繼續照常工作,
但它的字符串店,現在是一個Unicode字符串。
MultiByteToWideChar
挑戰MultiByteToWideChar可以簡單地拆卸和更換一個簡單的任務。使用MultiByteToWideChar的例子:
procedure TWideCharStrList.AddString(const S: string);
var
Size, D: Integer;
begin
Size := SizeOf(S);
D := (Size 1) * SizeOf(WideChar);
FList[FUsed] := AllocMem(D);
MultiByteToWideChar(0, 0, PChar(S), Size, FList[FUsed], D);
Inc(FUsed);
end;

,後過渡到Unicode,此代碼已被修改為編譯為ANSI和Unicode:
procedure TWideCharStrList.AddString(const S: string);
var
L, D: Integer;
begin
FList[FUsed] := StrNew(PWideChar(S));
Inc(FUsed);
end;
SysUtils.AppendStr
這種方法只能使用AnsiString類型,而不是為的UnicodeString超載。
更換電話是這樣的:
AppendStr(String1, String2);
此代碼:
String1 := String1 String2;

或者,更好的是,使用一個新的類TStringBuilder來連接字符串。
GetProcAddress函數
當你調用GetProcAddress應該總是使用PAnsiChar(SDK中是沒有後綴「W」的功能)。例如:
procedure CallLibraryProc(const LibraryName, ProcName: string);
var
Handle: THandle;
RegisterProc: function: HResult stdcall;
begin
Handle := LoadOleControlLibrary(LibraryName, True);
@RegisterProc := GetProcAddress(Handle, PAnsiChar(AnsiString(ProcName)));
end;

註:Windows.pas包含一個重載方法,執行此轉換。
使用轉換為PChar類型(),工作的指針指向了不為字符類型
在以前的版本中,並非所有類型的指針算術支持。正因為如此,這類招牌上執行算術運算,他們轉換為PChar類型。在Delphi 2009年,可能包
括指針算術指令編譯器,它是專門為類型PByte包括在內。所以,如果你有類似的代碼轉換成一個指向PChar類型上執行算術運算:
function TCustomVirtualStringTree.InternalData(Node: PVirtualNode): Pointer;
begin
if (Node = FRoot) or (Node = nil) then
Result := nil
else
Result := PChar(Node) FInternalDataOffset;
end;

您應該取代它而不是使用PByte PChar類型:
function TCustomVirtualStringTree.InternalData(Node: PVirtualNode): Pointer;
begin
if (Node = FRoot) or (Node = nil) then
Result := nil
else
Result := PByte(Node) FInternalDataOffset;
end;
在上面的片斷節點不包含字符數據。他只轉換為PChar類型訪問數據,通過一個節點後的字節數指定。此前它曾擔任一下SizeOf(字符)=一
下SizeOf(字節)。現在,它不會工作。為了使代碼正常工作,你應該使用PByte代替PChar。如果你讓一切保持不變,結果將指向無效的數據
期權Variant數組
如果您的代碼使用TVarRec工作與參數 - 變量數組 -
你可能需要編輯它來工作的UnicodeString。要做到這一點,現在有一種新型的vtUnicodeString,數據存儲從一的UnicodeString。考慮下面
這段DesignIntf.pas,顯示,在這種情況下你應該增加新的代碼才能使用的UnicodeString。
procedure RegisterPropertiesInCategory(const CategoryName: string;
const Filters: array of const); overload;
var
I: Integer;
begin
if Assigned(RegisterPropertyInCategoryProc) then
for I := Low(Filters) to High(Filters) do
with Filters[I] do
case vType of
vtPointer:
RegisterPropertyInCategoryProc(CategoryName, nil,
PTypeInfo(vPointer), );
vtClass:
RegisterPropertyInCategoryProc(CategoryName, vClass, nil, );
vtAnsiString:
RegisterPropertyInCategoryProc(CategoryName, nil, nil,
string(vAnsiString));
vtUnicodeString:
RegisterPropertyInCategoryProc(CategoryName, nil, nil,
string(vUnicodeString));
else
raise Exception.CreateResFmt(@sInvalidFilter, [I, vType]);
end;
end;

CreateProcessW
的Unicode的CreateProcess(CreateProcessW)版本的作品有點不一樣的ANSI版本。從MSDN描述報價參數lpCommandLine:
「的Unicode此功能,CreateProcessW,版本可以改變這個字符串的內容因此,這個選項不能成為回憶,只有讀書(即是一個常數變量或字符
串)如果這個參數 - 。。一個常數函數可能會導致訪問錯誤。「
正因為如此現有代碼調用CreateProcess,可以開始提供訪問錯誤(訪問衝突)時,在德爾福2009年編製。
這樣的代碼例子:
轉移一個字符串常量
CreateProcess(nil, 'foo.exe', nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo);
const
cMyExe = 'foo.exe'
begin
CreateProcess(nil, cMyExe, nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo);
end;
;與鏈接(引用計數)-1號輸電線路:
const
cMyExe = 'foo.exe'
var
sMyExe: string;
begin
sMyExe := cMyExe;
CreateProcess(nil, PChar(sMyExe), nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo);
end;
驗證碼
這裡是一個可能的地方在代碼中,你需要找到清單,檢查是否已準備好您的代碼正確使用Unicode:
找到任何「字符」使用「屬於ANSIChar」,或驗證工作緩衝區使用Unicode正確;
找到「字符串[」和驗證字符符號論(即WideChar)進入連結歡迎。
檢查出與AnsiString類型,ANSIChar和PAnsiChar隱工作,確保它仍然是必要的,正常工作;
發現隱式使用ShortString短,確保它仍然是必需的,是否工作正常;
找到電話通話時長(和檢查,沒有任何暗示的長度是因為這一下SizeOf相同;
找到挑戰複製(,尋求(,指針(,AllocMem(和GetMem函數(並檢查他們的工作與字符串或字符數組正確。
這是一個典型的設計,這可能改變以支持新的類型的UnicodeString。
結論
這是在代碼中要檢查的Unicode世界上所有生命的正確性潛在的瓶頸。你的代碼的大多數仍然是可行的。的警告,這將讓你從編譯器的大部分
代碼,你可以輕鬆解決。一個事物的檢查中很大一部分是相當罕見的,因此幾乎所有代碼會工作得很好。
------
能力不足,求助於人;有能力時,幫幫別人;如果您滿意答覆,請適時結案!

子曰:問有三種,不懂則問,雖懂有疑則問,雖懂而想知更多則問!
系統時間:2024-04-27 7:52:35
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!