2013-06-03 3 views
2

Я пытаюсь написать класс оболочки вокруг TRichEdit, который может кодировать и декодировать RTF в/из открытого текста.Поддерживает ли TRichEdit Unicode?

Это то, что я написал до сих пор:

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 кодировке пользователь по умолчанию.

Он не работает (преобразует их в ?) для других персонажей.

Есть ли простой способ включить правильную обработку Юникода в моем коде?

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

+0

Немного не по теме: Почему вы не наследует от 'TRichEdit' вместо этого? –

+1

@JerryDodge: Тогда это станет контролем. –

+0

@AndreasRejbrand Ну да, это была моя точка. Мне просто интересно, почему это не унаследованный контроль. –

ответ

2

Я думаю, что вы слишком усложняете это. Нет необходимости использовать свойство 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; 
+1

В стороне, я не убежден в 'TRichEdit.CreateParented (HWND_MESSAGE)'. Когда я использовал это, я обнаружил, что форматирование может быть искажено при испускании RTF. Я бы использовал 'TRichEdit.Create (nil)', а затем назначил элементы управления ParentWindow' Application.Handle'. –

+1

Так что использование 'LoadFromStream' для открытого текста Unicode не работает вообще? –

+0

Что касается родителя: что бы вы использовали в консольном приложении? –