IceCold
IceCold

Reputation: 21154

How to know when the USER changed the text in a TMemo/TEdit?

I was always bugged by the fact that TMemo (and other similar controls) only have the OnChange event. I would like to know when the USER changed the text, not when the text was changed programmatically.

I know two methods to discriminate between the user changed text and programmatically changed text:

  1. Put OnChange:= NIL before you change the text programmatically. Then restore the OnChange. This is error prone as you need to remember to do it every time you change text from the code (and to which memos/edits needs this special treatment to be applied). Now we know that every time the OnChange is called, the control was edited by user.
  2. Capture the OnKeyPress, MouseDown, etc events. Decide if the text was actually changed and manually call the code that needs to be called when user edited the ext. This could add a big amount of procedures to an already large file.

There is a more elegant way to do it?

Upvotes: 3

Views: 1909

Answers (2)

Magnus
Magnus

Reputation: 18758

How about using the Modified property?

procedure TForm1.MyEditChange(Sender: TObject);
begin
    if MyEdit.Modified then
    begin
        // The user changed the text since it was last reset (i.e. set programmatically)

        // If you want/need to indicate you've "taken care" of the 
        // current modification, you can reset Modified to false manually here.
        // Otherwise it will be reset the next time you assign something to the 
        // Text property programmatically.
        MyEdit.Modified := false;
    end;
end;

Upvotes: 3

kobik
kobik

Reputation: 21252

You can write a helper procedure to do your option 1, and use it in your framework whenever you want to ensure no OnChange event is triggered when you set the text. e.g.:

type
  TCustomEditAccess = class(TCustomEdit);

procedure SetEditTextNoEvent(Edit: TCustomEdit; const AText: string);
var
  OldOnChange: TNotifyEvent;
begin
  with TCustomEditAccess(Edit) do
  begin
    OldOnChange := OnChange;
    try
      OnChange := nil;
      Text := AText;
    finally
      OnChange := OldOnChange;
    end;
  end;
end;

TMemo has also the Lines property which also triggers OnChange, so you can make another similar procedure that accepts Lines: TStrings argument.

Upvotes: 5

Related Questions