TEdit and TCheckBox Validations - edit

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.

Related

How can I fix a NulPointerException in this line?

I am coding UNO and want to make a method to check if the player can throw a card mathcing that on the table. If not, then method return true and the player can draw extra cards. If a match can be made, then the method returns false and the player can not draw cards.
I have made a label for the card on the table, called discardpileLabel and an JButton arraylist for the players cards. The method isValid() is called when draw button is clicked.
public boolean isValid ()
{
int i = 0;
do
{
if ((discardpileLabel.getName()).charAt(0) == (playersCards2.get(i)).getName()).charAt(0)
||(discardpileLabel.getName()).charAt(1) == ((playersCards2.get(i)).getName()).charAt(1))
{
return false;
} else i++;
} while (i < playersCards2.size());
return true;
}
I want the nullPointerException on the if statement to go away.
If you want to throw Custom Exceptions
Check : Custom Exception C#

Best way "select all" on a *form*? [duplicate]

I'm looking for a best way to implement common Windows keyboard shortcuts (for example Ctrl+F, Ctrl+N) in my Windows Forms application in C#.
The application has a main form which hosts many child forms (one at a time). When a user hits Ctrl+F, I'd like to show a custom search form. The search form would depend on the current open child form in the application.
I was thinking of using something like this in the ChildForm_KeyDown event:
if (e.KeyCode == Keys.F && Control.ModifierKeys == Keys.Control)
// Show search form
But this doesn't work. The event doesn't even fire when you press a key. What is the solution?
You probably forgot to set the form's KeyPreview property to True. Overriding the ProcessCmdKey() method is the generic solution:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if (keyData == (Keys.Control | Keys.F)) {
MessageBox.Show("What the Ctrl+F?");
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
On your Main form
Set KeyPreview to True
Add KeyDown event handler with the following code
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.N)
{
SearchForm searchForm = new SearchForm();
searchForm.Show();
}
}
The best way is to use menu mnemonics, i.e. to have menu entries in your main form that get assigned the keyboard shortcut you want. Then everything else is handled internally and all you have to do is to implement the appropriate action that gets executed in the Click event handler of that menu entry.
You can even try this example:
public class MDIParent : System.Windows.Forms.Form
{
public bool NextTab()
{
// some code
}
public bool PreviousTab()
{
// some code
}
protected override bool ProcessCmdKey(ref Message message, Keys keys)
{
switch (keys)
{
case Keys.Control | Keys.Tab:
{
NextTab();
return true;
}
case Keys.Control | Keys.Shift | Keys.Tab:
{
PreviousTab();
return true;
}
}
return base.ProcessCmdKey(ref message, keys);
}
}
public class mySecondForm : System.Windows.Forms.Form
{
// some code...
}
If you have a menu then changing ShortcutKeys property of the ToolStripMenuItem should do the trick.
If not, you could create one and set its visible property to false.
From the main Form, you have to:
Be sure you set KeyPreview to true( TRUE by default)
Add MainForm_KeyDown(..) - by which you can set here any shortcuts you want.
Additionally,I have found this on google and I wanted to share this to those who are still searching for answers. (for global)
I think you have to be using user32.dll
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x0312)
{
/* Note that the three lines below are not needed if you only want to register one hotkey.
* The below lines are useful in case you want to register multiple keys, which you can use a switch with the id as argument, or if you want to know which key/modifier was pressed for some particular reason. */
Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF); // The key of the hotkey that was pressed.
KeyModifier modifier = (KeyModifier)((int)m.LParam & 0xFFFF); // The modifier of the hotkey that was pressed.
int id = m.WParam.ToInt32(); // The id of the hotkey that was pressed.
MessageBox.Show("Hotkey has been pressed!");
// do something
}
}
Further read this http://www.fluxbytes.com/csharp/how-to-register-a-global-hotkey-for-your-application-in-c/
Hans's answer could be made a little easier for someone new to this, so here is my version.
You do not need to fool with KeyPreview, leave it set to false. To use the code below, just paste it below your form1_load and run with F5 to see it work:
protected override void OnKeyPress(KeyPressEventArgs ex)
{
string xo = ex.KeyChar.ToString();
if (xo == "q") //You pressed "q" key on the keyboard
{
Form2 f2 = new Form2();
f2.Show();
}
}
In WinForm, we can always get the Control Key status by:
bool IsCtrlPressed = (Control.ModifierKeys & Keys.Control) != 0;
The VB.NET version of Hans' answer.
(There's a ProcessCmdKey function template in Visual Studio.)
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
If (keyData = (Keys.Control Or Keys.F)) Then
' call your sub here, like
SearchDialog()
Return True
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
End Class

qvariant_cast causing segfault

Within qt's item/view framework, I'm trying to save a QColorDialog as user data and then retrieve that dialog as the editor, as well as during paint, in a tableview.
In my class constructor I do
QStandardItem *item = new QStandardItem();
QColorDialog *colorDlg = new QColorDialog(QColor(0,0,255), this);
item->setData(QVariant::fromValue(colorDlg), ColorDialogRole);
mTableModel->setItem(0,2,item);
then, inside my delegate's paint function I have
void ReportFigureTableDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QVariant vColorDlg= index.data(ReportFigure::ColorDialogRole);
if(vColorDlg.isValid())
{
////////////////////////////////////////////////
// Program segfaults on the next line ... why?
////////////////////////////////////////////////
QColorDialog *colorDlg = qvariant_cast<QColorDialog*>(vColorDlg);
if(colorDlg != NULL)
{
painter->save();
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
painter->fillRect(opt.rect, colorDlg->selectedColor());
painter->restore();
}
else
QStyledItemDelegate::paint(painter, option, index);
}
else
QStyledItemDelegate::paint(painter, option, index);
}
During runtime, the table shows up the first time (although with the wrong color ... different issue I assume). I double click to edit the cell and it brings up the dialog as expected. When I close, though, it segfaults on the indicated line. I don't understand why since I think I'm doing all the necessary checks.
You set the data on a QStandardItem object. Meanwhile you are retrieving the data on a QModelIndex object. Now why is the variant valid is a mystery. Maybe because ReportFigure::ColorDialogRole is equal to a build-in Qt role while it should be at least Qt::UserRole.
Anyway In the paint() method you can access the previously set item using
QStandardItem *item = mTableModel->itemFromIndex(index);

Check whether the Control is a Button in c++/cli

How can I check whether the Control^ is a Button^ in the following code?
System::Void DisableControls(Control ^parent)
{
for each (Control^ c in parent->Controls)
{
if(c== /*Check for Button*/)
{
//Do something
}
}
}
You can use GetType() and typeid for this:
if (c->GetType() == Button::typeid) { /* ... */ }
You didn't specify whether you were using WinForms or WPF. The WinForms button, System.Windows.Forms.Button, doesn't have any built-in subclasses, but the WPF button, System.Windows.Controls.Button, does have some subclasses, and if you're using one of those subclasses, you'll miss it if you compare to typeid.
Instead, I'd do a dynamic cast (equivalent to the as keyword in C#), and check for null.
Button b = dynamic_cast<Button^>(c);
if(b != nullptr) { ... }

Edited properties who can't be set to true/false equally

It's hard to explain my problem so give me a break if it's not very clear.
I have some ten properties that can be edited in the view. Most of them are booleans. These properties configure a test environment (like one property can be configured to show the solution).
Now, the problem is that some properties can't be set to true if others are set to false. Nothing would go wrong, but it's just useless. It's like one property would be configured not to show the correct button and another to show the solution. In our system, if you can't click on the correct button, then solution will never be shown.
Does this kind of problem have a name?
Do such properties have a name (just like there are immutable properties)?
Are there best-practices to implement such a story? We can hard code it in the view, but I would rather have a generic system.
The word you're looking for is orthogonality. The settings are not orthogonal, as they can't vary independently.
As to how to handle showing these properties, the completely generic way to do it (and your problem may not warrant the coding cost of this genericicity) would be to give each control an expression that references the other controls, where if the complete expression evaluates to true (or false), the control is disabled in the view.
Easier to code would be a control that exposed an isDisabled() method, which you could override as necessary. Here's a short Java example, which leverages Java anonymous classes to do the hard work. It assumes there's already a Control class, with a booleanValue() getter that converts it to a boolean, and that since AutoDisabledControl is-a Control, it can be used as a drop-in replacement for a Control:
public class AutoDisabledControl extends Control {
public isDisabled() { return false ; }
}
..... usage ....
// control1 is never disabled
final Control1 = new AutoDisabledControl() ;
// Control2 is disabled if control1 is false
final Control2 = new AutoDisabledControl() {
public isDisabled() { return control1.booleanValue() == false; }
};
// conntrol 3 is enabled only if control1 and control2 are true
final Control1 = new AutoDisabledControl() {
public isDisabled() { return ! (
control1.booleanValue()
&& control2.booleanValue()) ;
};
Naturally, in the View's display, it checks each control's isDisabled() , and disables the ones that return true; when a Control's value is changed, the view redisplays. I'm assuming some sort of MVC Pattern.
You propably mismodeled your solution.
Try to think in a different way - perhaps U can eliminate some parameters that can be inferred from the others or u can use enumarations to combine few parameters into one.
Investigate your parameters' value space to find it out.
You could use an int or long to store the related properties and use a bit mask when setting a property to correctly clear invalid settings. This int or long could be in the form of a flagged enumeration.
[Flags]private enum BitValues
{
Bit1 = 1 << 0, //Inclusive
Bit2 = 1 << 1, //Exclusive to bit 3 and 4
Bit3 = 1 << 2, //Exclusive to bit 2 and 4
Bit4 = 1 << 3, //Exclusive to bit 2 and 3
ExclusiveBits = Bit2 | Bit3 | Bit4 //All exclusive bits
}
private BitValues enValues;
public bool Bit1
{
get { return (enValues & BitValues.Bit1) == BitValues.Bit1; }
set
{
//Clear the bit
enValues = (enValues ^ BitValues.Bit1) & enValues;
//Set the bit
enValues = enValues | BitValues.Bit1;
}
}
public bool Bit2
{
get { return (enValues & BitValues.Bit2) == BitValues.Bit2; }
set
{
//Clear exclusive bits
enValues = (enValues ^ BitValues.ExclusiveBits) & enValues;
//Set bit
enValues = enValues | BitValues.Bit2;
}
}