简体   繁体   English

在TRichEdit中加载长RTF文本不起作用

[英]Loading long RTF-Text in TRichEdit does not work

If a long RTF-sequenz (eg 150 000 chars) is streamed into a TRichEdit control (in XE4), the control does not display the text but instead shows the raw RTF code: 如果将长RTF-sequenz(例如150 000个字符)流式传输到TRichEdit控件(在XE4中),则控件不会显示文本,而是显示原始RTF代码:

{\rtf1\ansi\ansicpg1252\deff0...

What is wrong? 怎么了?

procedure TForm1.Button1Click(Sender: TObject);
var
    RtfText: string;
    Stream: TStringStream;
begin
    RtfText := GenerateRtfText();

    Stream := TStringStream.Create(RtfText);
    try
        RichEdit2.PlainText := False;
        RichEdit2.Lines.LoadFromStream(Stream); //<--- ERROR: RichEdit displays raw RTF-Code
                                                //     if RtfText is too long
        if StartsText('{\rtf', RichEdit2.Lines.Text) then
        begin
            ShowMessage('Oh no, not converted!');
            //WORKAROUND: 2nd try seems to work...
            //Stream.Position := 0;
            //RichEdit2.Lines.LoadFromStream(Stream);
        end;
    finally
        Stream.Free;
    end;
end;

For instance with following RTF generation function: 例如,具有以下RTF生成功能:

function TForm1.GenerateRtfText: string;
var
    I: Integer;
    Stream: TStringStream;
const
    DOES_WORK_COUNT = 10000;
    DOES_NOT_WORK_COUNT = 15000;
begin
    //Fill
    RichEdit1.Lines.BeginUpdate;
    try
        //for I := 0 to DOES_WORK_COUNT do
        for I := 0 to DOES_NOT_WORK_COUNT do
          RichEdit1.Lines.Add(IntToStr(I));
    finally
        RichEdit1.Lines.EndUpdate;
    end;
    //Convert to RTF
    Stream := TStringStream.Create;
    try
        RichEdit1.Lines.SaveToStream(Stream);
        Result := Stream.DataString;
    finally
        Stream.Free;
    end;
end;

Edited: Even copy and paste does not work correctly: 编辑:即使复制和粘贴无法正常工作:

This is what I did: 这就是我做的:

  • I copied the generated content of RichEdit1 (lines 1..15000 with numbers 1..15000) into notpad.exe to remove any RTF 我将生成的RichEdit1内容(行号1..15000,数字1..15000)复制到notpad.exe中以删除任何RTF
  • I copied the content of notepad into RichEdit2 我将记事本的内容复制到RichEdit2中

Result: 结果:

  • only 12773 lines are displayed correctly. 只有12773行正确显示。 The last line is only 12 最后一行只有12
  • if I try to add another char into the TRichEdit nothing happens 如果我尝试在TRichEdit中添加另一个char,则没有任何反应
  • if I remove 10 chars (per backspace) I can add exactly 10 chars afterwards... 如果我删除10个字符(每个退格)我之后可以添加10个字符...

Is there a hidden character limit for TRichEdit? TRichEdit是否有隐藏的字符限制?

Rich edit control has a text limit. 丰富的编辑控件具有文本限制。

Try using EM_EXLIMITTEXT message, which sets an upper limit to the amount of text the user can type or paste into a rich edit control. 尝试使用EM_EXLIMITTEXT消息,该消息设置用户可以键入或粘贴到富编辑控件的文本量的上限。 This message also limit the amount of text that you can stream into a rich edit control when streaming RTF ( PlainText = False ). 此消息还限制在流式传输RTF时可以流式传输到富编辑控件的文本量( PlainText = False )。 but does not limit the control when streaming plain text. 但是在流式传输纯文本时不限制控件。

eg: 例如:

const
  RE_MAX_TEXT_SIZE = 256000;

SendMessage(RichEdit1.Handle, EM_EXLIMITTEXT, 0, RE_MAX_TEXT_SIZE);

or: 要么:

SendMessage(RichEdit1.Handle, EM_EXLIMITTEXT, 0, $7FFFFFF0);

for the maximum limit as implemented in TRichEditStrings.LoadFromFile() : RichEdit.DoSetMaxLength($7FFFFFF0); 对于TRichEditStrings.LoadFromFile()实现的最大限制: RichEdit.DoSetMaxLength($7FFFFFF0); However, DoSetMaxLength() is not correctly used in the sources, as it should be called before the stream is loaded. 但是, DoSetMaxLength() 在源中正确使用,因为应在加载流之前调用它。 Also, DoSetMaxLength() is not used at all for TRichEditStrings.LoadFromStream() . 此外, DoSetMaxLength()根本不用于TRichEditStrings.LoadFromStream() Remy mentioned this in the comments of his answers. 雷米在他的回答评论中提到了这一点

In addition to what kobik said: 除了kobik所说的:

TRichEdit.Lines.LoadFromStream() uses EM_STREAMIN internally. TRichEdit.Lines.LoadFromStream()内部使用EM_STREAMIN When TRichEdit.PlainText is false, LoadFromStream() will first try to load the stream data as RTF, and if any error is encountered than it will re-load the stream data as plain text instead. TRichEdit.PlainText为false时, LoadFromStream()将首先尝试将流数据加载为RTF,如果遇到任何错误,则会将流数据重新加载为纯文本。 That is why you see the raw RTF code appear. 这就是您看到原始RTF代码出现的原因。

RTF is an ASCII-based format, and so LoadFromStream() expects 8-bit RTF data (and in the case of PlainText=True , will try to convert it to Unicode). RTF是一种基于ASCII的格式,因此LoadFromStream()需要8位RTF数据(在PlainText=True的情况下,将尝试将其转换为Unicode)。 Try using AnsiString and TMemoryStream instead of (Unicode)String and TStringStream for your RTF stream. 尝试使用AnsiStringTMemoryStream代替(Unicode)StringTStringStream作为RTF流。

type
  TReadOnlyMemoryBufferStream = class(TCustomMemoryStream)
  public
    constructor Create(APtr: Pointer; ASize: NativeInt);
    function Write(const Buffer; Count: Longint): Longint; override;
  end;

constructor TReadOnlyMemoryBufferStream.Create(APtr: Pointer; ASize: NativeInt);
begin
  inherited Create;
  SetPointer(APtr, ASize);
end;

function TReadOnlyMemoryBufferStream.Write(const Buffer; Count: Longint): Longint;
begin
  Result := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  RtfText: AnsiString;
  Stream: TReadOnlyMemoryBufferStream;
begin
  RtfText := GenerateRtfText();

  Stream := TReadOnlyMemoryBufferStream.Create(PAnsiChar(RtfText), Length(RtfText));
  try
    RichEdit2.PlainText := False;
    RichEdit2.Lines.LoadFromStream(Stream);
    ...
  finally
    Stream.Free;
  end;
end;

function TForm1.GenerateRtfText: AnsiString;
var
  I: Integer;
  Stream: TMemoryStream;
const
  DOES_WORK_COUNT = 10000;
  DOES_NOT_WORK_COUNT = 15000;
begin
  //Fill
  RichEdit1.Lines.BeginUpdate;
  try
    //for I := 0 to DOES_WORK_COUNT do
    for I := 0 to DOES_NOT_WORK_COUNT do
      RichEdit1.Lines.Add(IntToStr(I));
  finally
    RichEdit1.Lines.EndUpdate;
  end;

  //Convert to RTF
  Stream := TMemoryStream.Create;
  try
    RichEdit1.PlainText := False;
    RichEdit1.Lines.SaveToStream(Stream);
    SetString(Result, PAnsiChar(Stream.Memory), Stream.Size);
  finally
    Stream.Free;
  end;
end;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM