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;
}
}
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):
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);
}
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.