Delphi - 将WideStrings存储在程序中

问题描述 投票:-2回答:3

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

我想存储这些信件:

āčēūīšķļņž
delphi unicode delphi-7 widestring
3个回答
2
投票

如果你肯定需要使用Delphi 7,那么有一些变种:

  1. 将字符串存储在链接到可执行文件的资源
  2. 将字符串存储在大备忘录或同一事物中,位于全局数据模块或任何其他可视或非可视组件上,并通过索引访问它。这是可能的,因为Delphi资源中的字符串以XML编码形式存储。例如。您的符号示例āčēūīšķļņž将存储为āčēūīšķļņž
  3. 将XML编码或Base64编码的字符串存储在代码中的字符串常量中。

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

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

Windows NT提供对本机Unicode窗口的支持。要向TWinControl后代添加Unicode支持,请覆盖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,最终会通过dweo DefWindowProcW(),它需要一个PWideChar,这就是一个问题。

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

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


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;

使用64位Windows 7 Enterprise SP 1上的Delphi 2007


0
投票

const MyString = WideString('Teksts latvie'#$0161'u valod'#$0101);
© www.soinside.com 2019 - 2024. All rights reserved.