How can I detect when a user is finished editing a TStringGrid cell?

Renier Engelbrecht picture Renier Engelbrecht · Feb 20, 2011 · Viewed 14.5k times · Source

I would like to return the contents of a cell in a string grid when the user finishes entering the data. The user is finished when pressing the enter key on the keyboard, or single- or double-clicking another cell.

In Lazarus there is a method of FinishedCellEditing, but not in Delphi. How can I detect it in Delphi?

Answer

z666zz666z picture z666zz666z · Oct 23, 2012

I have quite the same problem, but easier solution since i force user to press Enter key...

The trick: I do not let the user change to another cell while is editing one, so i force user to must press Intro/Enter to end editing, then i allow to change to other cell.

The bad part is that OnKeyPress happens before OnSetEditText, so i tried with OnKeyUp...

And what i found is that just when editing a cell, after pressing Enter/Intro, OnKeyUp is not fired... that is a BUG on VCL... a key has being released and OnKeyUp has not being fired.

So, i make another trick to bypass that... use a Timer to differ what i would do just a little, so i let time to event OnSetEditText be fired before.

Let me explain what i have done to success...

I have locked selecting another cell by putting code on OnSelectCell, quite similar to this:

CanSelect:=Not UserIsEditingOneCell;

And on OnSetEditText i put code like this:

UserIsEditingOneCell:=True;

So now, what is needed is to detect when the user press Enter/Intro... and i found a horrible thing as i said... OnKeyUp is not fired for such key... so, i will simulate that by using a Timer and using OnKeyPress, because OnKeyPress is fired, but OnKeyUp not, for Enter key...

So, on OnKeyPress i put something like:

TheTimerThatIndicatesUserHasPressEnter.Interval:=1; // As soon as posible
TheTimerThatIndicatesUserHasPressEnter.Enabled:=True; // But after event OnSetEditText is fired, so not jsut now, let some time pass

An on such timer event:

UserIsEditingOneCell:=False;
// Do whatever needed just after the user has finished editing a cell

That works, but i know that is horrible because i need to use a Timer... but i do not know a better way... and since i need to not let user go to another cell while the one that is edinting does not have a valid value... i can use that.

Why on the hell there is not an event like OnEndingEditing?

P.D.: I have also noticed that OnSetEditText is fired multiple times for each key being pressed, and with different value on Value parameter... at least when working with EditMask value '00:00:00' set on OnGetEditMask event.