delphiunicodedelphi-7widestring

Delphi - Store WideStrings inside a program


In the past I used INI-Files to store unicode text, but now I need to store unicode text in the executable. How can I achieve this?

I want to store these letters:

āčēūīšķļņž

Solution

  • If you definitely need to use Delphi 7 there are some variants:

    1. Store strings in resources linked to executable file.

    2. Store strings in big memo or same thing, located on global data module or any other visual or non-visual component and access it by index. It's possible because strings in Delphi resources stored in XML-encoded form. E.g. your symbols example āčēūīšķļņž will be stored as āčēūīšķļņž

    3. Store XML-encoded or Base64-encoded strings in string constants inside your code.

    For string conversion you can use EncdDecd.pas , xdom.pas or some functions of System.pas like UTF8Encode/UTF8Decode.

    To display and edit Unicode strings in Delphi forms you can use special set of Unicode controls like TNT Unicode Controls or subclass original Delphi controls and do some other workarounds by yourself, like described in this excerpt from comments in TntControls.pas (part of TNT Unicode Controls):

    Windows NT provides support for native Unicode windows. To add Unicode support to a TWinControl descendant, override CreateWindowHandle() and call CreateUnicodeHandle().

    One major reason this works is because the VCL only uses the ANSI version of SendMessage() -- SendMessageA(). If you call SendMessageA() on a UNICODE window, Windows deals with the ANSI/UNICODE conversion automatically. So for example, if the VCL sends WM_SETTEXT to a window using SendMessageA, Windows actually expects a PAnsiChar even if the target window is a UNICODE window. So caling SendMessageA with PChars causes no problems.

    A problem in the VCL has to do with the TControl.Perform() method. Perform() calls the window procedure directly and assumes an ANSI window. This is a problem if, for example, the VCL calls Perform(WM_SETTEXT, ...) passing in a PAnsiChar which eventually gets passed downto DefWindowProcW() which expects a PWideChar.

    This is the reason for SubClassUnicodeControl(). This procedure will subclass the Windows WndProc, and the TWinControl.WindowProc pointer. It will determine if the message came from Windows or if the WindowProc was called directly. It will then call SendMessageA() for Windows to perform proper conversion on certain text messages.

    Another problem has to do with TWinControl.DoKeyPress(). It is called from the WM_CHAR message. It casts the WideChar to an AnsiChar, and sends the resulting character to DefWindowProc. In order to avoid this, the DefWindowProc is subclassed as well. WindowProc will make a WM_CHAR message safe for ANSI handling code by converting the char code to #FF before passing it on. It stores the original WideChar in the .Unused field of TWMChar. The code #FF is converted back to the WideChar before passing onto DefWindowProc.