Использование TRichEdit во время выполнения без определения родителя - PullRequest
18 голосов
/ 12 июля 2010

Мне нужно использовать TRichEdit во время выполнения для выполнения преобразования rtf в текст, как обсуждено здесь .Мне удалось это сделать, но мне пришлось установить фиктивную форму в качестве родительской, если нет, я не могу заполнить TRichedit.Lines.(Ошибка: родитель отсутствует).Я вставляю свою функцию ниже, может кто-нибудь предложить способ избежать определения родителя?Можете ли вы также прокомментировать это и сказать мне, если вы найдете более производительную идею?

Примечание: мне нужна строка, а не TStrings в качестве вывода, поэтому она была разработана следующим образом.*

ОБНОВЛЕНИЕ : После ответа я обновил функцию и напишу ее здесь для справки:

function RtfToText(const RTF: string;ReplaceLineFeedWithSpace: Boolean): string;
var
  RTFConverter: TRichEdit;
  MyStringStream: TStringStream;
begin
  RTFConverter := TRichEdit.CreateParented(HWND_MESSAGE);
  try
    MyStringStream := TStringStream.Create(RTF);
    try
      RTFConverter.Lines.LoadFromStream(MyStringStream);
      RTFConverter.PlainText := True;
      RTFConverter.Lines.StrictDelimiter := True;
      if ReplaceLineFeedWithSpace then
        RTFConverter.Lines.Delimiter := ' '
        else
        RTFConverter.Lines.Delimiter := #13;
      Result := RTFConverter.Lines.DelimitedText;
    finally
      MyStringStream.Free;
    end;
  finally
    RTFConverter.Free;
  end;
end;

Ответы [ 4 ]

30 голосов
/ 12 июля 2010

Элемент управления TRichEdit является оболочкой для элемента управления RichEdit в Windows.Элементы управления Windows ... ну ... Windows, и им нужен дескриптор окна для работы.Delphi должен вызвать CreateWindow или CreateWindowEx для создания дескриптора, и обеим подпрограммам нужен действительный родительский дескриптор окна для работы.Delphi пытается использовать дескриптор родительского элемента управления (и это имеет смысл!).К счастью, можно использовать альтернативный конструктор (конструктор CreateParanted(HWND)), и приятные люди из Microsoft составили HWND_MESSAGE, который будет использоваться в качестве родительского для окон, которым на самом деле не нужно «окно» (только для обмена сообщениями).1003 *

Этот код работает как ожидалось:

procedure TForm2.Button2Click(Sender: TObject);
var R:TRichEdit;
    L:TStringList;
begin
  R := TRichEdit.CreateParented(HWND_MESSAGE);
  try
    R.PlainText := False;
    R.Lines.LoadFromFile('C:\Temp\text.rtf');
    R.PlainText := True;

    Memo1.Lines.Text := R.Lines.Text;
  finally 
    R.Free;
  end;
end;
8 голосов
/ 12 июля 2010

Это часть работы VCL, и вы не сможете заставить ее работать по-другому без каких-либо тяжелых обходных путей.Но вам не нужно определять фиктивную форму, чтобы быть родителем;просто используйте вашу текущую форму и установите visible := false; в TRichEdit.

Если вы действительно хотите улучшить производительность, вы можете исключить цикл, который вы используете для построения строки результата.Он должен много перераспределять и копировать память.Используйте свойство Text TrichEdit.Lines, чтобы получить CRLF между каждой строкой, и DelimitedText, чтобы получить что-то еще, например, пробелы.Они используют внутренний буфер, который выделяется только один раз, что значительно ускоряет объединение, если вы работаете с большим количеством текста.

4 голосов
/ 12 июля 2010

Я использую DrawRichText для рисования RTF без элемента управления RichEdit. (IIRC это называется Элементы управления Rich Windowless Window * .) Может быть, вы можете использовать это также для преобразования - однако я никогда не пробовал это.

0 голосов
/ 12 декабря 2014

Для меня было наиболее полезным начать работу с TRichEdit, но не с конвертацией. Однако это работает, как и ожидалось, и вам не нужно устанавливать разделитель строк:

// RTF to Plain:
procedure TForm3.Button1Click(Sender: TObject);
var
    l:TStringList;
    s:WideString;
    RE:TRichEdit;
    ss:TStringStream;
begin
    ss := TStringStream.Create;
    s := Memo1.Text; // Input String
    RE := TRichEdit.CreateParented(HWND_MESSAGE);
    l := TStringList.Create;
    l.Add(s);
    ss.Position := 0;
    l.SaveToStream(ss);
    ss.Position := 0;
    RE.Lines.LoadFromStream(ss);
    Memo2.Text := RE.Text; // Output String
end;

// Plain to RTF:
procedure TForm3.Button2Click(Sender: TObject);
var
    RE:TRichEdit;
    ss:TStringStream;
begin
    RE := TRichEdit.CreateParented(HWND_MESSAGE);
    RE.Text := Memo2.Text; // Input String
    ss := TStringStream.Create;
    ss.Position := 0;
    RE.Lines.SaveToStream(ss);
    ss.Position := 0;
    Memo1.Text := ss.ReadString(ss.Size); // Output String
end;

Я использую TStringList "l" при преобразовании в обычный, потому что TStringStream каким-то образом помещает каждый отдельный символ в новую строку.

Редактировать: Сделал код немного приятнее и убрал неиспользуемые переменные.

...