2012-09-09 34 views
6

ứng dụng của tôi là một ứng dụng không unicode viết bằng Delphi 7.Widestring để chuyển đổi chuỗi trong Delphi 7

Tôi muốn chuyển đổi chuỗi unicode cho ANSI với chức năng này:

function convertU(ws : widestring) : string; 
begin 
    result := string(ws); 
end; 

tôi sử dụng cũng là mã này để thiết lập đúng mã để chuyển đổi.

initialization 
    SetThreadLocale(GetSystemDefaultLCID); 
    GetFormatSettings; 

Nó hoạt động tuyệt vời trong các chủ đề chính VCL nhưng không phải trong một TThread, nơi tôi nhận được một số câu hỏi dấu '?' là kết quả của hàm convertU.

Tại sao không có trong TThread?

+0

Trước tiên, bạn không cần chức năng hoặc kiểu chữ để thực hiện việc này; một chuỗi 'stringVar: = wideStringVar;' đơn giản sẽ hoạt động. Thứ hai, vấn đề là không phải tất cả các WideChars đều có thể chuyển đổi trực tiếp sang AnsiString; một số có chiều rộng lớn hơn một ký tự và một số có các giá trị ký tự không thể đại diện trong AnsiChar và một số phông chữ không chứa tất cả các giá trị Unicode có thể có. Nếu bạn đang thấy * '?', Điều đó có nghĩa là bạn đang hiển thị chúng, đó có thể là vấn đề thứ ba - các luồng không nên truy cập các điều khiển GUI mà không sử dụng 'Sychronize'. Vì bạn không đăng mã hiển thị, thật khó để nói nếu đó là nó. –

+0

Câu hỏi đặt ra là: tại sao tôi nhận được dấu hỏi khi được sử dụng trong TThread? – user382591

+2

Tôi lặp lại: ** Nếu bạn đang nhìn thấy '?', Bạn đang hiển thị văn bản. ** Bạn đã cung cấp ** không mã hoặc thông tin ** về cách bạn hiển thị nó. –

Trả lời

5

Gọi SetThreadLocale() bên trong khối initialization không có hiệu lực trên TThread. Nếu bạn muốn đặt ngôn ngữ của một chủ đề, bạn phải gọi SetThreadLocale() bên trong phương thức TThread.Execute().

Một tùy chọn tốt hơn là không dựa vào SetThreadLocale(). Thực hiện chuyển đổi của riêng bạn bằng cách gọi trực tiếp WideCharToMultiByte() để bạn có thể chỉ định mã trang Ansi cụ thể để chuyển đổi thành.

+0

Cảm ơn sự giúp đỡ của bạn. Nó hoạt động !!! – user382591

+0

Nếu bạn là tác giả của tất cả các mã trong ứng dụng của bạn thì các cuộc gọi rõ ràng đến WideCharToMultiByte là một lựa chọn khả thi. Nếu bạn bao gồm mã của bên thứ ba, thì cài đặt toàn bộ chuỗi của ngôn ngữ có thể là sự thỏa hiệp tốt nhất. –

+0

có. cảm ơn. Tôi sử dụng kết hợp cả hai hiện tại: WideCharToMultiByte AND SetThreadLocale() – user382591

6

AFAIK SetThreadLocale không thay đổi hệ thống hiện tại Mã Page, như vậy sẽ không ảnh hưởng đến việc chuyển đổi widestring để ansistring trong Delphi 7, mà dựa vào GetACP gọi API, ví dụ: hệ thống Mã Trang.

Trang mã hệ thống được đặt, ví dụ: trong Windows Seven trong Control Panel, sau đó là Region Languages ​​/ Administrative tab/Code Page cho các ứng dụng không phải Unicode. Điều này cần khởi động lại hệ thống.

Delphi 7 sử dụng trang Mã hệ thống này, cung cấp 0 cho tất cả các lệnh gọi API chuyển đổi. Vì vậy AFAIR SetThreadLocale sẽ không ảnh hưởng đến chuyển đổi widestring sang ansistring ở Delphi 7. Nó sẽ thay đổi ngôn ngữ (ví dụ: ngày/giờ và định dạng tiền tệ), không phải trang mã được hệ thống sử dụng để chuyển đổi Ansi < -> Unicode.

Phiên bản mới hơn của Delphi có chức năng SetMultiByteConversionCodePage(), có thể đặt trang mã sẽ được sử dụng cho tất cả xử lý AnsiString.

Nhưng các cuộc gọi API (nghĩa là tất cả các chức năng ....A() trong Windows.pas được ánh xạ bởi ...() trong Delphi 7) sẽ sử dụng trang mã hệ thống này. Vì vậy, bạn sẽ phải gọi API rộng ...W() sau khi chuyển đổi sang Unicode nếu bạn muốn xử lý một trang mã khác. Nghĩa là, VCL Delphi 7 sẽ chỉ hoạt động với trang mã hệ thống, không phải giá trị được chỉ định bởi SetThreadLocale.

Dưới Delphi 7, lời khuyên của tôi là:

  • Sử dụng WideString ở khắp mọi nơi, và "Wide" cuộc gọi API cụ thể - có một số thiết lập của các thành phần cho Delphi 7 mà xử lý WideString;
  • Sử dụng các loại của riêng bạn, với bộ ký tự chuyên dụng, nhưng bạn cần chuyển đổi rõ ràng trước khi sử dụng các lệnh gọi API VCL/RTL hoặc "Ansi" - ví dụ: MyString = type AnsiString (đây là những gì chúng tôi làm trong mORMot, bằng cách xác định một loại tùy chỉnh RawUTF8 cho quy trình UTF-8 nội bộ).

Điều này được xử lý tốt hơn với Delphi 2009 trở lên, vì bạn có thể chỉ định trang mã cho mọi loại AnsiString và xử lý đúng cách chuyển đổi sang/từ Unicode, cho các cuộc gọi API hoặc quá trình VCL.

+0

+1 Tôi tin rằng điều này là chính xác. –

+0

Tôi chỉ muốn xử lý bảng mã hệ thống mặc định. Những gì tôi đã nhận thấy, là cho Unicode <-> Ansi chuyển đổi, các mã được sử dụng là người dùng DEFAULT LCID và không phải là hệ thống DEFAULT LCID và đó là một vấn đề. – user382591