Я должен использовать TRichEdit во времени выполнения для выполнения rtf для отправки текстовых сообщений преобразованию, как обсуждено здесь. Я успешно выполнился в выполнении этого, но я должен был установить фиктивную форму как родителя, если не я не могу заполнить TRichedit. Строки. (Ошибка: родитель отсутствует). Я вставляю свой funciton ниже, кто-либо может предложить способ постараться не определять родителя? Можно ли также прокомментировать это и сказать ли мне при нахождении более производительной идеи?
Примечание: Мне нужна строка, не TStrings, как произведено, это - то, почему она была разработана как это.
function RtfToText(const RTF: string;ReplaceLineFeedWithSpace: Boolean): string;
var
RTFConverter: TRichEdit;
MyStringStream: TStringStream;
i: integer;
CustomLineFeed: string;
begin
if ReplaceLineFeedWithSpace then
CustomLineFeed := ' '
else
CustomLineFeed := #13;
try
RTFConverter := TRichEdit.Create(nil);
try
MyStringStream := TStringStream.Create(RTF);
RTFConverter.parent := Form4; // this is the part I don't like
RTFConverter.Lines.LoadFromStream(MyStringStream);
RTFConverter.PlainText := True;
for i := 0 to RTFConverter.Lines.Count - 1 do
begin
if i < RTFConverter.Lines.Count - 1 then
Result := Result + RTFConverter.Lines[i] + CustomLineFeed
else
Result := Result + RTFConverter.Lines[i];
end;
finally
MyStringStream.Free;
end;
finally
RTFConverter.Free;
end;
end;
ОБНОВЛЕНИЕ: После ответа я обновил функцию, и запишите это здесь для ссылки:
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;
Элемент управления TRichEdit - это обертка вокруг элемента управления RichEdit в Windows. Элементы управления Windows - это... ну... Windows, и для работы им нужен Window Handle. Delphi нужно вызвать CreateWindow или CreateWindowEx для создания хэндла, и обеим процедурам для работы нужен действительный хэндл родительского окна. Delphi пытается использовать дескриптор родительского элемента управления (и это имеет смысл!). К счастью, можно использовать альтернативный конструктор (конструктор CreateParanted(HWND)
), а добрые люди из Microsoft придумали HWND_MESSAGE
, чтобы использовать его в качестве родителя для окон, которым на самом деле не нужно "окно" (только для сообщений).
Этот код работает как ожидалось:
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;
Я использую DrawRichText для рисования RTF без элемента управления RichEdit. (IIRC это называется Windowless Rich Edit Controls.) Возможно, вы можете использовать это и для конвертации - однако я никогда не пробовал.
Это часть способа работы VCL, и вы не сможете заставить его работать иначе без серьезных обходных путей. Но вам не нужно определять фиктивную форму в качестве родительской; просто используйте вашу текущую форму и установите visible: = false;
в TRichEdit.
Если вы действительно хотите повысить производительность, вы можете отказаться от цикла, который вы используете для построения строки результата. Он должен много перераспределять и копировать память. Используйте свойство Text TrichEdit.Lines, чтобы получить CRLF между каждой строкой, и DelimitedText, чтобы получить что-то еще, например пробелы. Они используют внутренний буфер, который выделяется только один раз, что немного ускоряет конкатенацию, если вы работаете с большим количеством текста.