Using TRichEdit at runtime without defining a parent

后端 未结 4 1670
囚心锁ツ
囚心锁ツ 2020-12-02 19:02

I need to use a TRichEdit at runtime to perform the rtf to text conversion as discussed here. I succeded in doing this but I had to set a dummy form as parent if not I canno

相关标签:
4条回答
  • 2020-12-02 19:46

    TRichEdit control is an wrapper around the RichEdit control in Windows. Windows's controls are... well.. Windows, and they need an Window Handle to work. Delphi needs to call CreateWindow or CreateWindowEx to create the Handle, and both routines need an valid parent Window Handle to work. Delphi tries to use the handle of the control's parent (and it makes sense!). Happily one can use an alternative constructor (the CreateParanted(HWND) constructor) and the nice people at Microsoft made up the HWND_MESSAGE to be used as parent for windows that don't actually need a "window" (messaging-only).

    This code works as expected:

    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;
    
    0 讨论(0)
  • 2020-12-02 19:49

    I use DrawRichText to draw RTF without a RichEdit control. (IIRC this is called Windowless Rich Edit Controls.) Maybe you can use this also for converting - however I have never tried this.

    0 讨论(0)
  • 2020-12-02 19:50

    This has been the most helpfull for me to get started with TRichEdit, but not with the conversion. This however works as expected and you don't need to set the Line Delimiter:

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

    I'm using the TStringList "l" in the conversion to plain because somehow the TStringStream puts every single character in a new line.

    Edit: Made the code a bit nicer and removed unused variables.

    0 讨论(0)
  • 2020-12-02 19:54

    This is part of the way the VCL works, and you're not going to get it to work differently without some heavy workarounds. But you don't need to define a dummy form to be the parent; just use your current form and set visible := false; on the TRichEdit.

    If you really want to improve performance, though, you could throw out that loop you're using to build a result string. It has to reallocate and copy memory a lot. Use the Text property of TrichEdit.Lines to get a CRLF between each line, and DelimitedText to get somethimg else, such as spaces. They use an internal buffer that's only allocated once, which will speed up the concatenation quite a bit if you're working with a lot of text.

    0 讨论(0)
提交回复
热议问题