I need to determine whether a key, when it is pressed, will change the control's text or not; I need to ignore key presses like Ctrl+Z or Esc, but I need to know which key was pressed if the text changed.
Is there any way to know that in the KeyDown event? Currently, I'm using a flag, set on KeyDown and checked on TextChanged, but I was wondering if there is a better way?
You're looking for Char.IsControl
private Keys lastKey = Keys.None;
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
lastKey = e.KeyData;
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (Char.IsControl(e.KeyChar))
{
e.Handled = true;//prevent this key press
Keys pressedKey = this.lastKey;
//Do your stuff with pressedKey here
}
}
You could catch the KeyPress event on the text box and if it is a valid key you would set e.handled = false and if it was a bad key you would set e.handled = true.
example from: here
private void keypressed(Object o, KeyPressEventArgs e)
{
// The keypressed method uses the KeyChar property to check
// whether the ENTER key is pressed.
// If the ENTER key is pressed, the Handled property is set to true,
// to indicate the event is handled.
if (e.KeyChar == (char)Keys.Return)
{
e.Handled = true;
}
}
There are some keys which produce a Control char but they also change the text, for example BackSpace. They have another difficulty: if the textbox is empty, pressing them (for example BackSpace) doesn't change the text; so it breaks the previous rule. So Control characters are not naive to deal with and build a rule upon.
Moreover, consider Ctrl + C or Shift + Insert or similar cases. The 'C' key is somehow seductive; it is like pressing 'C' changes the text but if it was pressed with 'Ctrl', it actually didn't change the text. We should check the Modifiers.
Perhaps you can find other difficulties to deal with and I think the flag approach is good enough.
Related
How to do the event handling when the user presses the ENTER key or leaves the focus on the particular textbox? I tried for KeyChanged event, but it will keep updating the number instead of only once when complete.
private void txtNumber_TextChanged(object sender, EventArgs e)
{
txtNumber.Text = double.Parse(txtNumber.Text).ToString("F2");
}
There are a few issues with the posted code. One issue is that doing the formatting each time the user “types” a character is going to be awkward for the user. In addition, if the user presses the “Enter” key, the event txtNumber_TextChanged is not going to fire. I assume you may already know this.
Next, when getting input from users, it is imperative that you check the input for valid numbers BEFORE calling the parse method…Example, the line of code…
double.Parse(txtNumber.Text).ToString("F2");
Will FAIL and crash the program if the text in the text box… txtNumber.Text is NOT a valid double.
You should always assume the user is going to make a mistake and you don’t want your code to crash when they do.
Therefore I suggest using the double.TryPasre method to avoid these possible crashes, calling this method will NEVER throw an exception and will make validating the number easier.
To get what you want I recommend you wire up three (3) events for the text box…
The Leave event, this is used to format the text, when the user leaves the text box, like when they click on another control.
Next is the PreviewKeyDown event, this is used when the user presses the “Enter” key.
And one extra event to help the user ONLY add numbers and one dot. The KeyPressed event is wired up and will ignore any pressed keys that are not numbers or the dot (period). Also, it will only allow one period, if the user tries to add a second decimal place, it will be ignored.
Bear in mind, the key pressed event helps by preventing the user from “typing” alpha text into the text box… however, the user can still paste text. Fortunately, since we are using the TryParse method, when the pasted text is an invalid number, the try parse will simply return “0.00” and NOT crash the code.
private void txtNumber_Leave(object sender, EventArgs e) {
double.TryParse(txtNumber.Text.Trim(), out double number);
txtNumber.Text = number.ToString("F2");
}
private void txtNumber_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) {
if (e.KeyCode == Keys.Enter) {
double.TryParse(txtNumber.Text.Trim(), out double number);
txtNumber.Text = number.ToString("F2");
}
}
private void txtNumber_KeyPress(object sender, KeyPressEventArgs e) {
if (!char.IsControl(e.KeyChar) // <- key pressed is not a control key
&& !char.IsDigit(e.KeyChar) // <- key pressed is not a digit (number)
&& e.KeyChar != '.') { // <- key pressed is not a dot (.)
e.Handled = true; // <- if its not a control key, digit or dot... then ignore it
}
// only allow one decimal point - if there is already a dot, then ignore the second one
if (e.KeyChar == '.' && txtNumber.Text.IndexOf('.') > -1) {
e.Handled = true; // <- if there is already a dot in the text... then ignore it
}
}
Formatting a text value in a TextBox must be done once the input is already done.
TextChanged, occurs when the Text property value changes. So this is not ideal.
The only event you can rely on.
LostFocus, occurs when the control loses focus. You can sheck some info when control change focus.
private void textBox1_LostFocus(object sender, System.EventArgs e)
{
// Code here
}
Sometimes we wanted the format to be changed once we click something on the keyboard, so here are the possible events for that.
The non-character keys do raise the KeyDown and KeyUp events.
KeyDown, occurs when a key is pressed while the control has focus.
KeyUp, occurs when a key is released while the control has focus.
KeyPress, occurs when a character. space or backspace key is pressed while the control has focus.
Note: When using the KeyPress you need to also consider if the Form is the one handling the input events first or not, check the Remarks here.
private void textBox1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
{
if (e.KeyCode == Keys.Return) // You can also use: e.KeyValue == 13
{
// Do your code here
}
};
How can I replace pressed 'decimal point' key from numpad to always return '.' independent of regional setting. I want that works only for one (specific) TextBox not all in application.
It's possible to accomplished this without creating own control?
This is a possible solution (most possibly not the best one, but one that should work) that would add a . character to a textbox if the decimal key on the numpad is pressed, if the , key is pressed it still adds the , character to the textbox.
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Decimal)
{
e.SuppressKeyPress = true;
textBox1.Text += ".";
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.SelectionLength = 0;
}
}
The SuppressKeyPress prevents that the pressed key is sent to the textbox. Then you add the desired character to the textbox. The SelectionStart and SelectionLength properties are set to move the cursor to the end of the string in the textbox.
Hope that helps
EDIT:
As cdkMoose pointed out the flaw with this approach is that the .character is always added to the end of the string, if it is desired to add the .character anywhere in the string the code could be used like this:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Decimal)
{
e.SuppressKeyPress = true;
var caretPosition = textBox1.SelectionStart;
textBox1.Text.Insert(caretPosition , ".");
textBox1.SelectionStart = caretPosition + 1;
textBox1.SelectionLength = 0;
}
}
In order to do this, you simply need to handle the KeyDown event, supress the activated key if its the numpad decimal, and then simply send the new key you want.
It's pretty straightforward, the following links should give you enough pointers to actually write some code:
Keys
Control.KeyDown
KeyEventArgs
SendKeys
Once you've written something, you can ask a new question about any specific dificulties you might encounter.
Look at this.
You can handle KeyDown event and if is , on numpad cancel event and send new with '.'.
When the user enters a character with the TextBox in focus, I do not want the character to show up on the TextBox at all and I don't want to use the Clear() method as there may be other text in the TextBox I don't want erased. so far I've tried:
private void WriteBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13) // enter key pressed
{
WriteBox1.Text = "";
}
// Code to write Serial....
String writeValues = WriteBox1.Text;
String withoutLast = writeValues.Substring(0, 1);
WriteBox1.Text = withoutLast;
}
This leaves the last letter entered in writeBox1. I need it to delete all characters entered.
I've also tired:
writeValues.Replace(writeValues, "");
WriteBox1.Text = writeValues;
Try setting Handled property on eventargs. Set Handled to true to cancel the KeyPress event. This keeps the control from processing the key press.
example :
private void keypressed(Object o, KeyPressEventArgs e)
{
// The keypressed method uses the KeyChar property to check
// whether the ENTER key is pressed.
// If the ENTER key is pressed, the Handled property is set to true,
// to indicate the event is handled.
if (e.KeyChar == (char)Keys.Return)
{
e.Handled = true;
}
}
https://msdn.microsoft.com/ru-ru/library/system.windows.forms.keypresseventargs.handled%28v=vs.110%29.aspx
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
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.