Why am I getting RichEdit line insertion error when I call Delete in OnChange event?

时光总嘲笑我的痴心妄想 提交于 2019-12-05 18:27:46

You are getting the RichEdit line insertion error because of check added to the Delphi 2009 version. This check verifies if the insertion of a new line has been successful and this check uses for it the selection position. Unfortunately, for the following piece of code:

procedure TForm1.Button1Click(Sender: TObject);
begin
  RichEdit1.Clear;
  RichEdit1.Lines.Add('1');
end;

procedure TForm1.RichEdit1Change(Sender: TObject);
begin
  if RichEdit1.Lines.Count > 0 then
    RichEdit1.Lines.Delete(0);
end;

The workflow looks like this:

1. - TRichEdit.Lines.Add → TRichEdit.Lines.Insert

Get the position of the first char for the line where the string will be inserted, add the linebreak to that string, setup the selection (0 length, starting at the line beginning) and insert the string by performing EM_REPLACESEL message, what except the text insertion, changes also the selection position. The check mentioned above has not been performed yet, and in the meantime that text insertion causes the OnChange event to fire, where the TRichEdit.Lines.Delete is called.

2. - TRichEdit.Lines.Delete

Delete does something similar. It gets the first character index of the deleted line, setup the selection, now in the whole line length and performs the EM_REPLACESEL message with the empty string. But it also changes the selection position of course. And that's the problem, because we are now going back to the last line of the TRichEdit.Lines.Insert function.

3. - TRichEdit.Lines.Add → TRichEdit.Lines.Insert

Now the last thing of a previous call of the TRichEdit.Lines.Insert function remains to be done, the evil check based just on the selection position. And since the position has been changed by the meantime deletion, it doesn't match to the expected result and you are getting the error message.

Also, before someone fix this issue, don't use even this, it will cause the same error:

procedure TForm1.Button1Click(Sender: TObject);
begin
  RichEdit1.Lines.Add('1');
end;

procedure TForm1.RichEdit1Change(Sender: TObject);
begin
  RichEdit1.SelStart := 0;
end;

If you didn't fell asleep from this boring story, then I can suggest you just to avoid the manipulation with the lines in OnChange event as much as you can (better to say, only when you know what can happen).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!