TRichEdit是否支持Unicode?

3
我正在尝试编写一个包装类,围绕TRichEdit进行编码和解码RTF到/从纯文本。

到目前为止,这是我写的:

type
  TRTF = class
  private
    FRichEdit : TRichEdit;
    procedure SetText(const AText: string);
    function GetText: string;
    class function Convert(const AInput: string; AEncode: Boolean): string; inline; static;
  public
    constructor Create;
    destructor Destroy; override;
    class function Decode(const AInput: string): string; static;
    class function Encode(const AInput: string): string; static;
  end;

constructor TRTF.Create;
begin
  FRichEdit := TRichEdit.CreateParented(HWND_MESSAGE);
end;

destructor TRTF.Destroy;
begin
  FRichEdit.Free;
  inherited;
end;

function TRTF.GetText: string;
var
  Stream: TStringStream;
begin
  if FRichEdit.PlainText then begin
    Stream := TStringStream.Create('', TEncoding.ANSI);
  end else begin
    Stream := TStringStream.Create('', TEncoding.ASCII);
  end;
  try
    FRichEdit.Lines.SaveToStream(Stream, Stream.Encoding);
    Result := Stream.DataString;
  finally
    Stream.Free;
  end;
end;

procedure TRTF.SetText(const AText: string);
var
  Stream: TStringStream;
begin
  if FRichEdit.PlainText then begin
    Stream := TStringStream.Create(AText, TEncoding.ANSI);
  end else begin
    Stream := TStringStream.Create(AText, TEncoding.ASCII);
  end;
  try
    Stream.Seek(0, TSeekOrigin.soBeginning);
    FRichEdit.Lines.LoadFromStream(Stream);
  finally
    Stream.Free;
  end;
end;

class function TRTF.Convert(const AInput: string; AEncode: Boolean): string;
var
  RTF: TRTF;
begin
  RTF := TRTF.Create;
  try
    RTF.FRichEdit.PlainText := AEncode;
    RTF.SetText(AInput);
    RTF.FRichEdit.PlainText := not AEncode;
    Result := RTF.GetText;
  finally
    RTF.Free;
  end;
end;

class function TRTF.Encode(const AInput: string): string;
begin
  Result := Convert(AInput, True);
end;

class function TRTF.Decode(const AInput: string): string;
begin
  Result := Convert(AInput, False);
end;

对于可以由用户默认ANSI代码页表示的所有内容,这似乎运行得相当好。

但对于其他字符,则会失败(将其转换为?)。

有没有一种简单的方法,在我的代码中启用正确的Unicode处理?

TRichEdit设置为PlainText := True时,我尝试将TEncoding.UnicodeTEncoding.UTF8用作TStringStream的编码,但那样并不起作用。


有点跑题,为什么你不直接继承自TRichEdit呢? - Jerry Dodge
1
@JerryDodge:那它就会变成一个控件。 - Andreas Rejbrand
3
@Jerry 因为Jens想要一个非可视类,可以执行与RTF文本处理相关的操作。 - David Heffernan
1
@DavidHeffernan:那么Jens根本不应该使用TRichEdit。Jens应该使用无窗口RichEdit控件 - Remy Lebeau
Rob Kennedy在这里提供了一些包装器单元:http://pages.cs.wisc.edu/~rkennedy/windowless-rtf - Jens Mühlenhoff
显示剩余2条评论
1个回答

3

我认为您过于复杂化了这个问题。根本不需要使用 PlainText 属性。将其保持默认设置 True。然后,要读取/编写 RTF,请使用 LoadFromStreamSaveToStream。要读取/编写纯文本,请使用 Lines.Text 属性。

这是我能做到的最简单的解释:

type
  TRTF = class
  strict private
    class function CreateRichEdit: TRichEdit; static;
  public
    class function Decode(const AInput: string): string; static;
    class function Encode(const AInput: string): string; static;
  end;

class function TRTF.CreateRichEdit: TRichEdit;
begin
  Result := TRichEdit.CreateParented(HWND_MESSAGE);
end;

class function TRTF.Encode(const AInput: string): string;
var
  RichEdit: TRichEdit;
  Stream: TStringStream;
begin
  RichEdit := CreateRichEdit;
  try
    RichEdit.Lines.Text := AInput;
    Stream := TStringStream.Create;
    try
      RichEdit.Lines.SaveToStream(Stream);
      Result := Stream.DataString;
    finally
      Stream.Free;
    end;
  finally
    RichEdit.Free;
  end;
end;

class function TRTF.Decode(const AInput: string): string;
var
  RichEdit: TRichEdit;
  Stream: TStringStream;
begin
  RichEdit := CreateRichEdit;
  try
    Stream := TStringStream.Create(AInput);
    try
      RichEdit.Lines.LoadFromStream(Stream);
      Result := RichEdit.Lines.Text;
    finally
      Stream.Free;
    end;
  finally
    RichEdit.Free;
  end;
end;

1
顺便说一句,我对 TRichEdit.CreateParented(HWND_MESSAGE) 不是很满意。当我使用它时,我发现在输出 RTF 时格式可能会被破坏。我会使用 TRichEdit.Create(nil),然后将控件的 ParentWindow 分配给 Application.Handle - David Heffernan
1
那么使用LoadFromStream加载Unicode纯文本根本不起作用吗? - Jens Mühlenhoff
关于父级对象:在控制台应用程序中,您会使用什么? - Jens Mühlenhoff
1
@JensMühlenhoff,代码已经考虑了使用Unicode纯文本的LoadFromStream。老实说,我没有尝试理解你的代码出了什么问题。我只是从头开始编写了自己的版本。 - David Heffernan
1
不正确的做法是在非可视化工作中使用带窗口的TRichEdit。微软为非可视化RTF工作提供了完全独立的API:无窗口的RichEdit控件 - Remy Lebeau
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接