Forms, basic calculator key triggering problem - c#

private void UserInputText_KeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyCode == Keys.D4 && e.Modifiers == Keys.Shift) || (e.KeyCode == Keys.Add))
{
if (String.IsNullOrEmpty(UserInputText.Text))
{
MessageBox.Show("Bir sayı giriniz.");
UserInputText.Clear();
return;
}
if (double.TryParse(UserInputText.Text, out sayı1))
{
CalculationResultText.Text = sayı1 + " + ";
islem = "+";
UserInputText.Clear();
}
else
{
MessageBox.Show("Sadece sayı değeri girebilirsiniz.");
UserInputText.Clear();
}
}
}
I am coding a basic forms calculator. I am trying to trigger addition function and clear the textbox when textbox is focused and user presses "+" key. "if (String.IsNullOrEmpty(UserInputText.Text)) and else conditions work well. But if no Message boxes shows up as in the
if (double.TryParse(UserInputText.Text, out sayı1)) condition, the "+" character remains in the textbox as in the image. Thanks for help.

If I understand correctly, you want to first check the character that was typed in and if it's incorrect then you want to prevent this character from appearing?
If so, then you need to set e.Handled = true property when you want to prevent it.
This call tells the GUI element (your TextBox) that "I did all the checks for this event (i.e. KeyDown event), and I don't want you to contribute in handling of this event (i.e. normally the TextBox would try to add this character to its Text property, but you prevent it)".
Check out documentation on KeyEventArgs.Handled.

KeyPress event enables you to prevent any further changes in the TextBox.
You can do that thanks to Handled property of KeyPressEventArgs
private void UserInputText_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == '+')
{
UserInputText.Clear();
e.Handled = true;
}
}

Related

WPF how to manage ENTER hit on TextBox for messaging purpose

Take a simple messaging program, such as Steam friend conversation.
When you hit ENTER, the message is sent, and the message field is emptied.
When you enter CTRL/SHIFT + ENTER a newline is created. If your cursor is not at the end of the input text, then all the text appearing after your cursor will be sent to a newline.
Well, how do you accomplish such a feat ?
Furthermore, I'd like to know how to have the aforementioned features and also how to still be able to paste a multiline text into the message field.
For now, this is my code. It's something but does not get all the job done :
private bool ctrlOrShift = false;
private void MessageField_KeyDown( object sender, KeyEventArgs e )
{
if( e.Key == Key.LeftCtrl || e.Key == Key.LeftShift )
{
ctrlOrShift = true;
}
else if( e.Key == Key.Enter && ctrlOrShift != true && !MessageField.AcceptsReturn )
{
AsyncSendMessage();
}
else if( e.Key == Key.Enter && ctrlOrShift != true && MessageField.AcceptsReturn )
{
MessageField.AcceptsReturn = false;
}
else if( e.Key == Key.Enter && ctrlOrShift == true )
{
ctrlOrShift = false;
MessageField.AcceptsReturn = true;
MessageField.Text += System.Environment.NewLine;
MessageField.Select( MessageField.Text.Length, 0 );
MessageField.AcceptsReturn = false;
}
else
{
ctrlOrShift = false; // Canceled because follow-up key wat not ENTER !
}
}
The following scenarios occur :
Using CTR or SHIFT, I can create a new line in my TextBox :) ;
I cannot paste a multiline text from the Clipboard: only the first line will be pasted, nothing else :( ;
If I use CTRL + V to paste content, the MessageField_KeyDown event takes the CTRL hit is taken into account, therefore, if I press ENTER, message is not sent but a newline is created instead :/ (in a case where you would paste a content and send it right away) ;
If my cursor position is before the end of the input text, CTR/SHIT + ENTER will create a newline at the end of the text regardless of the cursor position :/
So, how can I tweak this code ? Thanks for the help !
The Result of the Solution is this:
Normal
After one SHIFT + ENTER
When you push ENTER it looks like in Normal only without text in the box
As mentioned in the comments you could use the AcceptsReturn and TextWrapping properties for a multiline textbox (like in steam).
Use Height = Auto for a better looking one (otherwise you only have one line and all other lines disappear)
XAML
for Textbox:
<TextBox HorizontalAlignment="Left" Height="Auto" Margin="10,10,0,0"
TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top"
Width="497" AcceptsReturn="True"
KeyDown="TextBoxKeyDown" PreviewKeyDown="TextBoxPreviewKeyDown"/>
Event Handler:
This is not that easy as i thought first :'D But i figured it out.
When you use the AcceptsReturn Property the Enter Key is Handeled by the AcceptsReturn. So if you push enter you will see a new line instead of a Send() if you programm is like this:
private void TextBoxKeyDown(object sender, KeyEventArgs e)
{
var textbox = sender as TextBox;
// This will never happen because the Enter Key is handeled before
// That means TextBoxKeyDown is not triggered for the Enter key
if (e.Key == Key.Enter &&
!(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) &&
!(Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.LeftShift)))
{
// Send(textBox.Text)
textbox.Text = "";
}
}
So you need to implement the PreviewKeyDown eventhandler. Because in the PreviewKeyDown event handler the Event is routed through the (Parent)Elements.
Look at this Answer
Also note the e.Handled = true line. Otherwise the Enter is routed through the method to the AcceptsReturn and you will have 2 lines after the enter, but the Textbox is empty.
With this method the KeyDown Method is no longer needed!
private void TextBoxPreviewKeyDown(object sender, KeyEventArgs e)
{
// Enter key is routed and the PreviewKeyDown is also fired with the
// Enter key
var textbox = sender as TextBox;
// You don't want to clear the box when CTRL and/or SHIFT is down
if (e.Key == Key.Enter &&
!(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) &&
!(Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)))
{
textbox.Text = "";
e.Handled = true;
}
}
The pros of the Multiline Textbox is that you can copy and paste
+ you have no problems with CTRL pushed or not.
What do you think about it?
Hope it helps

Using backspace to move back to previous textBox (C#)

This may be a simple question. I'm new to C# (and most programming) and I am trying to make a program that consists of two text boxes. The information in these textboxes will frequently be deleted and new information will need entered, so it needs to be quick. For convenience I'm trying to make the backspace key refocus on the previous textbox rather than using Shift+Space or clicking. Here is what I have. The program runs, but the code below doesn't seem to do what I intend it to do.
if (e.KeyCode == Keys.Back && textBox2.TextLength == 0)
textBox1.Focus();
So, when textbox2 has 0 characters and backspace is subsequently keyed, I would like it to move back to textbox1. Thanks for any help.
So to make this work you're going to need to make sure you run this code on KeyUp, but you also do not need multiple KeyUp handlers to do this. Consider this KeyUp handler:
private void textBox_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
{
var textBox = sender as TextBox;
if (textBox == null) { return; }
if (e.KeyCode == Keys.Back && textBox.Text.Length == 0)
{
// this here of course being the Form
// Select causes the form to select the previous control in the tab order
this.Select(true, false);
}
}
Now just attach this handler to all text boxes that you want to behave this way and they'll all work.
I did get it to work finally. What I did wasn't too different than what I was trying before, but here is how I did it.
I created two text boxes from the .cs [Design] view.
I selected each box and clicked the "Events" lightning bolt icon under Properties. This is something I left out previously when this didn't work.
I set both of them to KeyPress and TextChanged (i.e. textBox1_KeyPress & textBox1_TextChanged (Did the same thing with textBox2). I don't know if this is part of the reason why it worked. I'm just documenting my actions.
I double clicked each textBox, which created an EventArgs for each. This is where I stored my regular code.
In addition to the EventArgs I manually created a KeyEventArgs (see below) where I put the function for the Backspace. Here is the code:
// Here is the KeyEventArgs I created using KeyPress (Public).
public void textBox2_KeyPress(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Back && textBox2.Text.Length == 0)
textBox1.Focus();
}
// Here is where the rest of my code (Private).
private void textBox2_TextChanged(object sender, EventArgs e)
{
if (textBox2.Text == "A")
richTextBox3.Text = "January";
if (textBox2.Text == "B")
richTextBox3.Text = "February";
if (textBox2.Text == "C")
richTextBox3.Text = "March";
// Code Continues...
Sorry if this isn't clear. I just wanted to document what I did in case it helps someone later. Thanks for the help everyone.

Restrict numbers and letters in textbox - C#

I want to restrict what numbers and letters can be entered into a textbox. Let's say I only want to allow numbers 0-5 and letters a-d (both lower and uppercase).
I already tried using a masked text box but it only let me specify numbers only, letters only (both without restriction) or numbers and letters together but in a particular order.
Best scenario would be: user tries to enter number 6 and nothing gets entered into the textbox, same for letters outside the range a-f.
I think the best event to use would be the Keypress event, but I am at a loss as to how I can achieve the restriction thing.
Use the KeyPress Event for your textbox.
protected void myTextBox_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs)
{
e.Handled = !IsValidCharacter(e.KeyChar);
}
private bool IsValidCharacter(char c)
{
bool isValid = true;
// put your logic here to define which characters are valid
return isValid;
}
// Boolean flag used to determine when a character other than a number is entered.
private bool nonNumberEntered = false;
// Handle the KeyDown event to determine the type of character entered into the control.
private void textBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
// Initialize the flag to false.
nonNumberEntered = false;
// Determine whether the keystroke is a number from the top of the keyboard.
if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
{
// Determine whether the keystroke is a number from the keypad.
if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
{
// Determine whether the keystroke is a backspace.
if(e.KeyCode != Keys.Back)
{
// A non-numerical keystroke was pressed.
// Set the flag to true and evaluate in KeyPress event.
nonNumberEntered = true;
}
}
}
//If shift key was pressed, it's not a number.
if (Control.ModifierKeys == Keys.Shift) {
nonNumberEntered = true;
}
}
// This event occurs after the KeyDown event and can be used to prevent
// characters from entering the control.
private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
// Check for the flag being set in the KeyDown event.
if (nonNumberEntered == true)
{
// Stop the character from being entered into the control since it is non-numerical.
e.Handled = true;
}
}
Override the PreviewKeyDownEvent like this:
private void textBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.A || e.KeyCode == Keys.B || ...)
e.IsInputKey = true;
else
e.IsInputKey = false;
}
This will tell the textBox which keys it will consider as a user input or not.
Use the KeyDown event and if the e.Key is not in your allowable set, then just e.Handled = true.
An alternative would be accept all input, validate it and then provide useful feedback to the user, for example an error label asking them to enter data within a certain range. I prefer this method as the user knows something went wrong and can fix it. It is used throughout the web on web forms and would be not at all surprising for a user of your app. Pressing a key and getting no response at all might be confusing!
http://en.wikipedia.org/wiki/Principle_of_least_astonishment
The Keypress event is probably your best bet. Do a check there if the entered char is not the char you want, set e.SuppressKey to true to make sure the KeyPress event is not fired, and the char is not added to the textbox.
If you are using ASP.NET Web Forms a regular expression validation would be the easiest. In MVC, a jQuery library such as MaskedEdit would be a good place to start. The answers above document the Windows forms approach well.

Detect Key in KeyUp event

I have a textbox on a form where I'm trying to detect the keys the user types in. The TextBox is multilined with wordwrap on. I don't want the user the press the enter key (as I want all text entered on ONE line, wrapped) so I used the following code:
private void txtPlain_KeyPress(object sender, KeyPressEventArgs e) {
if (e.KeyChar == (char)13) {
MessageBox.Show("Enter keys are not allowed");
e.KeyChar = (char)0;
}
}
This worked fine in my tests, but when I tested for CTRL+ENTER it didn't work as I'm not sure how to detect for the control key. From my googling I found that I need to use the KeyUp/Down events so I now have the following Code:
private void txtPlain_KeyUp(object sender, KeyEventArgs e) {
//if (e.KeyData == (Keys.Control | Keys.Enter)) {
if (e.KeyCode == Keys.Enter || (e.KeyCode == Keys.Enter && e.Control)) {
MessageBox.Show("Enter keys are not allowed:");
//e.KeyValue = Keys.None;
}
}
The first commented out line didn't work for some reason so if anyone could explain why this would be useful.
The problem with the KeyUp/Down event is that I don't know how to REMOVE the enter key from the text - unlike the KeyPress event when I can set the KeyChar to zero. The event captures both the Enter and Ctrl+Enter keys, but the cursor still goes to the next line in the TextBox.
Thanks for any help on this.
Hmm, there's no reason to disallow the Enter key by handling the KeyDown or KeyUp events. You can simply set the AcceptsReturn property of the textbox control to False. This will prevent a multiline textbox from responding to a press of the Enter key.
Of course, this doesn't solve the problem of Ctrl+Enter. In fact, that's the expected way to create a new line when the AcceptsReturn property is set to False. To solve that, you will need to handle one of the keyboard events and prevent the control from receiving this input.
KeyDown is a good place to start. What you want to do is filter out any keyboard events that include the Keys.Enter flag. That will catch them no matter which other modifier key they might be combined with. Then, once you've found an Enter keypress, you want to set the e.Handled property to True in order to prevent it from being passed on to the control.
But unfortunately, we're not quite done yet. The textbox control tries to handle certain keys internally, and you're not going to be able to override that in a key event handler method. You also need to tell the control not to interpret that particular key as an input key. There are two primary ways of doing this. The first (and recommended way) is to inherit from the base TextBox class to create your own custom control, and then override the protected IsInputKey method. The second (somewhat simpler) way is just to handle the PreviewKeyDown event, and set the IsInputKey property to False.
Sample code:
private void txtPlain_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
// Check if the KeyCode value has the Keys.Enter flag set
if ((e.KeyCode & Keys.Enter) == Keys.Enter)
{
// Set the IsInputKey property to False
e.IsInputKey = false;
}
}
private void txtPlain_KeyDown(object sender, KeyEventArgs e)
{
// Check if the KeyCode value has the Keys.Enter flag set
if ((e.KeyCode & Keys.Enter) == Keys.Enter)
{
// Show the user a message
MessageBox.Show("Enter keys are not allowed in this textbox.");
// Prevent the key event from being passed on to the control
e.Handled = true;
}
}
And, though I assume this is for testing purposes only, you definitely want to take that MessageBox call out of there for production code. Find another way to alert the user that their input was not allowed, such as a short beep sound and an ErrorProvider component placed next to the textbox. Showing a message box is very jarring, and not very user-friendly. See my answer here for other hints and tips.
private void txtPlain_KeyUp(object sender, KeyEventArgs e) {
//if (e.KeyData == (Keys.Control | Keys.Enter)) {
if (e.KeyCode == Keys.Enter || (e.KeyCode == Keys.Enter && e.Control)) {
MessageBox.Show("Enter keys are not allowed:");
//e.KeyValue = Keys.None;
// mark event as handled
e.Handled = true;
}
}
from msdnlink
edit:
I think that you need the key down event not the key up
EDIT2
here is some tested code and it works as you wanted:
bool invalid=false;
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyCode & Keys.Enter) == Keys.Enter)
{
invalid = true;
}
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (invalid)
{
e.Handled = true;
}
invalid = false;
}
The first commented out line didn't work for some reason so if anyone could explain why this would be useful.
You wanted to detect Ctrl + Enter.
if (e.KeyData == (Keys.Control | Keys.Enter)) {..
Keys.Control and Key.Enter are nothing but are some values please refer . Now doing logical or will not necessarily result to key which has been pressed. Totally illogical clause.
Ok now come to your actual problem you want to detect Enter stroke and Ctrl + Enter stroke to be treated as same.
Besides you want to undo the newline character thats been introduced. Try
PreviewKeyDown or Preview key up eventhandler with the following condition
if(e.KeyCode==Keys.Enter)
Let me know if this works

how to make a multiline textbox not accept Enter and Backspace

I have a multiline textbox which shouldn't accept alphabets, numbers, newline(enter key) and backspace. In short, the textbox.Text shouldn't be editable. But I do want the textbox to accept two shortcut keys - control and control+R. One way I can make the textbox un-editable is by making it read-only. But then the textbox wont accept any keystroke at all. In short, my shortcuts ( control and control+R) wont work( Control + R) with read-only method.
Can anyone help in this regard. That's all I have to do.
One thing I could do here is not to make the textbox read-only and then restrict the characters(alphabets and digits) that could be inputted in the textbox. With this code:
private void txtResult_KeyPress(object sender, KeyPressEventArgs e)
{
// only modifier keys, escape, enter, backspace etc is accepted now
e.Handled = !char.IsControl(e.KeyChar);
}
private void txtResult_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control == true)
{
if (e.KeyCode == Keys.R)
{
// do something
}
else
{
//do something
}
}
if (e.KeyCode == Keys.Escape)
{
//do something
}
}
With this technique I can get the shortcuts(control and control+R) working. But the trouble with this method is that Enter and Backspace keys work as well making it possible to edit the text of textbox. How can I specifically restrict Enter and Backspace key being registered from the textbox, but let Control and Escape??
did you try SuppressKeyPress = true ?
private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control == true)
{
if (e.KeyCode == Keys.R)
{
// do something
}
else
{
//do something
}
}
else
e.SuppressKeyPress = true;
}
Since you are handling the keys in the KeyDown event handler, why not have your KeyPress handler return that all keystrokes are handled?
So just set e.Handled = true no matter what. I believe the backspace and enter would be interpreted as control characters, also.
The Enter and Backspace keys won't work if the textbox is set to ReadOnly, as you suggested early on in the question that you had done. Make sure the property is still set to true. You can either set it in the Properties window, or through code like so:
myTextBox.ReadOnly = true;
Then, you need to handle the KeyDown event for the textbox control, and watch for the specific keys that you're interested in. Something like this:
private void myTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control)
{
if (e.KeyCode == Keys.R)
{
MessageBox.Show("Pressed Ctrl+R");
}
else
{
MessageBox.Show("Pressed Ctrl");
}
}
else if (e.KeyCode == Keys.Escape)
{
MessageBox.Show("Pressed Esc");
}
}
This works exactly as expected, as long as the textbox is set to read-only. No other keys are recognized, and the user cannot change or modify any of the text in the textbox. You don't need to suppress the keypresses, as the control is already doing that when you set it to read-only. You also don't need to handle both the KeyDown and KeyPress events. KeyPress won't work for you anyway, as it doesn't let you handle control characters.

Categories

Resources