Поддерживает ли TRichEdit Unicode?

Я пытаюсь написать класс-оболочку вокруг 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 в моем коде?

Я попытался использовать TEncoding.Unicode и TEncoding.UTF8 в качестве кодировки для TStringStream, когда для TRichEdit установлено значение PlainText := True, но это не сработало.


person Jens Mühlenhoff    schedule 03.06.2013    source источник
comment
Слегка не по теме: почему вы не наследуете вместо этого TRichEdit?   -  person Jerry Dodge    schedule 03.06.2013
comment
@JerryDodge: Тогда это станет контролем.   -  person Andreas Rejbrand    schedule 03.06.2013
comment
@AndreasRejbrand Ну да, это было моей точкой зрения. Мне просто интересно, почему это не унаследованный элемент управления.   -  person Jerry Dodge    schedule 03.06.2013
comment
@Jerry Потому что Йенсу нужен невизуальный класс, который будет выполнять обработку текста в RTF и обратно.   -  person David Heffernan    schedule 03.06.2013
comment
@DavidHeffernan: Тогда Йенсу вообще не следует использовать TRichEdit. Вместо этого Йенсу следует использовать безоконный элемент управления RichEdit.   -  person Remy Lebeau    schedule 04.06.2013
comment
@RemyLebeau Этот API кажется сложным для реализации, стоит ли прилагать усилия по использованию TRichEdit?   -  person Jens Mühlenhoff    schedule 05.06.2013
comment
У Роба Кеннеди здесь есть несколько модулей оболочки: pages.cs.wisc.edu/~rkennedy/ Windowless-RTF   -  person Jens Mühlenhoff    schedule 05.06.2013


Ответы (1)


Я думаю, вы слишком усложняете это. Нет необходимости использовать свойство PlainText. Оставьте значение по умолчанию True. Затем для чтения / записи RTF используйте LoadFromStream и SaveToStream. А для чтения / записи обычного текста используйте свойство 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;
person David Heffernan    schedule 03.06.2013
comment
Кстати, меня не убеждает TRichEdit.CreateParented(HWND_MESSAGE). Когда я использовал это, я обнаружил, что форматирование может быть искажено при передаче RTF. Я бы использовал TRichEdit.Create(nil), а затем назначил элементы управления ParentWindow на Application.Handle. - person David Heffernan; 04.06.2013
comment
Значит, использование LoadFromStream для открытого текста Unicode вообще не работает? - person Jens Mühlenhoff; 04.06.2013
comment
Что касается родителя: что бы вы использовали в консольном приложении? - person Jens Mühlenhoff; 04.06.2013
comment
@ JensMühlenhoff LoadFromStream с открытым текстом Unicode обслуживается кодом. Если честно, я не пытался понять, где у вас что-то пошло не так. Я просто написал свою версию с нуля. - person David Heffernan; 04.06.2013
comment
Для консольного приложения вы, вероятно, захотите создать скрытое окно. Если вы реплицируете то, что сделано с Application.Handle, это сработает. Но я подозреваю, что HWND_MESSAGE это нехорошо. Опять же, я не особо вдавался в подробности. Форматированный текст - не мое! - person David Heffernan; 04.06.2013
comment
Неправильно использовать оконный TRichEdit для невизуальных работ. У Microsoft есть полностью отдельный API для невизуальной работы RTF: Windowless RichEdit controls; - person Remy Lebeau; 04.06.2013
comment
Спасибо, Дэвид. У меня была такая же проблема с кодировкой набора символов TRichEdit, и этот код решил проблему, сэкономив мне много времени. - person Steve F; 16.02.2021