TEdit and TCheckBox Validations

142 views Asked by At

My purpose is that the users will never be able to check a TCheckBox when the number is entered into a TEdit less than 7 digits. Also, this TCheckBox can never be checked when the TEdit is being empty.

A problem of my codes is sometimes TCheckBox can still be checked although TEdit is being empty.

Moreover, my another target is that the start button can never be executed or will always display an error message if the start button is clicked when the TCheckBox is checked while the TEdit is being empty.

The problem is what codes should I put in the start button ?.

I am using the following code:

//--------------------------------------------------------------------------------
void __fastcall TForm::MyTEditBoxKeyPress(TObject *Sender, System::WideChar &Key)
{
    if( Key == VK_BACK ) return;
    if((Key < '1') || (Key > '9'))
    {
        MessageDlg("Please enter number only.",mtInformation, TMsgDlgButtons()<< mbOK, 0);
        Key = 0;
    }
}
//--------------------------------------------------------------------------------
void __fastcall TForm::MyTEditBoxExit(TObject *Sender)
{
    if (MyTEditBox->Text.Length() < 7) {
        MessageDlg("Please enter at least 7 digit.",mtInformation, TMsgDlgButtons()<< mbOK, 0);
    }
}
//--------------------------------------------------------------------------------
void __fastcall TForm::MyCheckBoxClick(TObject *Sender)
{
    if (MyCheckBox->Tag == 0 ) {
        MyCheckBox->Tag = 1;
        if (MyTEditBox->Text.Length() >= 7)
            MyCheckBox->Checked = true;
        IdThrottler->BitsPerSec = StrToInt64(MyTEditBox->Text);
    }
    else {
        MyCheckBox->Tag = 0;
        if (MessageDlg("Please enter at least 7 digit.",mtInformation, TMsgDlgButtons()<< mbOK, 0) == mrYes)
            MyCheckBox->Checked = false;
    }
}
1

There are 1 answers

3
Remy Lebeau On BEST ANSWER

First off, the throttler's BitsPerSec property is an int, not an __int64, so you should be using StrtoInt() instead of StrToInt64().

You are setting the TCheckBox::Enabled property in the TCheckBox::OnClick event, so the user has to actually click on the TCheckBox to make it update itself. If the user only typed in the TEdit and never clicks on the TCheckBox, it will never be updated.

If you don't want the user to click on the TCheckBox at all unless the TEdit text is adequate, you should use the TEdit::OnChange event to set the TCheckBox::Enabled property, and get rid of your TCheckBox::Tag handling altogether:

void __fastcall TMyForm::MyTEditBoxChange(TObject *Sender)
{
    MyCheckBox->Enabled = (MyTEditBox->GetTextLen() >= 7);
}

void __fastcall TMyForm::MyCheckBoxClick(TObject *Sender)
{
    if (MyCheckBox->Checked)
        IdThrottler->BitsPerSec = StrToInt(MyTEditBox->Text);
    else
        IdThrottler->BitsPerSec = 0;
}

Do note that just because the user can type in more than 6 digits does not mean its Text represents a value int value. In that situation, StrToInt() will raise an exception.

A different way to handle this is to add a TActionList to your Form, create a custom action in it, assign that action to the TCheckBox::Action property, and then use the TAction::OnUpdate event to set the TAction::Enabled property (which will enable/disable the TCheckBox):

void __fastcall TMyForm::MyActionUpdate(TObject *Sender)
{
    MyAction1->Enabled = (MyTEditBox->GetTextLen() >= 7);
}

The benefit of this approach is that the TCheckBox::Enabled property will be updated automatically and in real-time without having to manually react to changes in the TEdit at all.

With that said, if you are using a modern version of C++Builder, TEdit has a NumbersOnly property. When set to true, you don't have to filter keystrokes in the TEdit::OnKeyPress event anymore, the OS will prevent the user from typing non-digit characters for you (besides, when you are filtering manually, you are not allowing the user to type in 0 digits, which is wrong).

If you really must allow the user to enter a number via a TEdit, and if the TEdit::NumbersOnly property is not available in your version of C++Builder, you still have a couple of other options (which you should consider anyway, even in modern C++Builder versions):

  1. make the TEdit read-only, attach a TUpDown to it via the TUpDown::Associate property, and assign appropriate TUpDown::Min and TUpDown::Max values as needed. Use the TUpDown::Position property to update the throttler's BitsPerSec property:

    void __fastcall TMyForm::MyActionUpdate(TObject *Sender)
    {
        MyAction1->Enabled = (MyUpDown->Position > 999999);
    }
    
    void __fastcall TMyForm::MyUpDownClick(TObject *Sender, TUDBtnType Button)
    {
        if ((MyCheckBox->Enabled) && (MyCheckBox->Checked))
            IdThrottler->BitsPerSec = MyUpDown->Position;
        else
            IdThrottler->BitsPerSec = 0;
    }
    

    Maybe also use a TTrackBar that sets the TUpDown::Value property in larger increments so the user does not have to press the up/down arrows for more than small adjustments:

    void __fastcall TMyForm::MyTrackBarChange(TObject *Sender)
    {
        MyUpDown->Position = MyTrackBar->Position;
        MyUpDownClick(NULL, btNext);
    }
    
  2. Don't bother using a TEdit at all. Use a TCSpinEdit or TSpinEdit instead (depending on your version of C++Builder). The user can type in numbers, and it will reject non-numeric input. It provides up/down arrows, like TUpDown, for making small adjustments. And it has a Value property that returns/accepts an int instead of a String, just like the TUpDown::Position property.

    void __fastcall TMyForm::MyActionUpdate(TObject *Sender)
    {
        MyAction1->Enabled = (MySpinEdit->Value > 999999);
    }
    
    void __fastcall TMyForm::MySpinEditChange(TObject *Sender)
    {
        if ((MyCheckBox->Enabled) && (MyCheckBox->Checked))
            IdThrottler->BitsPerSec = MySpinEdit->Value;
        else
            IdThrottler->BitsPerSec = 0;
    }
    

Either way, the user cannot enter non-numeric values at all, and the TCheckBox still auto-disables itself for values that are smaller than your desired threshold.