Delphi TNumberBox - 如何仅允许正整数值?

发布于 2025-01-12 16:47:18 字数 2391 浏览 0 评论 0原文

我使用的是 Delphi 10.2,但以下内容也可能适用于其他 Delphi 版本。 我正在为 Android 进行开发,但我也在调试 Windows 版本。

TNumberBox 具有 ValueType 属性,可以将其设置为 Integer。由此产生的行为是不一致的。一方面,用户可以输入带有十进制数字的数字(例如5.5),TNumberBox 会处理它并从其Value 属性返回四舍五入的值。因此,ValueType=Integer 以某种方式工作。另一方面,为什么 TNumberBox 显示带有小数点的键盘(并且不能使用 KeypadType 属性将其修剪为仅整数位)并允许在 TNumberBox 中输入小数点/分隔符与 ValueType=Integer?所以,这是德尔福的悲哀。

我尝试使用以下代码进行解决方法,过滤掉在 TNumberBox.OnTyping 事件上执行的小数分隔符和其他非数字字符:

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;

但结果行为至少在两种方面非常奇怪:

  1. 88< /code> ir 正确转换为 88888 转换为 100问题已更新这一点已解决 - TNumberBox 默认情况下有 Max=100,这只是默认值的效果。
  2. 可以尝试单击 TNumberBox 并用鼠标选择(突出显示/标记)数字(或其一部分),甚至这样的选择也会改变数字,显然,选择操作会触发 OnTyping 事件等。

可以有很多调试更进一步,但我决定停下来咨询一下其他人。我是否采取了正确的路径来配置 TNumberBox 以仅输入整数值?以及如何做到这一点?

额外更新 我的用例要求只允许整数值。我更新了问题标题并添加了此注释以进行澄清。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

黯然 2025-01-19 16:47:18

FilterChar 不是 TNumberBox 的已发布属性,但我认为您仍然可以通过代码设置它,这将允许您进一步限制输入的字符。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文