Convert Widestring to String in Delphi 7

my application is a non-unicode application written in Delphi 7.

I would like to convert Unicode strings to ANSI using this function:

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

I also use this code to set the correct code page for conversion.

 initialization SetThreadLocale(GetSystemDefaultLCID); GetFormatSettings; 

It works fine in the main VCL thread, but not in TThread, where I get a few '?' Question marks as a result of the convertU function.

Why not in TThread?

+6
source share
2 answers

Calling SetThreadLocale() inside the initialization block does not affect TThread . If you want to set the locale of the thread, you must call SetThreadLocale() inside the TThread.Execute() method.

It’s best not to rely on SetThreadLocale() at all. Do your own conversion by calling WideCharToMultiByte() directly so that you can specify the specific Ansi codepage to convert.

+5
source

AFAIK SetThreadLocale does not change the current system code page, therefore it does not affect the conversion of widestring to ansistring in Delphi 7, which relies on a call to the GetACP API, that is, on the system code page.

The system code page is set, for example. on Windows Seven in the control panel, then the regional languages ​​/ Admin / Codepage tab for applications that do not support Unicode. This requires a system reboot.

Delphi 7 uses this System Code Page, delivering 0 to all calls to the conversion APIs. Therefore, AFAIR SetThreadLocale will not affect the conversion of widestring to ansistring in Delphi 7. It will change the locale (for example, date / time and currency formatting), and not the code page used by the system for its Ansi ↔ Conversion to Unicode.

In newer versions of Delphi, there is the SetMultiByteConversionCodePage() function, which can set the code page that will be used for all ansistring .

But API calls (i.e., all ....A() functions in Windows.pas that map to ...() in Delphi 7) will use this system code page. So you have to call the API ...W() wide after converting to Unicode if you want to process another code page. That is, Delphi 7 VCL will only work with the system code page, not the value specified by SetThreadLocale .

In Delphi 7 my advice is:

  • Use widestring everywhere, and specific "Wide" API calls β€” for Delphi 7, there are several components that handle widestring ;
  • Use your own types with dedicated encoding, but you will need to explicitly convert before using the VCL / RTL or "Ansi" API calls - for example, MyString = type AnsiString (this is what we do in mORMot, defining our own RawUTF8 type for the internal UTF- process 8).

This does a lot better with Delphi 2009 and above, since you can specify a code page for each type of ansistring and handle conversion to / from Unicode correctly for API calls or VCL processes.

+6
source

Source: https://habr.com/ru/post/924943/


All Articles