I would like to ask what code should I insert to to my "numGPA" to inform the user that they have exceeded the "maximum".
Right now if the try to "submit" a value above the maximum, my visual studio will only play a "ding" sound.
Instead of that I would like to have a message box that says something like "Only a value from 0 to 4 is allowed"
I found this code on Google and despite me changing the numericUpDown1 to numGPA it does not work.
if (numGPA.Value >= 4 || numGPA.Value <= 0)
{
MessageBox.Show("Error. Number must be between 0 and 4");
numGPA.Value = 1;
numGPA.ReadOnly = true;
}
Do take a look at this video to get a clear picture of what I am saying
https://www.youtube.com/watch?v=XVv-it6x044&feature=youtu.be
Instead of the "ding" sound effect played #0.06, I would like a MessageBox.
You can do that with the TextChange event. You can (and should) also set the minimum and maximum properties to limit the input with the arrows.
Private Sub NumericUpDown1_Changed(sender As Object, e As EventArgs) Handles NumericUpDown1.TextChanged
If IsNumeric(NumericUpDown1.Text) AndAlso _
CInt(NumericUpDown1.Text) > NumericUpDown1.Maximum Then MsgBox("Oops! Too big.")
End Sub
The best way is to let the user edit and only check when he has finished. This will trigger the ValueChanged event.
Here we can get at the entered value by grabbing the internal TextBox control.
I suggest using a helper function, maybe like this:
void nudCheck(NumericUpDown nud)
{
TextBox tb = (TextBox) nud.Controls[1];
if (Convert.ToInt32(tb.Text) > nud.Maximum)
{
string msg = tb.Text + " is too large! Setting value to maximum: " + nud.Maximum;
tb.Text = "" + nud.Maximum;
nud.Value = nud.Maximum;
// do what you want with the message string!
//MessageBox.Show(msg); // not recommended!
toolTip1.Show(msg, nud); // add a ToolTip component to your form for this!
}
}
Call it here:
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
nudCheck(numericUpDown1);
}
We also want to suppress the error sound for the case when the user presses Enter, best in the KeyDown event..
private void numericUpDown1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
nudCheck(numericUpDown1);
e.SuppressKeyPress = true;
}
}
Note that bringing up an actual MessageBox will bring back the bell sound and force the user to get rid of it. So I have used a ToolTip, but a Label would also work, if you have the space..
Obviously you may want to add similar code to check input lower than the Minimum..
Related
I have already checked other questions here but the answers are not related to my issue. the following code allows textbox1 to only accept numbers if the physical keyboard (laptop) is pressed:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
char ch = e.KeyChar;
if ( !char.IsDigit(ch))
{
e.Handled = true;
}
}
but this is not what I wanted (I dont use physical laptop keyboard).
As shown in screenshot, I have windows form with buttons and a textbox. I designed this keyboard and it works well but I want textbox1 to only accept numbers and the ".".
There are only two lines of code inside each button (and only code in the project) which is:
private void buttonName_Click(object sender, EventArgs e)
{
// each button only has this code.
textBox1.Focus();
SendKeys.Send(buttonName.Text);
}
I know how to set txtbox to accept numbers if the physical (laptop ) keys are pressed but here in this case I have control buttons in windwos form and I want to set textBox1 to only accept numbers and the ".". Please help in how to achieve this. Thank you
Declare a string variable at form level, use it to store the last valid text and to restore it when an invalid text is entered on the TextChanged event of your textbox.
string previousText;
public Form1()
{
InitializeComponent();
previousText = String.Empty;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
int dummy, changeLenght, position;
if (!String.IsNullOrWhiteSpace(textBox1.Text) && !int.TryParse(textBox1.Text, out dummy))
{
position = textBox1.SelectionStart;
changeLenght = textBox1.TextLength - previousText.Length;
textBox1.Text = previousText;
textBox1.SelectionStart = position - changeLenght;
}
else
{
previousText = textBox1.Text;
}
}
position and changeLenght are used to keep the cursor where it was before restoring the text.
In case you want to accept numbers with decimals or something bigger than 2147483647, just change dummy to double and use double.TryParse instead of int.TryParse.
private void textBox1_TextChanged(object sender, EventArgs e)
{
int changeLenght, position;
double dummy;
if (!String.IsNullOrWhiteSpace(textBox1.Text) && !double.TryParse(textBox1.Text, out dummy))
{
...
}
}
Suppose button1 is your button control, you could do this:
private void allButtons_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
char c = btn.Text[0]; //assuming all buttons have exactly 1 character
if(Char.IsDigit(c) || c == '.')
{
//process
textBox1.Focus();
SendKeys.Send(btn.Text);
}
//otherwise don't
}
I'm assuming you put this in a common handler, to which you already wired all your buttons (i.e. allButtons_Click).
Problem with this approach, it allows you to type values like 0.0.1, which are most likely invalid in your context. Another way to handle this is to process TextChanged event, store previous value, and if new value is invalid, restore the old one. Unfortunately, TextBox class does not have TextChanging event, which could be a cleaner option.
The benefit of you determining the invalid value is modularity. For example, if you later decide your user can enter any value, but only numbers can pass validation, you could move your check from TextChanged to Validate button click or similar.
Why users may want that - suppose one of the options for input is copy/paste - they want to paste invalid data and edit it to become valid, for example abc123.5. If you limit them at the entry, this value will not be there at all, so they now need to manually paste into Notepad, cut out in the invalid characters, and paste again, which goes against productivity.
Generally, before implementing any user interface limitation, read "I won't allow my user to...", think well, whether it's justified enough. More often than not, you don't need to limit the user, even for the good purpose of keeping your DB valid etc. If possible, never put a concrete wall in front of them, you just need to guide them correctly through your workflow. You want users on your side, not against you.
I have a TextBox control. After pressing space, I want, instead of whitespace, to put "|". This is my code:
void TextBox1KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Space)
{
textBox1.AppendText("|");
}
}
Problem is it doesn't write only "|", but "| ": After the pipe char, it puts a space and the cursor moves after that space. I tried to use this method:
textBox1.Text = textBox1.Text.Substring(0, (textBox1.TextLength - 1));
but it doesn't work because it deletes "|" instead of the space.
And another question is: I want to disable inserting " " when Space is pressed when textbox is empty. When u want to press space while textbox is empty, nothing happens, textbox will stay empty and cursor stay at the begining of textbox
i try this
void TextBox1KeyDown(object sender, KeyEventArgs e)
{
if (textBox1.Text.Length==0 && e.KeyCode == Keys.Space) {
textBox1.Text=string.Empty;
}
}
It doesnt work cause same reason like my previous question. That event is handled after " " is already added so textbox is not empty
PS: sorry for my english and thanks to whoever edit my post and fix my grammatical and spellig errors
Instead of KeyPress handle your requirement in the KeyDown event
void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Space && e.Modifiers == Keys.None)
{
e.SuppressKeyPress = true;
textBox1.AppendText("|");
}
}
As noted below from DrewMcGowen, this will add always the pipe at the end of the textbox text. If you move the cursor somewhere inside the current text the behavior of this approach is confusing and probably incorrect.
This code instead tries to place the pipe exactly where the cursor is
void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Space && e.Modifiers == Keys.None)
{
e.SuppressKeyPress = true;
int pos = textBox1.SelectionStart;
textBox1.Text = textBox1.Text.Substring(0, pos) + "|" + textBox1.Text.Substring(pos);
textBox1.SelectionStart = pos + 1;
}
}
Notice also that a check on the value of the Modifiers property of the KeyEventArgs parameter is mandatory. For example ALT+SPACE should activate the System Menu and not change your textbox in any way (see comment below from Mr HansPassant). Checking for Keys.None will avoid this logic also for CTRL and SHIFT modifiers, if you want these modifiers to be accounted for you need to change that check.
The OnKeyPress event is fired before the space is added.
The workflow is thus:
You press down [Space];
The event is fired adding | to the content; and
The space event itself is handled adding a space to the content.
You need to use KeyRelease or KeyUp...
Documentation says:
Use the KeyChar property to sample keystrokes at run time and to modify keystrokes under special run-time circumstances. For example, you can use KeyChar to disable non-numeric keypresses when the user enters a ZIP code, change all alphabetical keypresses to uppercase in a data entry field, or monitor the keyboard or other key input device for specific key combinations.
So all you need is
if (e.KeyChar == ' ')
{
e.KeyChar = '|';
}
You forgot e.Handled = true; to suppress the space.
Monkeying with the user input is rather unwise. It is very disorienting and plain just doesn't work in some cases. Obvious failure modes are the user typing Ctrl+V or using right-click + Paste to insert text. Do this correctly with the Validating event:
private void textBox1_Validating(object sender, CancelEventArgs e) {
textBox1.Text = textBox1.Text.Replace(' ', '|');
}
With high odds that you want to further improve this code by checking for two || next to each other or a leading or trailing |. You can set e.Cancel = true when you're unhappy, use ErrorProvider to give the user hints.
I have a block of c# code on a TextChanged event for a winform textbox. Several of the voids called have messageboxes attached to them so the operator knows if they have valid data. Unfortunately, these calls get skipped completely. I have called the form in question with show() instead of showdialog() to eliminate the form being modal. Still no soap. The event is triggered by a barcode scanner. Code is as follows:
private void txtScanCode_TextChanged(object sender, EventArgs e)
{
string barCode;
barCode = txtScanCode.Text;
if (txtScanCode.Text.Length == 12)
{
MessageBox.Show(this, "Hey, look!", "A message box!",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
FindScanItem(barCode);
barCode = "";
txtScanCode.SelectionStart = 0;
txtScanCode.SelectionLength = txtScanCode.Text.Length;
}
}
I suspect it's a combination of text changed and keypress, but not really sure how it should be triggered properly.
After a week and a half, I have the answer, tested and verified. TaW and BillRuhl were on the right track with Leave and KeyPress. When those did not work, I finally hit on the KeyUp event.
A little background. A generic keyboard wedge USB scanner automatically adds a carriage return that trimming "\r\n" or Environment.Newline() will not get rid of. After several tries using different combinations and keypress, I caught the app firing a form before closing it. The barcode scanner, unlike normal keyboard input or cutting and pasting, continues to send an enter key to anything that listens for it during an event. I know. Buggy. But if we fire on the keyup event instead, like so...
private void txtScanCode_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
e.SuppressKeyPress = true;
barCode = txtScanCode.Text.Trim().ToString();
if (!doDataStuff) //This boolean is instantiated as false
{
if (txtScanCode.Text.Length == 12)
{
doDataStuff = true; //boolean tells the app go run data functions.
MessageBox.Show(this, "Pop up worked!", "Cool!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
getData(barCode); //Data methods performed on the barcode
barCode = "";
txtScanCode.Focus();
txtScanCode.SelectionStart = 0;
txtScanCode.SelectionLength = txtScanCode.Text.Length;
}
}
}
}
...We look only for an enter key, validate on the length of the string (In this case, "==12" is essential for validation), and use KeyEventArgs to filter out Keys.Enter. Works perfectly with one caveat. KeyUp actually works on the form level, so it will fire on other text boxes as well. In this case, txtScanCode is the only one that has data-bound functions behind it, so all the validation is written to check against that control.
Thanks all for chiming in. I think we broke Google a couple of times trying to figure it out.
I just did a copy/paste test, and I think the problem may be in your if condition. If I copy more than 12 characters and paste it into the text box, the 'if' statement doesn't trigger.
This simple change seemed to fix that case:
if (textBox1.Text.Length >= 12)
{
MessageBox.Show(this, "Hey, look!", "A message box!",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
// the rest of your code here
// (you may want to do some additional validation
// on the text if it's more than 12 characters)
}
Try a different event...I have better luck with the Leave event than I do with the TextChanged event. So your method would look like:
private void txtScanCode_Leave(object sender, EventArgs e)
{
string barCode;
barCode = txtScanCode.Text;
if (txtScanCode.Text.Length == 12)
{
MessageBox.Show(this, "Hey, look!", "A message box!",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
FindScanItem(barCode);
barCode = "";
txtScanCode.SelectionStart = 0;
txtScanCode.SelectionLength = txtScanCode.Text.Length;
}
}
Don't forget to wire up the Leave event...
Hope that helps
Bill
Just put MessageBox.Show("ble"); and then MessageBox.Show("blu); and the "blu" will fire.
I have a TextBox control. I have set my KeyPress event of the TextBox so that the user is only allowed to enter digits:
private void txtbxRecurEveryXWeeks_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
}
But in addition to that I do not want the user to set the value of the TexBot to zero "0". But they still should be allowed to enter "10" or "3400" as the value. How can I achieve that?
It's probably best to ignore the keypress event and handle the lost focus event and check and ensure the value isn't 0 when the user is done typing.
EDIT: It was pointed out that the user could type "000" and lose focus which would cause this to fail. You can check and confirm the textbox has a value and parse it as an int to confirm it isn't 0.
private void txtbxRecurEveryXWeeks_LostFocus(object sender, EventArgs e)
{
int value;
if(!string.IsNullOrWhitespace(txtbxRecurEveryXWeeks.Text)
&& int.TryParse(txtbxRecurEveryXWeeks.Text, out value)
&& value > 0)
{
//Do something like clear the textbox value
}
}
In the assumption that you use winforms, consider using the NumericUpDown control to enter numbers. It has the Minimum property, which you could set to 1 to avoid zero input.
Use NumericUpDown with minimum value = 1 and hidden up and down buttons.
numericUpDown1.Minimum = 1;
numericUpDown1.Controls[0].Hide();
In my program I have a TextBox who's value must be set in a specific integer range. If it is not within this range, it should warn the user and then highlight the incorrect text inside of the TextBox for re-editing (implying that the user must enter a value that is in the correct range before they are allowed to leave the TextBox). How would I change my code so that it performs these operations?
This is what I have so far. I am using a TextChanged event. This code warns the user about the restriction breach and refocuses (I would like to highlight the value instead) on the TextBox, but does not prevent the user from clicking out of it afterward:
int maxRevSpeed;
//Max Rev Speed -- Text Changed
private void maxRevSpeed_textChanged(object sender, RoutedEventArgs e)
{
if (maxRevSpeed_textBox.Text == "" || maxRevSpeed_textBox.Text == " ")
maxRevSpeed = 0;
else
{
maxRevSpeed = Convert.ToInt32(maxRevSpeed_textBox.Text);
if (maxRevSpeed <= 0 || maxRevSpeed > 45)
{
MessageBox.Show("Reverse Sensor speed must be between 0 and 45 FPM", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
}
maxRevSpeed_textBox.Focus();
}
}
Please note that this question is a revisit of a former question of mine. I am aware that it may be "frowned upon" to take this approach to a TextBox, but regardless I would still like to figure out how to implement such a thing. Thank you.
Update 1:
After looking at everyone's suggestions I have updated my code:
//Max Rev Speed -- Text Changed
private void maxRevSpeed_textChanged(object sender, RoutedEventArgs e)
{
if (maxRevSpeed_textBox.Text == "" || maxRevSpeed_textBox.Text == " ") //Is Empty or contains spaces
maxRevSpeed = 0;
else if (!Regex.IsMatch(maxRevSpeed_textBox.Text, #"^[\p{N}]+$")) //Contains characters
maxRevSpeed = 0;
else
maxRevSpeed = Convert.ToInt32(maxRevSpeed_textBox.Text);
}
//Max Rev Speed -- Lost Focus
private void maxRevSpeed_LostFocus(object sender, RoutedEventArgs e)
{
if (maxRevSpeed <= 0 || maxRevSpeed > 45)
{
MessageBox.Show("Reverse Sensor speed must be between 0 and 45 FPM", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
//Supposed to highlight incorrect text -- DOES NOT WORK
maxRevSpeed_textBox.SelectionStart = 0;
maxRevSpeed_textBox.SelectionLength = maxRevSpeed_textBox.Text.Length;
}
}
The integer representing the text in the textBox is now dealt with in the textChanged event. The LostFocus event handles the warning and the re-selection of the incorrect text value. However, the highlight text method works when it is in the textChanged event, but not in it's current location. Why is that, and how can I fix it?
If you just want to stop focus from leaving a TextBox, all you need to do is to set the Handled property of the KeyboardFocusChangedEventArgs object to true in a PreviewLostKeyboardFocus handler when your invalid condition is true:
private void PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
e.Handled = IsInvalidValue;
}
This of course assumes that you have a property named IsInvalidValue that you set to true when the entered data is invalid and false otherwise.
You can prevent the user from entering the text or out of range by using PreviewTextInput handler of textbox, call it like this.
private void textBox1_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (!char.IsDigit(e.Text, e.Text.Length - 1))
{
e.Handled = true;
}
}
The code above is for entering numbers only, you can change it according to your requirements, hope it helps :)
Hi I suppose you are using C#, here you can find a relevant post: C# auto highlight text in a textbox control
As they stated the following code should select the text inside texbox
In Windows Forms and WPF:
maxRevSpeed_textBox.SelectionStart = 0;
maxRevSpeed_textBox.SelectionLength = textbox.Text.Length;