Delphi - 将WideStrings存储在程序中

时间:2011-08-15 12:20:21

标签: delphi unicode delphi-7 widestring

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

我想存储这些信件:

āčēūīšķļņž

5 个答案:

答案 0 :(得分:3)

如果要保存Unicode INI文件,可以尝试以下代码。文件保存在UTF8 encoding

另外,您可以查看this Unicode library,在那里您可以找到许多辅助函数。

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;

enter image description here
在64位Windows 7 Enterprise SP 1上使用Delphi 2007

答案 1 :(得分:2)

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

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

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

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

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

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

      

    Windows NT提供对本机Unicode窗口的支持。加上   对a的Unicode支持       TWinControl后代,覆盖CreateWindowHandle()并调用   CreateUnicodeHandle()。

         

    这有效的一个主要原因是因为VCL仅使用ANSI   的版本       SendMessage() - SendMessageA()。如果你在一个上调用SendMessageA()   UNICODE       窗口,Windows处理ANSI / UNICODE转换   自动。所以       例如,如果VCL使用发送WM_SETTEXT到窗口   SendMessageA,       即使目标窗口,Windows实际上期望一个PAnsiChar   是一个UNICODE       窗口。所以使用PChars来调用SendMessageA不会产生任何问题。

         

    VCL中的问题与TControl.Perform()方法有关。   执行()       直接调用窗口过程并假定ANSI窗口。   这是一个       问题,例如,VCL调用Perform(WM_SETTEXT,...)   传入       PAnsiChar最终通过了劣势DefWindowProcW()   期待PWideChar。

         

    这就是SubClassUnicodeControl()的原因。这个程序   将子类化       Windows WndProc和TWinControl.WindowProc指针。它会   确定是否       消息来自Windows或是否调用了WindowProc   直。然后它会       为Windows调用SendMessageA()以执行正确的转换   某些短信。

         

    另一个问题与TWinControl.DoKeyPress()有关。它是   从WM_CHAR调用       信息。它将WideChar转换为AnsiChar,然后发送   由此产生的性格       DefWindowProc函数。为了避免这种情况,DefWindowProc是   子类也是。的WindowProc       将使ANSI处理代码的WM_CHAR消息安全   将char代码转换为       在传递之前#FF。它将原始的WideChar存储在   。未使用的TWMChar领域。       代码#FF在传递之前转换回WideChar   DefWindowProc函数。

答案 2 :(得分:0)

待办事项

const MyString = WideString('Teksts latvie'#$0161'u valod'#$0101);

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

Widestring(#$65E5#$672C) 的方法不起作用,因为 Delphi 7 只是不希望 # 超过一个字节,因此结果远远不是您在超过 255 或 $ 时所期望的FF。

另一种方法 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 文本。

或者,将常量存储在 ASCII 安全的 UTF-8 中 - 这样您就可以轻松使用 #。一个优点是,编写源代码的麻烦要少得多。一个缺点是,您永远不能直接使用常量,而必须先将其转换为 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 );