6

I found a code here that I needed. To only allow write numbers in a text box. But I still wanted more, which does not offer up the "Next" button without write the number in this text box.

Can help me?

procedure NumbersOnly(Sender: TObject; var Key: Char);
var
  S: string;
begin
  S := ('1234567890'#8);
  if Pos(Key, S) = 0 then 
    Key := #0;
end;
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
user11955
  • 63
  • 1
  • 4
  • Sorry, but your question makes little sense at this time. Do you want to enable the next button only when there is something entered in the edit box ? – TLama Jul 24 '14 at 17:33

3 Answers3

9

You can setup the next button to be enabled or disabled in the CurPageChanged event when the user reaches the page where resides your edit box. Except that you need to monitor changes of that edit box to enable or disable the next button according to whether there's something entered in that edit box. For this you need to write a handler for the OnChange event. Here is an example:

[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program

[Code]
var
  MyEdit: TNewEdit;
  MyPage: TWizardPage;

procedure MyEditChange(Sender: TObject);
begin
  { enable the next button if the edit box is not empty; disable otherwise }
  WizardForm.NextButton.Enabled := MyEdit.Text <> '';
end;

procedure MyEditKeyPress(Sender: TObject; var Key: Char);
var
  KeyCode: Integer;
begin
  { allow only numbers }
  KeyCode := Ord(Key);
  if not ((KeyCode = 8) or ((KeyCode >= 48) and (KeyCode <= 57))) then
    Key := #0;
end;

procedure InitializeWizard;
begin
  MyPage := CreateCustomPage(wpWelcome, 'Caption', 'Description');

  MyEdit := TNewEdit.Create(WizardForm);
  MyEdit.Parent := MyPage.Surface;
  MyEdit.Left := 0;
  MyEdit.Top := 0;
  MyEdit.Width := 150;
  MyEdit.OnChange := @MyEditChange;
  MyEdit.OnKeyPress := @MyEditKeyPress;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  { if the currently turned wizard page is the one with the edit box, enable }
  { the next button if the edit box is not empty; disable otherwise }
  if CurPageID = MyPage.ID then
    WizardForm.NextButton.Enabled := MyEdit.Text <> '';
end;
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
TLama
  • 75,147
  • 17
  • 214
  • 392
  • Thanks, TLana. Is almost perfect. Can you help me in this code: 1st- to create a label before the textbox 2nd- and at the end of the installation write the number of the textbox into a txt file and write this text in txt c:\ Thank you. I am very, very grateful for your help. – user11955 Jul 24 '14 at 20:53
  • My answer was about edit box as it was in your question, but what you are asking for better suits for so called input query page. I think [`this script`](http://pastebin.com/4vCc0PT5) will be better for your overall task. – TLama Jul 24 '14 at 21:09
4

There are two flaws in the @TLama's answer:

  • A user can bypass the check by using Paste command from edit box context menu (and possibly by other kinds of input methods).

    To fix this, you can introduce a last resort check in NextButtonClick.

    I would also suggest adding the check for an empty input there, instead of MyEditChange, as it allows providing feedback to the user, explaining what is wrong.

  • On the other hand, Ctrl+C, Ctrl+V and Ctrl+X keys are not working. Particularly a lack of Ctrl+V is not comfortable.

    To fix this, allow these control characters in the MyEditKeyPress.

[Code]

var
  MyEdit: TNewEdit;
  MyPage: TWizardPage;

procedure ValidateMyEdit;
begin
  { enable the next button if the edit box is not empty; disable otherwise }
  WizardForm.NextButton.Enabled := (MyEdit.Text <> '');
end;  

procedure MyEditChange(Sender: TObject);
begin
  ValidateMyEdit;
end;

function IsDigit(C: Char): Boolean;
begin
  Result := (C >= '0') and (C <= '9')
end;

procedure MyEditKeyPress(Sender: TObject; var Key: Char);
begin
  if not ((Key = #8) or { Tab key }
          (Key = #3) or (Key = #22) or (Key = #24) or { Ctrl+C, Ctrl+V, Ctrl+X }
          IsDigit(Key)) then
  begin
    Key := #0;
  end;
end;

procedure InitializeWizard;
begin
  MyPage := CreateCustomPage(wpWelcome, 'Caption', 'Description');

  MyEdit := TNewEdit.Create(WizardForm);
  MyEdit.Parent := MyPage.Surface;
  MyEdit.Left := 0;
  MyEdit.Top := 0;
  MyEdit.Width := 150;
  MyEdit.OnChange := @MyEditChange;
  MyEdit.OnKeyPress := @MyEditKeyPress;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  if CurPageID = MyPage.ID then
  begin
    ValidateMyEdit;
  end;
end;

function NextButtonClick(CurPageID: Integer): Boolean;
var
  I: Integer;
begin
  Result := True;

  if CurPageID = MyPage.ID then
  begin
    for I := 1 to Length(MyEdit.Text) do
    begin
      if not IsDigit(MyEdit.Text[I]) then
      begin
        MsgBox('Only numbers are allowed', mbError, MB_OK);
        Result := False;
        Break;
      end;
    end;
  end;
end;
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • Martin : `for I := 1 to Length(MyEdit.Text)` **- 1** you do not test last `Char` – moskito-x Jun 17 '17 at 15:16
  • @moskito-x Thanks. Fixed. – Martin Prikryl Jun 17 '17 at 17:14
  • I do not understand your question. `NumbersOnly` does not exist in Inno Setup API. And I do not know, what you mean by `Edit1.Caption := `. – Martin Prikryl Jun 17 '17 at 17:35
  • Though your are right that one can possibly use `GWL_STYLE` `ES_NUMBER` to implement this. But my answer shows more generic implementation, that can be used for wider range of formats, not just numbers-only. – Martin Prikryl Jun 17 '17 at 17:39
  • **I do not understand your question** -> Look here : https://stackoverflow.com/a/44599847/1322642 – moskito-x Jun 17 '17 at 17:41
  • OK, that's Dephi solution, that cannot work in Inno Setup. Vuio probably posted Delphi VCL solution, because Angel asked question with VCL code and Vuio didn't notice the Inno Setup tag. – Martin Prikryl Jun 17 '17 at 17:43
  • And `.Caption` and `.Text` are the same in `TEdit`. It's just that `.Caption` is customary used for display-only controls, while `.Text` is customary used for edit controls. – Martin Prikryl Jun 17 '17 at 17:45
  • There is: http://docwiki.embarcadero.com/Libraries/Berlin/en/Vcl.StdCtrls.TCustomEdit.NumbersOnly – Martin Prikryl Jun 17 '17 at 17:46
0

This is the way I use based on keys from ASCII code:

procedure justNumbers(Sender: TObject; var Key: Char);
begin
  if not ((Key = #8) or (Key = #43) or ((Key >= #48) and (Key <= #57)))
          then
  begin
    Key := #0;
  end;
end; 

Could work for validate others characters too.