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.
Related
I'm currently trying to make an application (just for learning purposes to try to get used to C# because I'm kinda new) and I've wanted to create a sort of to say Terminal within the Form. I've decided to try to use a text-box with multiple lines and tried using if and else statements but when I go into the text box and start typing it immediately goes to the error message that I set up for 'else' after every keystroke. I don't know what it is but I feel like I'm missing something. Any suggestions? Also, would it be possible to create my own "commands" for that application alone in itself? I'm talking about like when you type in lets say "program_speech" it will come up with a dialog asking for user input and it will basically convert text to speech with the built in Speech Synthesizer for Windows. Thanks! All help is appreciated!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Terminator //Lol Terminator Reference
{
public partial class Form1 : Form
{
private string answer;
public Form1()
{
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (answer == "help")
{
MessageBox.Show("There is only 2 commands as of now and that is 'help' and 'program_speech' ");
}
else if (answer == "program_speech")
{
MessageBox.Show("Still currently under creation");
}
else
{
MessageBox.Show("Invalid Command. Please try again or type help for current available commands");
}
}
}
}
At every keystroke an event called TextChanged is raised, it goes to else condition of 'Invalid Command' because the text in that textbox at that time is neither "help" nor "program_speech". Using TextChanged is definitely not recommended.
You should use a button and its click event to check the value of textbox. Because that's the only way you can be sure that all the required text is written. It would be something like -
private void btnCheckText_Click(object sender, EventArgs e)
{
answer = textBox1.Text;
if (answer == "help")
{
MessageBox.Show("There is only 2 commands as of now and that is 'help' and 'program_speech' ");
}
else if (answer == "program_speech")
{
MessageBox.Show("Still currently under creation");
}
else
{
MessageBox.Show("Invalid Command. Please try again or type help for current available commands");
}
}
Better make a Enter Button and read in the text from the textbox, after pressing the enter button
private void Button1_Enter(object sender, EventArgs e)
{
input = textbox.Text;
//then do a switch case
Initialize answer to textbox1.text. I am assuming you have achieved it somehow. If not #Kishor's answer is the way you should do it.
This is happening because your textBox1_TextChanged will get fired every time there is even a single change in your textbox. So when you type in any letter the textbox text changes and the function is fired thus triggering your else statement. For example you type h, ==> Textbox registers the change and calls textBox1_TextChanged and since the text is not help if goes in the else part. This is repeated till hel till u completely type in help.
If you try when your textbox finally reads help it will follow the MessageBox.Show("There is only 2 commands as of now and that is 'help' and 'program_speech' "); command you specified.
As per the dialogue thing you will need to create a new form and call it when you want. Also as u mentioned you are i will recommend watching this tutorial. I know it is outdated but it covers most of your doubts. I started with it and I think so should you.
Also I don't think a multiple line textbox is the best choice when you want to make a terminal like structure. Hope I cleared most of your doubts.
I've read answer here.
Cause problem is already found. As text change event is being fired on every change of Textbox's text change.
Two good working suggestion here mentioned,
To use exclusive Button and perform logic on Button's click
To use Textbox's Lost Focus event.
Both approach require user to leave Textbox ultimately. (so he would need to re-enter in terminal (textbox) if he wants to enter another command.
But here I wonder why nobody have suggested to track Enter press and do the logic only if Enter key being hit. Here user will not have to leave terminal (textbox) and fire another command without much effort.
you can do it like below.
First, use Textbox's key Up event, it will be fired later then Key Down (so to be sure that input is properly entered in textbox)
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
answer = textBox1.Text;
if (answer == "help")
{
MessageBox.Show("There is only 2 commands as of now and that is 'help' and 'program_speech' ");
}
else if (answer == "program_speech")
{
MessageBox.Show("Still currently under creation");
}
else
{
MessageBox.Show("Invalid Command. Please try again or type help for current available commands");
}
}
}
Alright,
I think I've found the problem.
The string variable named "answer", is it where the command entered by the user should be stored ?
Because in your code, nothing mentions it,
so try to add this line at the beginning of text_changed void :
answer = textBox1.Text;
If you're new to C#, this means you take the property Text of textBox1 and you store it in answer.
Hope it works !
You have to make sure, you are initializing the value of answer variable with the value of TextBox and change the event from TextChanged to LostFocus
private void textBox1_LostFocus(object sender, EventArgs e)
{
answer = textBox1.Text;
if (answer == "help")
{
MessageBox.Show("There is only 2 commands as of now and that is 'help' and 'program_speech' ");
}
else if (answer == "program_speech")
{
MessageBox.Show("Still currently under creation");
}
else
{
MessageBox.Show("Invalid Command. Please try again or type help for current available commands");
}
}
I have a winforms program containing a RichTextBox.
The user inputs the text into the RichTextBox.
I wish to receive the input through keyboard events and not through textBox1.Text property, validate the string and only display it in the RichTextBox later.
How can I prevent the RichTextBox from displaying the input text by the user, even though the user inputs the text into the RichTextBox?
The RichTextBox is selected and has focus.
I am sorry. I just wanted to simplify the issue and therefore I neglected to mention that it is not a TextBox but a RichTextBox. It turns out that it matters, as the proposed solution is based on the PassowrdChar property, which is not natively supported by RichTextBox. I do not wish to create an inherited class for a property which is not even being used as such, only to suppress displaying the user input at input time.
You can actually use the KeyDown event. By doing that, you have an ability to validate the user input.
Tutorial
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
//
// Detect the KeyEventArg's key enumerated constant.
//
if (e.KeyCode == Keys.Enter)
{
MessageBox.Show("You pressed enter! Good job!");
}
else if (e.KeyCode == Keys.Escape)
{
MessageBox.Show("You pressed escape! What's wrong?");
}
}
With that said, you have to store user input in string variable, validate it through the event and only then set variable value in textbox.
You can use this:
private void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
char c = e.KeyChar;
// ..
// handle the character as needed
// ..
e.Handled = true; // suppress the RTB from receiving it
}
Note that you may or may not want to treat mouse events like right mouseclicks to control inserting via the mouse..
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..
I have four text boxes in my winform, and I've already ordered their tab index sequentially. Also, I set their TabStop properties as true. But when I press Tab key while in filling my first textbox, it does not move to next one. For that, I even added the following part for each of them in the code:
firstTextbox.KeyDown += (sender, args) =>
{
if(args.KeyCode == Keys.Tab)
{
firstTextbox.SelectNextControl(this, true, true, true, true);
}
}
But this didn't help either. Any suggestion?
Responding to tab buttons is handled by the message loop. If you're running the form as modal, or are calling
Application.Run(myForm);
then you've got a message loop. If you're only doing
Form myForm = new Form();
myForm.Visible = true;
Then you do not have a message loop and therefore tab navigation won't work. (If you are not running the form modally, then try using the ShowDialog() method to show the form, and see if tabbing works in this case.)
If this is your issue, then this MSDN article below suggests that you either
Run each Form in its own thread (so that you can call Application.Run(myForm) on it). Running each form in its own thread is a huge can of worms and should not be undertaken by the faint of heart (especially if you have preexisting or poorly designed forms).
Show the dialog modally.
I've had some success with a horrible hack of setting KeyPreview on the form to true and then listening for System.Windows.Forms.Keys.Tab within the Form.OnKeyDown method (and setting KeyEventArgs.SuppressKeyPress and KeyEventArgs.Handled to true if I do handle it). (Also remember to check the KeyEventArgs.Modifiers property to see if the user is doing a [Shift]+[Tab].) The downside of this is that you rob the Control that has a focus on the opportunity to respond to the keypress since Form.KeyPreview causes the Form to get a chance to handle the key before the Control gets a chance. (I'm also not sure what would happen if you implemented this logic and had the message loop going.)
As far as what you should do when you detect the Tab Key, check out the Control.SelectNextControl function. I've been calling it like...
e.SuppressKeyPress = SelectNextControl(
ActiveControl, //Current Control
true, //Move Forward? (You want false for a Shift-Tab to go backward.)
true, //Only stop at controls where Control.TabStop == true?
true, //Consider controls nested within other controls?
true); //Wrap to the beginning of the form if you reach the end?
A person who is smarter than me might be able to set up a shared message loop or something else, but this is all I've figured out so far.
The only way I was able to fire textBox1_KeyDown with the Tab key was by overriding IsInputKey method.
class TabTextBox : TextBox
{
protected override bool IsInputKey(Keys keyData)
{
if (keyData == Keys.Tab)
{
return true;
}
else
{
return base.IsInputKey(keyData);
}
}
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyData == Keys.Tab)
{
this.SelectedText = " ";
}
else
{
base.OnKeyDown(e);
}
}
and then modify InitializeComponent():
private void InitializeComponent()
{
...
this.textBox1 = new TabTextBox();
...
}
Forms.Control.isInputKey
Every control in windows forms application have property
this.button1.TabIndex = 3;
you can use it to select next control if you order it correctly.
If your textboxes are multiline you need to set the AcceptsTab property to false.
Perhaps your event handler is not being registered. Make sure textboxes are not ReadOnly=true, TabStop=false. Try this
public Form1()
{
InitializeComponent();
this.textBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyDown);
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab)
{
textBox1.SelectNextControl(sender as Control, true, true, true, true);
}
}
I ran into a similar problem with tab order completely ignored. After two hours of digging I finally found my dumb mistake: "If mybutton.Focus Then ..." when I meant "If myButton.Focused Then...". Oops. Figured I'd share in case anyone else has this experience too.
I don't know if it is called an argument (i.e. textbox1.text = "Hello";).
I have a control and there is a text box in it. It has a dropdown box that opens when the text is changed. But when I update the text in the text box that box drops down.
I need a way to make it so it only drops down if someone manually does it.
TBAddressBar.ABText.Text = getCurrentBrowser().Source.ToString();
and
public void ABText_TextChanged(object sender, TextChangedEventArgs e)
{
if (sender == 1*)
{
ABDropDown.Visibility = Visibility.Visible;
}
else
{
ABDropDown.Visibility = Visibility.Collapsed;
}
}
If someone manually does it, presumably they are using keypresses to do so. In that case, use KeyDown or KeyUp events to show the dropdown instead.
What I have done in the past is use a boolean variable that I set when I update my textboxes programically to bypass the TextChangedEvent.
i.e.
bool loading;
....
loading =true;
TBAddressBar.ABText.Text = getCurrentBrowser().Source.ToString();
loading = false;
public void ABText_TextChanged(object sender, TextChangedEventArgs e)
{
if(loading) return;
....
}
Simple, just remove the code from your TextChanged Event.
Anyway you got the basic idea.. Now do your dropdown logic in KeyPress event, since it accepts only characters and not the modifiers. So it behaves closer to your requirement. Not that you cant handle the same using KeyDown and KeyUp, you can, but more code..