0

I am using Delphi 10.2, but the following may apply to other Delphi editions as well. I am developing for Android, but I am debugging the Windows release as well.

TNumberBox has property ValueType and one can set it to Integer. The resulting behavior is inconsistent. From the one side the user can enter the number with decimal digits (e.g. 5.5) and the TNumberBox takes care of it and it returns rounded value from its Value property. So, the ValueType=Integer works in some manner. On the other hand, why TNumberBox displays the Keypad with decimal points (and one can not trim this with KeypadType property down to the integer digits only) and allows to enter decimal point/separator at all in the TNumberBox with ValueType=Integer? So, this is sad thing about Delphi.

I have tried to make workaround with the following code, that filters out decimal separators and other non-digit characters, that execute on TNumberBox.OnTyping event:

function ReadDigits(AValue: string): string;
var i, Len, iHigh, iLow: Integer;
    c: Char;

  function CharIsDigit(AChar: Char): Boolean;
  begin
    Result:=False;
    if (AChar in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) then begin
      Result:=True;
    end;
  end;

begin
  Result:='';

  {iHigh:=High(AValue);
  iLow:=Low(AValue);
  for i:=iHigh downto iLow do begin
    if (AValue[i] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) then begin
      Result:=AValue[i]+Result;
    end;
  end;}

  {//New Delphi uses 0-based strings
  //https://stackoverflow.com/questions/19488010/how-to-work-with-0-based-strings-in-a-backwards-compatible-way-since-delphi-xe5
  Len:=Length(AValue);
  for i:=Len-1 downto 0 do begin
    if (AValue[i] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) then begin
      Result:=AValue[i]+Result;
    end;
  end; }

  //It appears, that question about base is more complex and the answer may depend on the compiler directive
  //https://stackoverflow.com/questions/21852034/delphi-loop-through-the-string
  //It is not immediately clear, whether string-base differs among Windows/Android versions
  for c in AValue do begin
    if CharIsDigit(c) then
      Result:=Result+c;
  end;
end;

procedure TTabbedwithNavigationForm.edIntegerHoursTyping(Sender: TObject);
begin
  edIntegerHours.Text:=ReadDigits(edIntegerHours.Text);
end;

But the resulting behavior is very strange in at least 2 ways:

  1. While 88 ir converted correctly to 88, the 888 is converted to 100! QUESTION UPDATED This point is solved - TNumberBox has Max=100 by default and this was just the effect of the default value.
  2. One can try to click in the TNumberBox and select (highlight/mark) the number (or part of it) with the mouse and even such selection changes the number, obviously, the selection operation triggers OnTyping event etc.

There can be lot of debugging further, but I decided to stop for a moment and consult with other. Am I taking the right path to configure TNumberBox for entering integer values only? And how to do this?

ADDITIONAL UPDATE My use case requires that only positive integer values are allowed. I updated question title and added this note for clarification.

TomR
  • 2,696
  • 6
  • 34
  • 87
  • 1
    `Integer` also implies negative numbers, which you don't honor yet. Input is not restricted to typing alone, it can also come from mouse (context menu > pasting clipboard content) and yet unknown devices. – AmigoJack Mar 07 '22 at 14:04
  • 1
    An unsigned Integer is a `Cardinal` or `DWord` if you want to use proper terms. Also your programming style is quite verbose - your inner function can be reduced to a one-liner of `Result:= AChar in ['0'.. '9'];` – AmigoJack Mar 07 '22 at 15:31
  • 1
    @AmigoJack That's pre-Unicode style. You should get a warning or hint for this, suggesting to use the function ``CharInSet`` – Delphi Coder Mar 07 '22 at 18:30
  • 1
    I generally like `AChar.IsDigit`, but in this case I realise it isn't ideal, since not all digits are Arabic. (For instance, ৯, ໕, and ௫ are all digits.) – Andreas Rejbrand Mar 07 '22 at 19:00
  • 1
    "My use case requires that only positive integer values are allowed." So `0` isn't allowed? – Andreas Rejbrand Mar 07 '22 at 19:04
  • 1
    For 2nd point in question check that `HorzIncrement`/`VertIncrement` are set to zero. – Alex Sawers Mar 08 '22 at 12:43

1 Answers1

1

FilterChar is not a published property of TNumberBox, but I think you can still set it by code, which will allow you to restrict the inputted characters even more.

Rick Hollerich
  • 197
  • 1
  • 7