delphi rtf trichedit

delphi - Uso de TRichEdit en tiempo de ejecución sin definir un padre



rtf (4)

El control TRichEdit es una envoltura alrededor del control RichEdit en Windows. Los controles de Windows son ... bueno ... Windows, y necesitan un identificador de Windows para funcionar. Delphi necesita llamar a CreateWindow o CreateWindowEx para crear el identificador, y ambas rutinas necesitan un identificador de ventana principal válido para funcionar. Delphi intenta usar el controlador de los padres del control (¡y tiene sentido!). Felizmente, uno puede usar un constructor alternativo (el constructor CreateParanted(HWND) ) y la gente agradable de Microsoft creó el HWND_MESSAGE para ser usado como padre para ventanas que en realidad no necesitan una "ventana" (solo mensajes).

Este código funciona como se espera:

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;

Necesito usar un TRichEdit en tiempo de ejecución para realizar la conversión de rtf a texto como se explica here . Logré hacer esto, pero tuve que establecer una forma ficticia como padre; de ​​lo contrario, no puedo rellenar el TRichedit.Lines. (Error: falta el padre). Pego mi función a continuación, ¿alguien puede sugerir una forma de evitar definir un padre? ¿Puedes también comentar sobre esto y decirme si encuentras una idea más interesante?

Nota: Necesito una cadena, no TStrings como salida, es por eso que ha sido diseñado de esta manera.

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;

ACTUALIZACIÓN : Después de la respuesta actualicé la función y la escribo aquí para referencia:

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;


Esto es parte de la forma en que funciona el VCL, y no va a lograr que funcione de manera diferente sin algunas soluciones pesadas. Pero no es necesario definir una forma ficticia para ser el padre; solo usa tu formulario actual y configura visible := false; en el TRichEdit.

Sin embargo, si realmente desea mejorar el rendimiento, puede tirar ese bucle que está usando para crear una cadena de resultados. Tiene que reasignar y copiar mucho la memoria. Use la propiedad Text de TrichEdit.Lines para obtener un CRLF entre cada línea y DelimitedText para obtener otra cosa, como espacios. Utilizan un búfer interno que solo se asigna una vez, lo que acelerará bastante la concatenación si se trabaja con mucho texto.


Esto ha sido lo más útil para comenzar con TRichEdit, pero no con la conversión. Sin embargo, esto funciona como se esperaba y no es necesario configurar el delimitador de línea:

// 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;

Estoy usando TStringList "l" en la conversión a simple porque, de alguna manera, TStringStream coloca todos los caracteres en una nueva línea.

Editar: hizo el código un poco más agradable y eliminó las variables no utilizadas.