44 Votes

Delphi/Lazarus: Only allow Numbers in TEdit

Tip by Stefan Trost | Last update on 2022-10-27 | Created on 2017-05-24

Sometimes it may be necessary, that you only want numerical input in an Edit box. The user should only be allowed to type the digits 0 till 9 while letters or other characters should be rejected. In this tutorial, I want to show you, how you can easily realize this behavior in Delphi or Lazarus.

The simplest method is to just use the OnKeyPress-Event of your Edit field. Here is the code.

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if not (Key in ['0'..'9', Char(VK_BACK), Char(VK_DELETE)]) then Key := #0;
end;

This event is triggered at each keypress in the Edit and passes the pressed key within the variable Key as Char even before the keystroke reaches the Edit. Therefore, we have enough time within this element to influence the user input before it is displayed.

We are doing that and as you can see in the code, we are checking whether Key is a digit from 0 to 9 or not in order to consider whether we want to disallow the input. If not, we are setting Key to #0 by which the input is deleted and no longer takes place. Additionally, we also allow VK_BACK (the backspace key) and VK_DELETE (the DEL key) so that the user still has the possibility to correct what he has typed.

Numbers from the Clipboard

One problem of this solution is that maybe users want to insert a number from clipboard. In the example above, keyboard shortcuts such as CTRL + V are rejected to, so that copying from clipboard will not work. However, if we allow clipboard content in general, every user can also copy any other arbitrary non-numeric text into the field without our OnKeyPress event could prevent it.

Here is one solution for this problem using the OnChange event that is triggered each time the value of the Edit is changed.

procedure TForm1.Edit1Change(Sender: TObject);
var
  v: integer;
begin
  if not TryStrToInt(Edit1.Text, v) then begin
     Edit1.Text  := '0';     // default value
     Edit1.Color := clRed;   // color change
  end else begin
     Edit1.Color := clWindow;
  end;
end;

TryStrToInt returns TRUE if the passed string is an integer number, FALSE otherwise. Afterwards, TryStrToInt provides this integer value in the variable v so that we can directly further use it without calling StrToInt.

In the example code, we are running TryStrToInt with the value of our Edit field and if it is not a number, the text color of the Edit is changed to red and the value is set to 0. Of course, you can also omit, adjust or change this colorization or the automatic change like you want and like you want to react to any wrong input.

However, in each case, you should additionally check the value before any processing by code if it is really an integer value.

Allow Decimal Numbers

Up to now, we only cared about integer numbers without any decimal point. As you can imagine, any decimal number like 1.5 or 3,7 will be rejected by both example codes, because of the decimal separator and because those numbers are no integers. In the first example, you have to add the decimal separator to the list of allowed characters to switch the code to floating point numbers. The decimal separator can vary depending on your country settings, so that we are using the constant DecimalSeparator instead of specifying . or , explicitly:

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if not (Key in ['0'..'9', DecimalSeparator, Char(VK_BACK), Char(VK_DELETE)])
  then Key := #0;
end;

If you want to change the second example code to decimal numbers, you can just change the function TryStrToInt to TryStrToFloat. Additionally, you also have to declare the variable v as extended. After this modification, also the second example will work with point numbers:

procedure TForm1.Edit1Change(Sender: TObject);
var
  v: extended;
begin
  if not TryStrToFloat(Edit1.Text, v) then begin
     Edit1.Text  := '0';     // default value
     Edit1.Color := clRed;   // color change
  end else begin
     Edit1.Color := clWindow;
  end;
end;

Of course, also in this case, the OnChange example is the better choice, because the OnKeyPress example is not checking whether the decimal separator is even written at the right place (not at the beginning of the string) or even specified for multiple times which would cause an error when trying to convert the number.

ReplyPositiveNegative

About the Author

AvatarYou can find Software by Stefan Trost on sttmedia.com. Do you need an individual software solution according to your needs? - sttmedia.com/contact
Show Profile

 

Related Topics

Important Note

Please note: The contributions published on askingbox.com are contributions of users and should not substitute professional advice. They are not verified by independents and do not necessarily reflect the opinion of askingbox.com. Learn more.

Participate

Ask your own question or write your own article on askingbox.com. That’s how it’s done.