6

I am running a Delphi XE7 VCL app on Windows 7.

I have observed that the TEdit.OnChange event triggers when Ctrl+A (select all) is pressed. Why is that?

I need to reliably trigger the OnChange event only when the text in the TEdit really changes. Unfortunately, no OnBeforeChange event is available so I can compare the text before and after a change.

So, how to implement a reliable OnChange event for TEdit?

Kromster
  • 7,181
  • 7
  • 63
  • 111
Gabriel
  • 20,797
  • 27
  • 159
  • 293
  • Is this VCL or FMX? – David Heffernan Feb 14 '17 at 15:33
  • Why does it matter if OnChange fires? Perhaps there's a more elegant solution? – J... Feb 14 '17 at 15:45
  • @J... - Perhaps, but the fact that OnChange triggers when there is no actual change is interesting enough :) Reason: In the OnChange even I create and assign an unique ID to the file entered by the user in the Edit box. If the event triggers more than once, more than one ID is generated and I don't want that. But as you said, I can change the design to go around that pesky OnChange. – Gabriel Feb 14 '17 at 15:53
  • 1
    @NAZCA by using OnChange, you would be generating a new ID every time the user types a new character. Why not require the user to click a button or menu item or something after input has been fully entered? – Remy Lebeau Feb 14 '17 at 16:13
  • @RemyLebeau - Yes, I will change the design. – Gabriel Feb 14 '17 at 16:33

1 Answers1

3

Yes, it's not a bad base implementation:

procedure TCustomEdit.CNCommand(var Message: TWMCommand);
begin
  if (Message.NotifyCode = EN_CHANGE) and not FCreating then Change;
end;

This message comes not taking in consideration that the 'A' that is the button that is firing the EN_CHANGE, currently comes together with the state of ctrl pressed.

What you can do is check if Ctrl is pressed or not:

procedure TForm44.edt1Change(Sender: TObject);

  function IsCtrlPressed: Boolean;
  var
    State: TKeyboardState;
  begin
    GetKeyboardState(State);
    Result := ((State[VK_CONTROL] and 128) <> 0);
  end;
begin
  if IsCtrlPresed then
    Exit;

  Caption := 'Ctrl is not pressed';
end;

To avoid reading the state of the whole key board, you can do what was suggested by David Heffernan:

procedure TForm44.edt1Change(Sender: TObject);

  function IsCtrlPresed: Boolean;
  begin
    Result := GetKeyState(VK_CONTROL) < 0;
  end;
begin
  if IsCtrlPresed then
    Exit;

  Caption := 'Ctrl is not pressed';
end;
Rodrigo Farias Rezino
  • 2,687
  • 3
  • 33
  • 60