如何在memo或richedit中輸入新增的Big5中文字啊? |
尚未結案
|
martialart
一般會員 發表:6 回覆:6 積分:7 註冊:2002-06-15 發送簡訊給我 |
|
lcsboy
版主 發表:87 回覆:622 積分:394 註冊:2002-06-18 發送簡訊給我 |
|
lcsboy
版主 發表:87 回覆:622 積分:394 註冊:2002-06-18 發送簡訊給我 |
|
領航天使
站長 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
|
martialart
一般會員 發表:6 回覆:6 積分:7 註冊:2002-06-15 發送簡訊給我 |
[轉貼]VCL中TStrings的重大BUG-不支持Unicode 好久沒有來csdn了,最近主要忙著項目開發,這麼舊沒有來,想想不能空手而來,所以帶來了一篇文章,也是我在項目開發中遇到的問題,希望大家會喜歡。 Unicode已經成為Windows字符的主要編碼方式,我想這也是大勢所趨,現在軟件越來越傾向國際化,而國際化主要的編碼方式就是Unicode,不管是單字節英文字符,還是雙字節漢字,在Unicode編碼格式下都能正常顯示。在Windows2000中大到Word,小到Notepad,都能很好的顯示Unicode格式的文本文件。可是在我最近的項目中卻發現VCL中的TMemo類不支持它,例如如下16進制顯示的Unicode文本文件 66 00 67 00 68 00 69 00 在WindowsXP自帶的Notepad中顯示為: 但是在C builder6中的TMemo控件中則顯示為: 除了把第一個字符顯示出來,其他的字符都被忽略了,這在設計應用中是絕對不允許的,究其原因,原來是TMemo類的Lines屬性不支持Unicode,Lines屬性是TStings類,TMemo是通過TStrings的LoadFormFile方法代開文件並顯示的,在VCL源代碼中,我們可以找到如下函數 procedure TStrings.LoadFromFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
LoadFromStream(Stream);
finally
Stream.Free;
end;
end; procedure TStrings.LoadFromStream(Stream: TStream);
var
Size: Integer;
S: string;
begin
BeginUpdate;
try
Size := Stream.Size - Stream.Position;
SetString(S, nil, Size);
Stream.Read(Pointer(S)^, Size);
SetTextStr(S);
finally
EndUpdate;
end;
end; 最後來到SetTextStr函數,由於這個函數的處理,使得Unicode被忽略了 procedure TStrings.SetTextStr(const Value: string);
var
P, Start: PChar;
S: string;
begin
BeginUpdate;
try
Clear;
P := Pointer(Value);
if P <> nil then
while P^ <> #0 do
begin
Start := P;
while not (P^ in [#0, #10, #13]) do Inc(P);
SetString(S, Start, P - Start);
Add(S);
if P^ = #13 then Inc(P);
if P^ = #10 then Inc(P);
end;
finally
EndUpdate;
end;
end; 以上代碼片斷我們可以清楚的看出Unicode是如何被忽略了,對於Unicode,它的編碼方式是不管單字節還是雙字節都是都是以雙字節編碼,單字節的英文則以0來補高位,但是很可惜,在以上函數中只要遇到0就退出了,所以在上面的例子中我們看到了『f』這唯一的倖存者。 原因找到了,解決起來就倒是很容易,在判斷字符串結束時不要以0來定界,而是實際的字符長度,這樣就可以解決了,如下代碼: Clear;
P := Pointer(S);
if P <> nil then
begin
iPos := 0;
while (iPos < Size) do // (P^ <> #0) do
begin
Start := P;
while not (P^ in [#0, #10, #13]) do
begin
Inc(P);
Inc(iPos);
end;
SetString(S1, Start, P - Start);
Add(S1);
if (P^ = #13) then
begin
Inc(P);
Inc(iPos);
end;
if (P^ = #10) then
begin
Inc(P);
Inc(iPos);
end;
if (P^ = #0) then
begin
Inc(P);
Inc(iPos);
end;
end;
end;
finally
EndUpdate;
end;
end; 這樣TStrings就能很好的支持Unicode字符集了。 寫在最後: 其實在C Builder中對Unicode支持的還是很好的,VCL提供了WideString類封裝了w_char*,而且還提供很多有用的方法用於Ansi與Unicode的相互轉換,可能是TMemo太老了,它還來不及改正,說道太老了,VCL裡很多控件都應該升級了,比如TRichEdit還是用的Richedit1.0,VCL的界面外觀還不能應用XP的外觀。 Borland公司的產品推出速度卻是「驚人」,很多都還沒有用過Delphi6,Delphi7就快要出來了,Borland公司只是在技術上推出新產品,但在服務上卻始終不見前進,在這點上Borland要多學習Microsoft,做一個產品要很踏實,升級太平凡會顯得「落後的」,記得以前Borland C 就是因為過快的發佈,而沒有足夠的測試,導致出現很多Bug,很多用戶轉向了Microsoft的Visual C ,要不是Delphi力挽狂瀾,Borland早就Game Over了,希望Borland不要重蹈覆轍,相信很多和我一樣的Borland忠實用戶都不希望看到這樣。
|
kensoong
初階會員 發表:31 回覆:70 積分:45 註冊:2003-05-28 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |