-2

过去我使用 INI-Files 来存储 unicode 文本,但现在我需要将 unicode 文本存储在可执行文件中。我怎样才能做到这一点?

我想存储这些字母:

āčēūīšķļņž
4

5 回答 5

3

如果要保存 Unicode INI 文件,则可以尝试以下代码。这些文件以UTF8 编码保存。

你也可以看看这个 Unicode 库,在那里你可以找到很多帮助函数。

uses IniFiles;

function WideStringToUTF8(const Value: WideString): AnsiString;
var
  BufferLen: Integer;
begin
  Result := '';

  if Value <> '' then
  begin
    BufferLen := WideCharToMultiByte(CP_UTF8, 0, PWideChar(Value), -1, nil, 0, nil, nil);
    SetLength(Result, BufferLen - 1);
    if BufferLen > 1 then
      WideCharToMultiByte(CP_UTF8, 0, PWideChar(Value), -1, PAnsiChar(Result), BufferLen - 1, nil, nil);
  end;
end;

function UTF8ToWideString(const Value: AnsiString): WideString;
var
  BufferLen: integer;
begin
  Result := '';

  if Value <> '' then
  begin
    BufferLen := MultiByteToWideChar(CP_UTF8, 0, PAnsiChar(Value), -1, nil, 0);
    SetLength(Result, BufferLen - 1);
    if BufferLen > 1 then
      MultiByteToWideChar(CP_UTF8, 0, PAnsiChar(Value), -1, PWideChar(Result), BufferLen - 1);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  IniFile: TIniFile;
const
  UnicodeValue = WideString(#$0101#$010D#$0113#$016B#$012B#$0161);
begin
  IniFile := TIniFile.Create('C:\test.ini');

  try
    IniFile.WriteString('Section', 'Key', WideStringToUTF8(UnicodeValue));
    IniFile.UpdateFile;
  finally
    IniFile.Free;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  IniFile: TIniFile;
  UnicodeValue: WideString;
begin
  IniFile := TIniFile.Create('C:\test.ini');

  try
    UnicodeValue := UTF8ToWideString(IniFile.ReadString('Section', 'Key', 'Default'));
    MessageBoxW(Handle, PWideChar(UnicodeValue), 'Caption', 0);
  finally
    IniFile.Free;
  end;
end;

在此处输入图像描述
在 64 位 Windows 7 Enterprise SP 1 上使用 Delphi 2007

于 2011-08-15T18:36:31.010 回答
2

如果您确实需要使用 Delphi 7,则有一些变体:

  1. 将字符串存储在链接到可执行文件的资源中。

  2. 将字符串存储在大备忘录或相同的东西中,位于全局数据模块或任何其他可视或非可视组件上,并通过索引访问它。这是可能的,因为 Delphi 资源中的字符串以 XML 编码的形式存储。例如,您的符号示例āčēūīšķļņž将存储为&#257;&#269;&#275;&#363;&#299;&#353;&#311;&#316;&#326;&#382;

  3. 将 XML 编码或 Base64 编码的字符串存储在代码中的字符串常量中。

对于字符串转换,您可以使用 EncdDecd.pas、xdom.pas 或 System.pas 的一些函数,如 UTF8Encode/UTF8Decode。

要在 Delphi 表单中显示和编辑 Unicode 字符串,您可以使用特殊的 Unicode 控件集,如TNT Unicode 控件或子类原始 Delphi 控件,并自行执行一些其他解决方法,如 TntControls.pas(TNT Unicode 的一部分)中注释的摘录中所述控制):

Windows NT 提供对本地 Unicode 窗口的支持。要将 Unicode 支持添加到 TWinControl 后代,请覆盖 CreateWindowHandle() 并调用 CreateUnicodeHandle()。

这样做的一个主要原因是因为 VCL 只使用 ANSI 版本的 SendMessage()——SendMessageA()。如果在 UNICODE 窗口上调用 SendMessageA(),Windows 会自动处理 ANSI/UNICODE 转换。例如,如果 VCL 使用 SendMessageA 将 WM_SETTEXT 发送到一个窗口,即使目标窗口是一个 UNICODE 窗口,Windows 实际上也需要一个 PAnsiChar。因此,使用 PChars 调用 SendMessageA 不会导致任何问题。

VCL 中的一个问题与 TControl.Perform() 方法有关。Perform() 直接调用窗口过程并假定一个 ANSI 窗口。例如,如果 VCL 调用 Perform(WM_SETTEXT, ...) 传入一个 PAnsiChar,该 PAnsiChar 最终被传递到需要一个 PWideChar 的 DefWindowProcW(),就会出现问题。

这就是 SubClassUnicodeControl() 的原因。此过程将子类化 Windows WndProc 和 TWinControl.WindowProc 指针。它将确定消息是来自 Windows 还是直接调用了 WindowProc。然后它将调用 Windows 的 SendMessageA() 以对某些文本消息执行正确的转换。

另一个问题与 TWinControl.DoKeyPress() 有关。它是从 WM_CHAR 消息中调用的。它将 WideChar 转换为 AnsiChar,并将生成的字符发送到 DefWindowProc。为了避免这种情况,DefWindowProc 也是子类化的。WindowProc 将通过在传递之前将 char 代码转换为 #FF 来使 WM_CHAR 消息对 ANSI 处理代码安全。它将原始 WideChar 存储在 TWMChar 的 .Unused 字段中。代码#FF 在传递到 DefWindowProc 之前被转换回 WideChar。

于 2011-08-15T15:24:36.910 回答
0

const MyString = WideString('Teksts latvie'#$0161'u valod'#$0101);
于 2011-08-15T12:22:59.127 回答
0

很简单,想法是找到一个非可视组件,它可以存储文本并将您的文本存储在那里。希望这样的组件还可以为您提供一个编辑器来在设计时编辑文本。

有一个组件调用FormResource可以做到这一点。我用TUniScript. 我相信还有其他类似的组件。但是,我没有从标准库中找到可用的组件。

于 2019-09-24T17:31:03.893 回答
0

该方法Widestring(#$65E5#$672C)不起作用,因为 Delphi 7 只是不希望#.

另一种方法WideChar($65E5)+ WideChar($672C)可用于在您的源代码中存储单个 Unicode 代码点,因为您知道您需要Widestring在分配的开头有一个(也可以是空文字),以便编译器了解您想要的数据类型:

const
  // Compiler error "Imcompatible types"
  WONT_COMPILE: WideChar($65E5)+ WideChar($672C);

  // 日本
  NIPPON: Widestring('')+ WideChar($65E5)+ WideChar($672C);

看起来很麻烦,但在 Delphi 7 中肯定有你的 UTF-16 文本。

或者,将常量存储在 UTF-8 中,这是 ASCII 安全的 - 这样您就可以#轻松使用。一个优点是,在源代码中编写起来不那么麻烦。一个缺点是,您永远不能直接使用该常量,而必须先将其转换为 UTF-16:

const
  // UTF-8 of the two graphemes 日 and 本, needing 3 bytes each
  NIPPON: #$E6#$97#$A5#$E6#$9C#$AC;
var
  sUtf16: Widestring;
begin
  // Internally these are 2 WORDs: $65E5 and $672C
  sUtf16:= UTF8ToWideString( NIPPON );
于 2021-05-09T20:43:41.287 回答