“文本超出备忘录容量”错误

时间:2011-02-01 18:20:35

标签: delphi

我有一个TMemo,其中我尝试加载文本,但我收到此错误:“文本超出备忘录容量”。代码是这样的:Memo1.Lines.LoadFromFile(s) Delphi 7 / Win 7下TMemo的限制是什么?我知道有64KB的限制,但在Win95 / 98下。

注意:此错误是用户发送的屏幕截图。我可以成功加载大文件(5-10 MB)。


更新

这次我收到了一个新的错误报告:

procedure TCLog.Add (s: string; Cl: TColor);
begin
  SelStart:= Length(Text);
  SelAttributes.Color:= Cl;                                              

  S:= GenerateString(Indent, ' ')+ S;
  TRY
    Lines.Add(s);                     <------------------------ HERE  
  EXCEPT    
    on E: Exception DO
     begin
      MesajError('Cannot store string '+ s);
      raise; // re-raise the currently caught exception
     end;
  END;
  if AutoScroll
  then LogScroll;
end;

4 个答案:

答案 0 :(得分:2)

在'stdctrls.pas'中的TMemoStrings.SetTextStr过程中引发异常,以响应发送到备忘录的失败的WM_SETTEXT消息。 VCL查看“SendMessage”的返回值,如果它为“0”则抛出异常。实际上没有办法说明失败的真正原因,正如您从文档中看到的那样,只有特殊的错误代码用于列表框和组合框。

如果用户可以一致地重现错误,您可以考虑向他发送一个特殊版本,将“LoadFromFile”包装在“SetLastError”/“GetLastError”调用之间。


编辑:我想知道如果我将设置文字的实际限制推到备忘录(而不是理论上的限制Jeroen's answer} GetLastError会告诉我什么指)。

var
  s: array [0.. 1073741823] of Char;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  FillChar(s[0], Length(s) - 1, Ord('a'));

  // without line breaks 'SendMessage' takes forever to return
  for i := 1 to Length(s) - 1 do
    if i mod 50 = 0 then begin
      s[i - 1] := #13;
      s[i] := #10;
    end;

  s[Length(s) - 1] := #0;

  SetLastError(0);
  try
    if SendMessage(Memo1.Handle, WM_SETTEXT, 0, Longint(@s[0])) = 0 then
      raise Exception.Create('set text fail');
  except
    ShowMessage(SysErrorMessage(GetLastError));
  end;
end;


限制将根据具体情况而变化,但在此处,上述弹出“没有足够的存储空间可用于处理此命令”。 (f.i。的一半(0.5GB)设置文本没有问题。)

答案 1 :(得分:2)

TMemo是Windows“编辑控件”的包装器; this question的答案解释了如何找出可存储在其中的最大长度,以及如何影响该长度。

- 的Jeroen

答案 2 :(得分:1)

如果我建议您只需要将TMemo取出并放置RichEdit,或者像SynEdit这样的编辑器。

然后,您将不必了解为什么TMemo包装的MS公共控制在您的客户端站点以这种随机和烦人的方式失败。

答案 3 :(得分:0)

我已经使用500,000个字符的字符串测试了TMemo并且它有效:

procedure TForm5.Button1Click(Sender: TObject);
VAR s: string;
begin
 s:= GenerateString(1000000, 'x');
 Memo1.Text:= s;
end;

虽然需要20秒。

后来我用TRichEdit替换了TEdit,我还有其他问题。最后我意识到罪魁祸首是一个包含#0字符的字符串。看起来TRichEdit遇到这个角色时会搞砸。