One possible solution may be to use an Editmask. You can constrain the characters as they are entered, but they are not acted on util the cell is exited.
Set it like this:
Procedure TForm1.StringGrid1GetEditMask(Sender: TObject; ACol, ARow: integer;
Var Value: string);
Begin
//'!' = delete leading blanks. '0' = position must be a number.
//'1' = keep formatting symbols. '_' = trailing '0'.
//Does not limit fields to 23:59:59.
//Use ValidateEntry and Copy()to check and change each character as the cell is exited.
If (ARow > 0) and (ACol = 1) Then
Value := '!99:99:99;1;_';
End;
Validate it like this:
Procedure TForm1.StringGrid1ValidateEntry(Sender: TObject; aCol, aRow: integer;
Const OldValue: string; Var NewValue: string);
Var
I: integer;
Begin
//Constrain to '23:59:59'.
//This only takes effect on leaving cell.
If (aRow > 0) and (aCol = 1) Then
Begin
If Copy(NewValue, 1, 1) > '2' Then
NewValue[1] := '2';
If Copy(NewValue, 2, 1) > '3' Then
NewValue[2] := '3';
If Copy(NewValue, 4, 1) > '5' Then
NewValue[4] := '5';
If Copy(NewValue, 7, 1) > '5' Then
NewValue[7] := '5';
For I := 1 To length(NewValue) Do //Replace any empty characters with '0' ie #32
If (Copy(NewValue, I, 1) = ' ') Then
NewValue[I] := '0';
If (length(NewValue) = 0) Then //Insert '00:00:00' if no value is entered.
NewValue := '00:00:00';
End;
End;