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 Защото Jens иска невизуален клас, който ще извършва обработка на текст към и от 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; - person Remy Lebeau; 04.06.2013
comment
Благодаря Дейвид. Имах същия проблем с TRichEdit кодиране на набор от символи и този код реши проблема, като същевременно ми спести много време. - person Steve F; 16.02.2021