如何检测用户何时完成编辑TStringGrid单元格?

Ren*_*cht 12 delphi events tstringgrid

我想在用户完成输入数据时返回字符串网格中单元格的内容.按下键盘上的Enter键或单击或双击另一个单元格时,用户完成.

在Lazarus中有一种FinishedCellEditing的方法,但在Delphi中则没有.如何在Delphi中检测到它?

z66*_*66z 5

我有相同的问题,但更容易解决,因为我强迫用户按Enter键...

诀窍:我不会让用户在编辑其中时更改为另一个单元格,因此我强制用户必须按Intro/Enter结束编辑,然后我允许更改为其他单元格.

不好的部分是OnKeyPress发生在OnSetEditText之前,所以我尝试使用OnKeyUp ......

我发现只是在编辑单元格时,按Enter/Intro后,OnKeyUp不被触发......这是VCL上的一个BUG ...一个键已被释放而OnKeyUp没有被触发.

所以,我做了另一个技巧绕过那个...使用一个Timer来区分我会做的一点点,所以我让事件OnSetEditText的时间被触发.

让我解释一下我为成功做了些什么......

我通过在OnSelectCell上放置代码来锁定选择另一个单元格,与此类似:

CanSelect:=Not UserIsEditingOneCell;
Run Code Online (Sandbox Code Playgroud)

在OnSetEditText上我输入如下代码:

UserIsEditingOneCell:=True;
Run Code Online (Sandbox Code Playgroud)

所以现在,需要的是检测用户何时按Enter/Intro ...并且我发现了一个可怕的事情,因为我说... OnKeyUp没有被解雇这样的密钥...所以,我将通过使用一个来模拟定时器和使用OnKeyPress,因为OnKeyPress被触发,但OnKeyUp没有,对于Enter键...

所以,在OnKeyPress上我放了类似的东西:

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

这样的计时器事件:

UserIsEditingOneCell:=False;
// Do whatever needed just after the user has finished editing a cell
Run Code Online (Sandbox Code Playgroud)

这是有效的,但我知道这是可怕的,因为我需要使用一个计时器...但我不知道更好的方式...并且因为我不需要让用户去另一个单元格而一个是edinting的有一个有效的价值......我可以使用它.

为什么在地狱里没有像OnEndingEditing这样的事件?

PD:我还注意到OnSetEditText针对每个被按下的键被多次触发,并且在Value参数上具有不同的值...至少在OnGetEditMask事件上设置EditMask值'00:00:00'时.


Mar*_*ema 4

对于 VCL 的 TStringGrid,您需要 OnSetEditText 事件。但请注意,每次用户在任何单元格中更改某些内容时都会触发它。因此,如果您只想在用户完成编辑后执行某些操作,则必须观察事件参数的 row 和 col 值。当然,您需要注意用户结束编辑一个单元格并且不编辑另一个单元格时的情况,例如通过单击 TStringGrid 外部。就像是:

TForm1 = class(TForm)
...
private
  FEditingCol, FEditingRow: Longint;
...
end;

procedure Form1.DoYourAfterEditingStuff(ACol, ARow: Longint);
begin
...
end;

procedure Form1.StringGrid1OnEnter(...)
begin
  EditingCol := -1;
  EditingRow := -1;
end;

procedure Form1.StringGrid1OnSetEditText(Sender: TObject; ACol, ARow: Longint; const Value: string)
begin
  if (ACol <> EditingCol) and (ARow <> EditingRow) then
  begin
    DoYourAfterEditingStuff(EditingCol, EditingRow);
    EditingCol := ACol;
    EditingRow := ARow;
  end;
end;

procedure Form1.StringGrid1OnExit(...)
begin
  if (EditingCol <> -1) and (EditingRow <> -1) then
  begin
    DoYourAfterEditingStuff(EditingCol, EditingRow);
    // Not really necessary because of the OnEnter handler, but keeps the code
    // nicely symmetric with the OnSetEditText handler (so you can easily 
    // refactor it out if the desire strikes you)
    EditingCol := -1;  
    EditingRow := -1;
  end;
end;
Run Code Online (Sandbox Code Playgroud)